Commit 388a8357 authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa_phy_divert'

Florian Fainelli says:

====================
net: dsa: support PHY reads/writes diversion

This patch series completes the PHY reads/writes diversion when we need to use
the slave MII bus provided by DSA and the underlying switch drivers to
implement the real PHY reads and writes. This is particularly useful when they
are conflicting MDIO bus addresses as in the case of multiple Broadcom switches
connected to each other (internal and external, or just external).
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d26ea6cc cd28a1a9
...@@ -88,7 +88,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi ...@@ -88,7 +88,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
return 0; return 0;
} }
static int of_mdio_parse_addr(struct device *dev, const struct device_node *np) int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
{ {
u32 addr; u32 addr;
int ret; int ret;
...@@ -108,6 +108,7 @@ static int of_mdio_parse_addr(struct device *dev, const struct device_node *np) ...@@ -108,6 +108,7 @@ static int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
return addr; return addr;
} }
EXPORT_SYMBOL(of_mdio_parse_addr);
/** /**
* of_mdiobus_register - Register mii_bus and create PHYs from the device tree * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
......
...@@ -24,6 +24,7 @@ struct phy_device *of_phy_attach(struct net_device *dev, ...@@ -24,6 +24,7 @@ struct phy_device *of_phy_attach(struct net_device *dev,
phy_interface_t iface); phy_interface_t iface);
extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np); extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np);
#else /* CONFIG_OF */ #else /* CONFIG_OF */
static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
...@@ -60,6 +61,12 @@ static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np) ...@@ -60,6 +61,12 @@ static inline struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np)
{ {
return NULL; return NULL;
} }
static inline int of_mdio_parse_addr(struct device *dev,
const struct device_node *np)
{
return -ENOSYS;
}
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
#if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY) #if defined(CONFIG_OF) && defined(CONFIG_FIXED_PHY)
......
...@@ -617,6 +617,24 @@ static int dsa_slave_fixed_link_update(struct net_device *dev, ...@@ -617,6 +617,24 @@ static int dsa_slave_fixed_link_update(struct net_device *dev,
} }
/* slave device setup *******************************************************/ /* slave device setup *******************************************************/
static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
struct net_device *slave_dev,
int addr)
{
struct dsa_switch *ds = p->parent;
p->phy = ds->slave_mii_bus->phy_map[addr];
if (!p->phy)
return -ENODEV;
/* Use already configured phy mode */
p->phy_interface = p->phy->interface;
phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
p->phy_interface);
return 0;
}
static int dsa_slave_phy_setup(struct dsa_slave_priv *p, static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
struct net_device *slave_dev) struct net_device *slave_dev)
{ {
...@@ -650,10 +668,24 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -650,10 +668,24 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
if (ds->drv->get_phy_flags) if (ds->drv->get_phy_flags)
phy_flags = ds->drv->get_phy_flags(ds, p->port); phy_flags = ds->drv->get_phy_flags(ds, p->port);
if (phy_dn) if (phy_dn) {
ret = of_mdio_parse_addr(&slave_dev->dev, phy_dn);
/* If this PHY address is part of phys_mii_mask, which means
* that we need to divert reads and writes to/from it, then we
* want to bind this device using the slave MII bus created by
* DSA to make that happen.
*/
if (ret >= 0 && (ds->phys_mii_mask & (1 << ret))) {
ret = dsa_slave_phy_connect(p, slave_dev, ret);
if (ret)
return ret;
} else {
p->phy = of_phy_connect(slave_dev, phy_dn, p->phy = of_phy_connect(slave_dev, phy_dn,
dsa_slave_adjust_link, phy_flags, dsa_slave_adjust_link,
phy_flags,
p->phy_interface); p->phy_interface);
}
}
if (p->phy && phy_is_fixed) if (p->phy && phy_is_fixed)
fixed_phy_set_link_update(p->phy, dsa_slave_fixed_link_update); fixed_phy_set_link_update(p->phy, dsa_slave_fixed_link_update);
...@@ -662,14 +694,9 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, ...@@ -662,14 +694,9 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
* MDIO bus instead * MDIO bus instead
*/ */
if (!p->phy) { if (!p->phy) {
p->phy = ds->slave_mii_bus->phy_map[p->port]; ret = dsa_slave_phy_connect(p, slave_dev, p->port);
if (!p->phy) if (ret)
return -ENODEV; return ret;
/* Use already configured phy mode */
p->phy_interface = p->phy->interface;
phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
p->phy_interface);
} else { } else {
netdev_info(slave_dev, "attached PHY at address %d [%s]\n", netdev_info(slave_dev, "attached PHY at address %d [%s]\n",
p->phy->addr, p->phy->drv->name); p->phy->addr, p->phy->drv->name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment