Commit e2597be5bcb90030fdc116e7c5810bdef7fd9e0d

Authored by Sekhar Nori
Committed by Tom Rini
1 parent 4495680735

drivers: net: cpsw: add support to update phy address

On some boards using TI CPSW, it may be possible that
PHY address was not latched correctly, and the actual
address that the phy responds on is different from that
set in device-tree. For example, see this problem report
on beaglebone black:

https://groups.google.com/d/msg/beagleboard/9mctrG26Mc8/1FuI_i5KW10J

Add support to check for this condition and use the
detected phy address when its safe to do so.

Also, add a public API that exposes the phy address of
a given slave. This can be used to update device-tree that
is passed to Linux kernel.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>

Showing 2 changed files with 30 additions and 0 deletions Side-by-side Diff

... ... @@ -1008,6 +1008,25 @@
1008 1008 return 1;
1009 1009 }
1010 1010  
  1011 +static void cpsw_phy_addr_update(struct cpsw_priv *priv)
  1012 +{
  1013 + struct cpsw_platform_data *data = &priv->data;
  1014 + u16 alive = mdio_regs->alive & GENMASK(15, 0);
  1015 + int active = data->active_slave;
  1016 + int new_addr = ffs(alive) - 1;
  1017 +
  1018 + /*
  1019 + * If there is only one phy alive and its address does not match
  1020 + * that of active slave, then phy address can safely be updated.
  1021 + */
  1022 + if (hweight16(alive) == 1 &&
  1023 + data->slave_data[active].phy_addr != new_addr) {
  1024 + printf("Updated phy address for CPSW#%d, old: %d, new: %d\n",
  1025 + active, data->slave_data[active].phy_addr, new_addr);
  1026 + data->slave_data[active].phy_addr = new_addr;
  1027 + }
  1028 +}
  1029 +
1011 1030 int _cpsw_register(struct cpsw_priv *priv)
1012 1031 {
1013 1032 struct cpsw_slave *slave;
... ... @@ -1034,6 +1053,9 @@
1034 1053 }
1035 1054  
1036 1055 cpsw_mdio_init(priv->dev->name, data->mdio_base, data->mdio_div);
  1056 +
  1057 + cpsw_phy_addr_update(priv);
  1058 +
1037 1059 priv->bus = miiphy_get_dev_by_name(priv->dev->name);
1038 1060 for_active_slave(slave, priv)
1039 1061 cpsw_phy_init(priv, slave);
... ... @@ -1458,6 +1480,13 @@
1458 1480 return 0;
1459 1481 }
1460 1482  
  1483 +int cpsw_get_slave_phy_addr(struct udevice *dev, int slave)
  1484 +{
  1485 + struct cpsw_priv *priv = dev_get_priv(dev);
  1486 + struct cpsw_platform_data *data = &priv->data;
  1487 +
  1488 + return data->slave_data[slave].phy_addr;
  1489 +}
1461 1490  
1462 1491 static const struct udevice_id cpsw_eth_ids[] = {
1463 1492 { .compatible = "ti,cpsw" },
... ... @@ -54,6 +54,7 @@
54 54  
55 55 int cpsw_register(struct cpsw_platform_data *data);
56 56 int ti_cm_get_macid(struct udevice *dev, int slave, u8 *mac_addr);
  57 +int cpsw_get_slave_phy_addr(struct udevice *dev, int slave);
57 58  
58 59 #endif /* _CPSW_H_ */