|
|
@@ -0,0 +1,126 @@
|
|
|
+From 7ff82416de8295c61423ef6fd75f052d3837d2f7 Mon Sep 17 00:00:00 2001
|
|
|
+From: Alexander Couzens <[email protected]>
|
|
|
+Date: Wed, 1 Feb 2023 19:23:29 +0100
|
|
|
+Subject: [PATCH] net: mediatek: sgmii: ensure the SGMII PHY is powered down on
|
|
|
+ configuration
|
|
|
+MIME-Version: 1.0
|
|
|
+Content-Type: text/plain; charset=UTF-8
|
|
|
+Content-Transfer-Encoding: 8bit
|
|
|
+
|
|
|
+The code expect the PHY to be in power down which is only true after reset.
|
|
|
+Allow changes of the SGMII parameters more than once.
|
|
|
+
|
|
|
+Only power down when reconfiguring to avoid bouncing the link when there's
|
|
|
+no reason to - based on code from Russell King.
|
|
|
+
|
|
|
+There are cases when the SGMII_PHYA_PWD register contains 0x9 which
|
|
|
+prevents SGMII from working. The SGMII still shows link but no traffic
|
|
|
+can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
|
|
|
+taken from a good working state of the SGMII interface.
|
|
|
+
|
|
|
+Fixes: 42c03844e93d ("net-next: mediatek: add support for MediaTek MT7622 SoC")
|
|
|
+Suggested-by: Russell King (Oracle) <[email protected]>
|
|
|
+Signed-off-by: Alexander Couzens <[email protected]>
|
|
|
+[ bmork: rebased and squashed into one patch ]
|
|
|
+Reviewed-by: Russell King (Oracle) <[email protected]>
|
|
|
+Signed-off-by: Bjørn Mork <[email protected]>
|
|
|
+Acked-by: Daniel Golle <[email protected]>
|
|
|
+Tested-by: Daniel Golle <[email protected]>
|
|
|
+Signed-off-by: Jakub Kicinski <[email protected]>
|
|
|
+---
|
|
|
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++
|
|
|
+ drivers/net/ethernet/mediatek/mtk_sgmii.c | 39 +++++++++++++++------
|
|
|
+ 2 files changed, 30 insertions(+), 11 deletions(-)
|
|
|
+
|
|
|
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
|
|
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
|
|
+@@ -1027,11 +1027,13 @@ struct mtk_soc_data {
|
|
|
+ * @regmap: The register map pointing at the range used to setup
|
|
|
+ * SGMII modes
|
|
|
+ * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
|
|
|
++ * @interface: Currently configured interface mode
|
|
|
+ * @pcs: Phylink PCS structure
|
|
|
+ */
|
|
|
+ struct mtk_pcs {
|
|
|
+ struct regmap *regmap;
|
|
|
+ u32 ana_rgc3;
|
|
|
++ phy_interface_t interface;
|
|
|
+ struct phylink_pcs pcs;
|
|
|
+ };
|
|
|
+
|
|
|
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
|
|
|
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
|
|
|
+@@ -24,6 +24,10 @@ static int mtk_pcs_setup_mode_an(struct
|
|
|
+ {
|
|
|
+ unsigned int val;
|
|
|
+
|
|
|
++ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
|
|
|
++ val &= ~RG_PHY_SPEED_MASK;
|
|
|
++ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
|
|
|
++
|
|
|
+ /* Setup the link timer and QPHY power up inside SGMIISYS */
|
|
|
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
|
|
|
+ SGMII_LINK_TIMER_DEFAULT);
|
|
|
+@@ -36,9 +40,6 @@ static int mtk_pcs_setup_mode_an(struct
|
|
|
+ val |= SGMII_AN_RESTART;
|
|
|
+ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
|
|
|
+
|
|
|
+- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
|
|
|
+- val &= ~SGMII_PHYA_PWD;
|
|
|
+- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+@@ -69,11 +70,6 @@ static int mtk_pcs_setup_mode_force(stru
|
|
|
+ val |= SGMII_SPEED_1000;
|
|
|
+ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
|
|
|
+
|
|
|
+- /* Release PHYA power down state */
|
|
|
+- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
|
|
|
+- val &= ~SGMII_PHYA_PWD;
|
|
|
+- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
|
|
|
+-
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -85,12 +81,32 @@ static int mtk_pcs_config(struct phylink
|
|
|
+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
++ if (mpcs->interface != interface) {
|
|
|
++ /* PHYA power down */
|
|
|
++ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
|
|
|
++ SGMII_PHYA_PWD, SGMII_PHYA_PWD);
|
|
|
++
|
|
|
++ mpcs->interface = interface;
|
|
|
++ }
|
|
|
++
|
|
|
+ /* Setup SGMIISYS with the determined property */
|
|
|
+ if (interface != PHY_INTERFACE_MODE_SGMII)
|
|
|
+ err = mtk_pcs_setup_mode_force(mpcs, interface);
|
|
|
+ else if (phylink_autoneg_inband(mode))
|
|
|
+ err = mtk_pcs_setup_mode_an(mpcs);
|
|
|
+
|
|
|
++ /* Release PHYA power down state
|
|
|
++ * Only removing bit SGMII_PHYA_PWD isn't enough.
|
|
|
++ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which
|
|
|
++ * prevents SGMII from working. The SGMII still shows link but no traffic
|
|
|
++ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
|
|
|
++ * taken from a good working state of the SGMII interface.
|
|
|
++ * Unknown how much the QPHY needs but it is racy without a sleep.
|
|
|
++ * Tested on mt7622 & mt7986.
|
|
|
++ */
|
|
|
++ usleep_range(50, 100);
|
|
|
++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
|
|
|
++
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -145,6 +161,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
|
|
|
+ return PTR_ERR(ss->pcs[i].regmap);
|
|
|
+
|
|
|
+ ss->pcs[i].pcs.ops = &mtk_pcs_ops;
|
|
|
++ ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|