diff options
Diffstat (limited to 'target/linux/generic/backport-5.15/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch')
-rw-r--r-- | target/linux/generic/backport-5.15/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.15/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch b/target/linux/generic/backport-5.15/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch new file mode 100644 index 0000000000..f2c9a7e53d --- /dev/null +++ b/target/linux/generic/backport-5.15/729-19-v6.3-net-ethernet-mtk_eth_soc-introduce-mtk_hw_warm_reset.patch @@ -0,0 +1,107 @@ +From: Lorenzo Bianconi <lorenzo@kernel.org> +Date: Sat, 14 Jan 2023 18:01:29 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: introduce mtk_hw_warm_reset + support + +Introduce mtk_hw_warm_reset utility routine. This is a preliminary patch +to align reset procedure to vendor sdk and avoid to power down the chip +during hw reset. + +Reviewed-by: Leon Romanovsky <leonro@nvidia.com> +Tested-by: Daniel Golle <daniel@makrotopia.org> +Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com> +Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com> +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +--- + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3220,7 +3220,54 @@ static void mtk_hw_reset(struct mtk_eth + 0x3ffffff); + } + +-static int mtk_hw_init(struct mtk_eth *eth) ++static u32 mtk_hw_reset_read(struct mtk_eth *eth) ++{ ++ u32 val; ++ ++ regmap_read(eth->ethsys, ETHSYS_RSTCTRL, &val); ++ return val; ++} ++ ++static void mtk_hw_warm_reset(struct mtk_eth *eth) ++{ ++ u32 rst_mask, val; ++ ++ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, RSTCTRL_FE, ++ RSTCTRL_FE); ++ if (readx_poll_timeout_atomic(mtk_hw_reset_read, eth, val, ++ val & RSTCTRL_FE, 1, 1000)) { ++ dev_err(eth->dev, "warm reset failed\n"); ++ mtk_hw_reset(eth); ++ return; ++ } ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0_V2; ++ else ++ rst_mask = RSTCTRL_ETH | RSTCTRL_PPE0; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSTCTRL_PPE1)) ++ rst_mask |= RSTCTRL_PPE1; ++ ++ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, rst_mask); ++ ++ udelay(1); ++ val = mtk_hw_reset_read(eth); ++ if (!(val & rst_mask)) ++ dev_err(eth->dev, "warm reset stage0 failed %08x (%08x)\n", ++ val, rst_mask); ++ ++ rst_mask |= RSTCTRL_FE; ++ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, rst_mask, ~rst_mask); ++ ++ udelay(1); ++ val = mtk_hw_reset_read(eth); ++ if (val & rst_mask) ++ dev_err(eth->dev, "warm reset stage1 failed %08x (%08x)\n", ++ val, rst_mask); ++} ++ ++static int mtk_hw_init(struct mtk_eth *eth, bool reset) + { + u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | + ETHSYS_DMA_AG_MAP_PPE; +@@ -3259,7 +3306,12 @@ static int mtk_hw_init(struct mtk_eth *e + return 0; + } + +- mtk_hw_reset(eth); ++ msleep(100); ++ ++ if (reset) ++ mtk_hw_warm_reset(eth); ++ else ++ mtk_hw_reset(eth); + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + /* Set FE to PDMAv2 if necessary */ +@@ -3464,7 +3516,7 @@ static void mtk_pending_work(struct work + if (eth->dev->pins) + pinctrl_select_state(eth->dev->pins->p, + eth->dev->pins->default_state); +- mtk_hw_init(eth); ++ mtk_hw_init(eth, true); + + /* restart DMA and enable IRQs */ + for (i = 0; i < MTK_MAC_COUNT; i++) { +@@ -4056,7 +4108,7 @@ static int mtk_probe(struct platform_dev + eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); + INIT_WORK(ð->pending_work, mtk_pending_work); + +- err = mtk_hw_init(eth); ++ err = mtk_hw_init(eth, false); + if (err) + goto err_wed_exit; + |