mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 18:13:04 +00:00
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.no Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
9983a2c986
@ -519,7 +519,7 @@
|
||||
#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
|
||||
#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
|
||||
#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_REMOTE_FAULT_DIS BIT(8)
|
||||
#define SGMII_CODE_SYNC_SET_VAL BIT(9)
|
||||
@ -1036,11 +1036,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;
|
||||
};
|
||||
|
||||
|
@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
int advertise, link_timer;
|
||||
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,
|
||||
advertising);
|
||||
if (advertise < 0)
|
||||
@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
bmcr = 0;
|
||||
}
|
||||
|
||||
/* Configure the underlying interface speed */
|
||||
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
|
||||
RG_PHY_SPEED_3_125G, rgc3);
|
||||
if (mpcs->interface != interface) {
|
||||
/* PHYA power down */
|
||||
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 */
|
||||
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,
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
|
||||
SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
|
||||
|
||||
/* Release PHYA power down state */
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
|
||||
SGMII_PHYA_PWD, 0);
|
||||
/* 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 changed;
|
||||
}
|
||||
@ -138,11 +154,11 @@ static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
|
||||
else
|
||||
sgm_mode = SGMII_SPEED_1000;
|
||||
|
||||
if (duplex == DUPLEX_FULL)
|
||||
sgm_mode |= SGMII_DUPLEX_FULL;
|
||||
if (duplex != DUPLEX_FULL)
|
||||
sgm_mode |= SGMII_DUPLEX_HALF;
|
||||
|
||||
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
|
||||
SGMII_DUPLEX_FULL | SGMII_SPEED_MASK,
|
||||
SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
|
||||
sgm_mode);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
ss->pcs[i].pcs.ops = &mtk_pcs_ops;
|
||||
ss->pcs[i].pcs.poll = true;
|
||||
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user