Commit 9983a2c9 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'fixes-for-mtk_eth_soc'

Bjørn Mork says:

====================
Fix mtk_eth_soc sgmii configuration.

This has been tested on a MT7986 with a Maxlinear GPY211C phy
permanently attached to the second SoC mac.
====================

Link: https://lore.kernel.org/r/20230201182331.943411-1-bjorn@mork.noSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b0de13d3 3337a6e0
...@@ -519,7 +519,7 @@ ...@@ -519,7 +519,7 @@
#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) #define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) #define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) #define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
#define SGMII_DUPLEX_FULL BIT(4) #define SGMII_DUPLEX_HALF BIT(4)
#define SGMII_IF_MODE_BIT5 BIT(5) #define SGMII_IF_MODE_BIT5 BIT(5)
#define SGMII_REMOTE_FAULT_DIS BIT(8) #define SGMII_REMOTE_FAULT_DIS BIT(8)
#define SGMII_CODE_SYNC_SET_VAL BIT(9) #define SGMII_CODE_SYNC_SET_VAL BIT(9)
...@@ -1036,11 +1036,13 @@ struct mtk_soc_data { ...@@ -1036,11 +1036,13 @@ struct mtk_soc_data {
* @regmap: The register map pointing at the range used to setup * @regmap: The register map pointing at the range used to setup
* SGMII modes * SGMII modes
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
* @interface: Currently configured interface mode
* @pcs: Phylink PCS structure * @pcs: Phylink PCS structure
*/ */
struct mtk_pcs { struct mtk_pcs {
struct regmap *regmap; struct regmap *regmap;
u32 ana_rgc3; u32 ana_rgc3;
phy_interface_t interface;
struct phylink_pcs pcs; struct phylink_pcs pcs;
}; };
......
...@@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ...@@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
int advertise, link_timer; int advertise, link_timer;
bool changed, use_an; bool changed, use_an;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
rgc3 = RG_PHY_SPEED_3_125G;
else
rgc3 = 0;
advertise = phylink_mii_c22_pcs_encode_advertisement(interface, advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
advertising); advertising);
if (advertise < 0) if (advertise < 0)
...@@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ...@@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
bmcr = 0; bmcr = 0;
} }
/* Configure the underlying interface speed */ if (mpcs->interface != interface) {
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3, /* PHYA power down */
RG_PHY_SPEED_3_125G, rgc3); regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
if (interface == PHY_INTERFACE_MODE_2500BASEX)
rgc3 = RG_PHY_SPEED_3_125G;
else
rgc3 = 0;
/* Configure the underlying interface speed */
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
RG_PHY_SPEED_3_125G, rgc3);
mpcs->interface = interface;
}
/* Update the advertisement, noting whether it has changed */ /* Update the advertisement, noting whether it has changed */
regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
...@@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ...@@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr); SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
/* Release PHYA power down state */ /* Release PHYA power down state
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, * Only removing bit SGMII_PHYA_PWD isn't enough.
SGMII_PHYA_PWD, 0); * 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 changed; return changed;
} }
...@@ -138,11 +154,11 @@ static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ...@@ -138,11 +154,11 @@ static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
else else
sgm_mode = SGMII_SPEED_1000; sgm_mode = SGMII_SPEED_1000;
if (duplex == DUPLEX_FULL) if (duplex != DUPLEX_FULL)
sgm_mode |= SGMII_DUPLEX_FULL; sgm_mode |= SGMII_DUPLEX_HALF;
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
SGMII_DUPLEX_FULL | SGMII_SPEED_MASK, SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
sgm_mode); sgm_mode);
} }
} }
...@@ -171,6 +187,8 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) ...@@ -171,6 +187,8 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
return PTR_ERR(ss->pcs[i].regmap); return PTR_ERR(ss->pcs[i].regmap);
ss->pcs[i].pcs.ops = &mtk_pcs_ops; ss->pcs[i].pcs.ops = &mtk_pcs_ops;
ss->pcs[i].pcs.poll = true;
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment