summaryrefslogtreecommitdiff
path: root/drivers/net/phy/microchip_t1.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/microchip_t1.c')
-rw-r--r--drivers/net/phy/microchip_t1.c70
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)