diff options
Diffstat (limited to 'drivers/net/phy/microchip_t1.c')
-rw-r--r-- | drivers/net/phy/microchip_t1.c | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c index 8569a545e0a3..a838b61cd844 100644 --- a/drivers/net/phy/microchip_t1.c +++ b/drivers/net/phy/microchip_t1.c @@ -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 }, @@ -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 }, @@ -397,7 +427,7 @@ 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); @@ -405,21 +435,28 @@ static int lan87xx_phy_init(struct phy_device *phydev) 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); } @@ -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: @@ -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) |