[PATCH v1 6/6] net: mv88e61xx: Reset switch PHYs when bootstrapped to !NO_CPU
Lukasz Majewski
lukma at denx.de
Wed Mar 17 15:14:10 CET 2021
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 at 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;
--
2.20.1
More information about the U-Boot
mailing list