b79afccd4c82b3cf4f1cb9413d731025ad78b5d2
[openwrt/openwrt.git] /
1 From 7ff82416de8295c61423ef6fd75f052d3837d2f7 Mon Sep 17 00:00:00 2001
2 From: Alexander Couzens <lynxis@fe80.eu>
3 Date: Wed, 1 Feb 2023 19:23:29 +0100
4 Subject: [PATCH] net: mediatek: sgmii: ensure the SGMII PHY is powered down on
5 configuration
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 The code expect the PHY to be in power down which is only true after reset.
11 Allow changes of the SGMII parameters more than once.
12
13 Only power down when reconfiguring to avoid bouncing the link when there's
14 no reason to - based on code from Russell King.
15
16 There are cases when the SGMII_PHYA_PWD register contains 0x9 which
17 prevents SGMII from working. The SGMII still shows link but no traffic
18 can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
19 taken from a good working state of the SGMII interface.
20
21 Fixes: 42c03844e93d ("net-next: mediatek: add support for MediaTek MT7622 SoC")
22 Suggested-by: Russell King (Oracle) <linux@armlinux.org.uk>
23 Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
24 [ bmork: rebased and squashed into one patch ]
25 Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
26 Signed-off-by: Bjørn Mork <bjorn@mork.no>
27 Acked-by: Daniel Golle <daniel@makrotopia.org>
28 Tested-by: Daniel Golle <daniel@makrotopia.org>
29 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
30 ---
31 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++
32 drivers/net/ethernet/mediatek/mtk_sgmii.c | 39 +++++++++++++++------
33 2 files changed, 30 insertions(+), 11 deletions(-)
34
35 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
36 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
37 @@ -1027,11 +1027,13 @@ struct mtk_soc_data {
38 * @regmap: The register map pointing at the range used to setup
39 * SGMII modes
40 * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
41 + * @interface: Currently configured interface mode
42 * @pcs: Phylink PCS structure
43 */
44 struct mtk_pcs {
45 struct regmap *regmap;
46 u32 ana_rgc3;
47 + phy_interface_t interface;
48 struct phylink_pcs pcs;
49 };
50
51 --- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
52 +++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
53 @@ -24,6 +24,10 @@ static int mtk_pcs_setup_mode_an(struct
54 {
55 unsigned int val;
56
57 + regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
58 + val &= ~RG_PHY_SPEED_MASK;
59 + regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
60 +
61 /* Setup the link timer and QPHY power up inside SGMIISYS */
62 regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
63 SGMII_LINK_TIMER_DEFAULT);
64 @@ -36,9 +40,6 @@ static int mtk_pcs_setup_mode_an(struct
65 val |= SGMII_AN_RESTART;
66 regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
67
68 - regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
69 - val &= ~SGMII_PHYA_PWD;
70 - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
71
72 return 0;
73
74 @@ -69,11 +70,6 @@ static int mtk_pcs_setup_mode_force(stru
75 val |= SGMII_SPEED_1000;
76 regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
77
78 - /* Release PHYA power down state */
79 - regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
80 - val &= ~SGMII_PHYA_PWD;
81 - regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
82 -
83 return 0;
84 }
85
86 @@ -85,12 +81,32 @@ static int mtk_pcs_config(struct phylink
87 struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
88 int err = 0;
89
90 + if (mpcs->interface != interface) {
91 + /* PHYA power down */
92 + regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
93 + SGMII_PHYA_PWD, SGMII_PHYA_PWD);
94 +
95 + mpcs->interface = interface;
96 + }
97 +
98 /* Setup SGMIISYS with the determined property */
99 if (interface != PHY_INTERFACE_MODE_SGMII)
100 err = mtk_pcs_setup_mode_force(mpcs, interface);
101 else if (phylink_autoneg_inband(mode))
102 err = mtk_pcs_setup_mode_an(mpcs);
103
104 + /* Release PHYA power down state
105 + * Only removing bit SGMII_PHYA_PWD isn't enough.
106 + * There are cases when the SGMII_PHYA_PWD register contains 0x9 which
107 + * prevents SGMII from working. The SGMII still shows link but no traffic
108 + * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
109 + * taken from a good working state of the SGMII interface.
110 + * Unknown how much the QPHY needs but it is racy without a sleep.
111 + * Tested on mt7622 & mt7986.
112 + */
113 + usleep_range(50, 100);
114 + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
115 +
116 return err;
117 }
118
119 @@ -145,6 +161,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
120 return PTR_ERR(ss->pcs[i].regmap);
121
122 ss->pcs[i].pcs.ops = &mtk_pcs_ops;
123 + ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
124 }
125
126 return 0;