Skip to content

Commit

Permalink
net: phy: microchip: run phy initialization during each link update
Browse files Browse the repository at this point in the history
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 <rakesh.sankaranarayanan@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20230120104733.724701-1-rakesh.sankaranarayanan@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Rakesh Sankaranarayanan authored and Jakub Kicinski committed Jan 24, 2023
1 parent 90e05ef commit d7bf56e
Showing 1 changed file with 56 additions and 14 deletions.
70 changes: 56 additions & 14 deletions drivers/net/phy/microchip_t1.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,15 +245,42 @@ static int lan87xx_config_rgmii_delay(struct phy_device *phydev)
PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, rc);
}

static int lan87xx_phy_init_cmd(struct phy_device *phydev,
const struct access_ereg_val *cmd_seq, int cnt)
{
int ret, i;

for (i = 0; i < cnt; i++) {
if (cmd_seq[i].mode == PHYACC_ATTR_MODE_POLL &&
cmd_seq[i].bank == PHYACC_ATTR_BANK_SMI) {
ret = access_smi_poll_timeout(phydev,
cmd_seq[i].offset,
cmd_seq[i].val,
cmd_seq[i].mask);
} else {
ret = access_ereg(phydev, cmd_seq[i].mode,
cmd_seq[i].bank, cmd_seq[i].offset,
cmd_seq[i].val);
}
if (ret < 0)
return ret;
}

return ret;
}

static int lan87xx_phy_init(struct phy_device *phydev)
{
static const struct access_ereg_val init[] = {
static const struct access_ereg_val hw_init[] = {
/* TXPD/TXAMP6 Configs */
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE,
T1_AFE_PORT_CFG1_REG, 0x002D, 0 },
/* HW_Init Hi and Force_ED */
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
T1_POWER_DOWN_CONTROL_REG, 0x0308, 0 },
};

static const struct access_ereg_val slave_init[] = {
/* Equalizer Full Duplex Freeze - T1 Slave */
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
T1_EQ_FD_STG1_FRZ_CFG, 0x0002, 0 },
Expand All @@ -267,6 +294,9 @@ static int lan87xx_phy_init(struct phy_device *phydev)
T1_EQ_WT_FD_LCK_FRZ_CFG, 0x0002, 0 },
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
T1_PST_EQ_LCK_STG1_FRZ_CFG, 0x0002, 0 },
};

static const struct access_ereg_val phy_init[] = {
/* Slave Full Duplex Multi Configs */
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
T1_SLV_FD_MULT_CFG_REG, 0x0D53, 0 },
Expand Down Expand Up @@ -397,29 +427,36 @@ static int lan87xx_phy_init(struct phy_device *phydev)
{ PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
T1_POWER_DOWN_CONTROL_REG, 0x0300, 0 },
};
int rc, i;
int rc;

/* phy Soft reset */
rc = genphy_soft_reset(phydev);
if (rc < 0)
return rc;

/* PHY Initialization */
for (i = 0; i < ARRAY_SIZE(init); i++) {
if (init[i].mode == PHYACC_ATTR_MODE_POLL &&
init[i].bank == PHYACC_ATTR_BANK_SMI) {
rc = access_smi_poll_timeout(phydev,
init[i].offset,
init[i].val,
init[i].mask);
} else {
rc = access_ereg(phydev, init[i].mode, init[i].bank,
init[i].offset, init[i].val);
}
rc = lan87xx_phy_init_cmd(phydev, hw_init, ARRAY_SIZE(hw_init));
if (rc < 0)
return rc;

rc = genphy_read_master_slave(phydev);
if (rc)
return rc;

/* The following squence needs to run only if phydev is in
* slave mode.
*/
if (phydev->master_slave_state == MASTER_SLAVE_STATE_SLAVE) {
rc = lan87xx_phy_init_cmd(phydev, slave_init,
ARRAY_SIZE(slave_init));
if (rc < 0)
return rc;
}

rc = lan87xx_phy_init_cmd(phydev, phy_init, ARRAY_SIZE(phy_init));
if (rc < 0)
return rc;

return lan87xx_config_rgmii_delay(phydev);
}

Expand Down Expand Up @@ -775,6 +812,7 @@ static int lan87xx_read_status(struct phy_device *phydev)
static int lan87xx_config_aneg(struct phy_device *phydev)
{
u16 ctl = 0;
int ret;

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

return phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl);
ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl);
if (ret == 1)
return phy_init_hw(phydev);

return ret;
}

static int lan87xx_get_sqi(struct phy_device *phydev)
Expand Down

0 comments on commit d7bf56e

Please sign in to comment.