2023-02-14 23:25:19 +00:00
|
|
|
From 7ff82416de8295c61423ef6fd75f052d3837d2f7 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Alexander Couzens <lynxis@fe80.eu>
|
|
|
|
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) <linux@armlinux.org.uk>
|
|
|
|
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
|
|
|
|
[ bmork: rebased and squashed into one patch ]
|
|
|
|
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
|
|
|
Signed-off-by: Bjørn Mork <bjorn@mork.no>
|
|
|
|
Acked-by: Daniel Golle <daniel@makrotopia.org>
|
|
|
|
Tested-by: Daniel Golle <daniel@makrotopia.org>
|
|
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
|
|
---
|
|
|
|
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
|
2023-03-04 16:57:46 +00:00
|
|
|
@@ -1062,11 +1062,13 @@ struct mtk_soc_data {
|
2023-02-14 23:25:19 +00:00
|
|
|
* @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;
|