
Some devices, when configured in bootstrap to 'no cpu' mode require PHY manual reset to get them operational and responding to reading their ID registers.
Without this step - the PHYLIB probing will fail.
In more details - the bootstrap configuration from switch must be read. The value of CONFIG Data1 (0x71) of Scratch and Misc register is read to check if 'no_cpu' and 'addr4' bits were set.
Signed-off-by: Lukasz Majewski lukma@denx.de
---
drivers/net/phy/mv88e61xx.c | 63 +++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c index 325d5b56135f..1fa821ca162b 100644 --- a/drivers/net/phy/mv88e61xx.c +++ b/drivers/net/phy/mv88e61xx.c @@ -202,6 +202,17 @@ struct mv88e61xx_phy_priv { u8 phy_ctrl1_en_det_width; /* Width of 'EDet' bit field */ u8 phy_ctrl1_en_det_ctrl; /* 'EDet' control value */ u8 direct_access; /* Access switch device directly */ + /* + * Bootstrap configuration: + * + * If addr4 = 1 device is accessible from 0x10 address on MDIO bus. + */ + u8 addr4; + /* + * If no_cpu = 1 switch is automatically setup, otherwise PHY reset is + * required from CPU for normal operation. + */ + u8 no_cpu; };
static inline int smi_cmd(int cmd, int addr, int reg) @@ -1235,6 +1246,33 @@ int phy_mv88e61xx_init(void) return 0; }
+static int mv88e61xx_read_bootstrap(struct phy_device *phydev) +{ + struct mv88e61xx_phy_priv *priv = phydev->priv; + struct mii_dev *mdio_bus = priv->mdio_bus; + int val; + + /* mv88e6020 - ID = 0x0200 (REG 3 on non PHY port) */ + if (priv->id == PORT_SWITCH_ID_6020) { + /* Prepare to read scratch and misc register */ + mdio_bus->write(mdio_bus, priv->global2, 0, + 0x1a /*MV_SCRATCH_MISC*/, + (0x71 /*MV_CONFIG_DATA1*/ << 8)); + + val = mdio_bus->read(mdio_bus, priv->global2, 0, + 0x1a /*MV_SCRATCH_MISC*/); + + if (val & (1 << 0)) + priv->no_cpu = 1; + if (val & (1 << 4)) + priv->addr4 = 1; + debug("mv88e6020: no_cpu=%d addr4=%d\n", priv->no_cpu, + priv->addr4); + } + + return 0; +} + /* * Overload weak get_phy_id definition since we need non-standard functions * to read PHY registers @@ -1274,13 +1312,34 @@ int get_phy_id(struct mii_dev *bus, int smi_addr, int devad, u32 *phy_id) if (val < 0) return val;
- val = mv88e61xx_phy_read_indirect(&temp_mii, 0, devad, MII_PHYSID1); + mv88e61xx_read_bootstrap(&temp_phy); + + /* + * When switch is configured to work with CPU (i.e. NO_CPU == 0), PHYs + * require reset (to at least single one) to have its registers + * accessible. + */ + if (!temp_priv.no_cpu && temp_priv.id == PORT_SWITCH_ID_6020) { + /* Reset PHY */ + val = mv88e61xx_phy_read_indirect(&temp_mii, temp_phy.addr, + devad, MII_BMCR); + if (val & BMCR_PDOWN) + val &= ~BMCR_PDOWN; + + mv88e61xx_phy_write_indirect(&temp_mii, temp_phy.addr, devad, + MII_BMCR, val); + } + + /* Read PHY_ID */ + val = mv88e61xx_phy_read_indirect(&temp_mii, temp_phy.addr, devad, + MII_PHYSID1); if (val < 0) return -EIO;
*phy_id = val << 16;
- val = mv88e61xx_phy_read_indirect(&temp_mii, 0, devad, MII_PHYSID2); + val = mv88e61xx_phy_read_indirect(&temp_mii, temp_phy.addr, devad, + MII_PHYSID2); if (val < 0) return -EIO;