Skip to content

Commit d7bf56e

Browse files
Rakesh Sankaranarayanankuba-moo
authored andcommitted
net: phy: microchip: run phy initialization during each link update
PHY initialization is supposed to run on every mode changes. "lan87xx_config_aneg()" verifies every mode change using "phy_modify_changed()" function. Earlier code had phy_modify_changed() followed by genphy_soft_reset. But soft_reset resets all the pre-configured register values to default state, and lost all the initialization done. With this reason gen_phy_reset was removed. But it need to go through init sequence each time the mode changed. Update lan87xx_config_aneg() to invoke phy_init once successful mode update is detected. PHY init sequence added in lan87xx_phy_init() have slave init commands executed every time. Update the init sequence to run slave init only if phydev is in slave mode. Test setup contains LAN9370 EVB connected to SAMA5D3 (Running DSA), and issue can be reproduced by connecting link to any of the available ports after SAMA5D3 boot-up. With this issue, port will fail to update link state. But once the SAMA5D3 is reset with LAN9370 link in connected state itself, on boot-up link state will be reported as UP. But Again after some time, if link is moved to DOWN state, it will not get reported. Signed-off-by: Rakesh Sankaranarayanan <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 90e05ef commit d7bf56e

File tree

1 file changed

+56
-14
lines changed

1 file changed

+56
-14
lines changed

drivers/net/phy/microchip_t1.c

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,42 @@ static int lan87xx_config_rgmii_delay(struct phy_device *phydev)
245245
PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, rc);
246246
}
247247

248+
static int lan87xx_phy_init_cmd(struct phy_device *phydev,
249+
const struct access_ereg_val *cmd_seq, int cnt)
250+
{
251+
int ret, i;
252+
253+
for (i = 0; i < cnt; i++) {
254+
if (cmd_seq[i].mode == PHYACC_ATTR_MODE_POLL &&
255+
cmd_seq[i].bank == PHYACC_ATTR_BANK_SMI) {
256+
ret = access_smi_poll_timeout(phydev,
257+
cmd_seq[i].offset,
258+
cmd_seq[i].val,
259+
cmd_seq[i].mask);
260+
} else {
261+
ret = access_ereg(phydev, cmd_seq[i].mode,
262+
cmd_seq[i].bank, cmd_seq[i].offset,
263+
cmd_seq[i].val);
264+
}
265+
if (ret < 0)
266+
return ret;
267+
}
268+
269+
return ret;
270+
}
271+
248272
static int lan87xx_phy_init(struct phy_device *phydev)
249273
{
250-
static const struct access_ereg_val init[] = {
274+
static const struct access_ereg_val hw_init[] = {
251275
/* TXPD/TXAMP6 Configs */
252276
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE,
253277
T1_AFE_PORT_CFG1_REG, 0x002D, 0 },
254278
/* HW_Init Hi and Force_ED */
255279
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
256280
T1_POWER_DOWN_CONTROL_REG, 0x0308, 0 },
281+
};
282+
283+
static const struct access_ereg_val slave_init[] = {
257284
/* Equalizer Full Duplex Freeze - T1 Slave */
258285
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
259286
T1_EQ_FD_STG1_FRZ_CFG, 0x0002, 0 },
@@ -267,6 +294,9 @@ static int lan87xx_phy_init(struct phy_device *phydev)
267294
T1_EQ_WT_FD_LCK_FRZ_CFG, 0x0002, 0 },
268295
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
269296
T1_PST_EQ_LCK_STG1_FRZ_CFG, 0x0002, 0 },
297+
};
298+
299+
static const struct access_ereg_val phy_init[] = {
270300
/* Slave Full Duplex Multi Configs */
271301
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
272302
T1_SLV_FD_MULT_CFG_REG, 0x0D53, 0 },
@@ -397,29 +427,36 @@ static int lan87xx_phy_init(struct phy_device *phydev)
397427
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
398428
T1_POWER_DOWN_CONTROL_REG, 0x0300, 0 },
399429
};
400-
int rc, i;
430+
int rc;
401431

402432
/* phy Soft reset */
403433
rc = genphy_soft_reset(phydev);
404434
if (rc < 0)
405435
return rc;
406436

407437
/* PHY Initialization */
408-
for (i = 0; i < ARRAY_SIZE(init); i++) {
409-
if (init[i].mode == PHYACC_ATTR_MODE_POLL &&
410-
init[i].bank == PHYACC_ATTR_BANK_SMI) {
411-
rc = access_smi_poll_timeout(phydev,
412-
init[i].offset,
413-
init[i].val,
414-
init[i].mask);
415-
} else {
416-
rc = access_ereg(phydev, init[i].mode, init[i].bank,
417-
init[i].offset, init[i].val);
418-
}
438+
rc = lan87xx_phy_init_cmd(phydev, hw_init, ARRAY_SIZE(hw_init));
439+
if (rc < 0)
440+
return rc;
441+
442+
rc = genphy_read_master_slave(phydev);
443+
if (rc)
444+
return rc;
445+
446+
/* The following squence needs to run only if phydev is in
447+
* slave mode.
448+
*/
449+
if (phydev->master_slave_state == MASTER_SLAVE_STATE_SLAVE) {
450+
rc = lan87xx_phy_init_cmd(phydev, slave_init,
451+
ARRAY_SIZE(slave_init));
419452
if (rc < 0)
420453
return rc;
421454
}
422455

456+
rc = lan87xx_phy_init_cmd(phydev, phy_init, ARRAY_SIZE(phy_init));
457+
if (rc < 0)
458+
return rc;
459+
423460
return lan87xx_config_rgmii_delay(phydev);
424461
}
425462

@@ -775,6 +812,7 @@ static int lan87xx_read_status(struct phy_device *phydev)
775812
static int lan87xx_config_aneg(struct phy_device *phydev)
776813
{
777814
u16 ctl = 0;
815+
int ret;
778816

779817
switch (phydev->master_slave_set) {
780818
case MASTER_SLAVE_CFG_MASTER_FORCE:
@@ -790,7 +828,11 @@ static int lan87xx_config_aneg(struct phy_device *phydev)
790828
return -EOPNOTSUPP;
791829
}
792830

793-
return phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl);
831+
ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl);
832+
if (ret == 1)
833+
return phy_init_hw(phydev);
834+
835+
return ret;
794836
}
795837

796838
static int lan87xx_get_sqi(struct phy_device *phydev)

0 commit comments

Comments
 (0)