Commit 6ef31c8b authored by Jeremy Linton's avatar Jeremy Linton Committed by David S. Miller

net: bcmgenet: enable automatic phy discovery

The unimac mdio driver falls back to scanning the
entire bus if its given an appropriate mask. In ACPI
mode we expect that the system is well behaved and
conforms to recent versions of the specification.

We then utilize phy_find_first(), and
phy_connect_direct() to find and attach to the
discovered phy during net_device open. While its
apparently possible to build a genet based device
with multiple phys on a single mdio bus, this works
for current machines. Further, this driver makes
a number of assumptions about the platform device,
mac, mdio and phy all being 1:1. Lastly, It also
avoids having to create references across the ACPI
namespace hierarchy.
Signed-off-by: default avatarJeremy Linton <jeremy.linton@arm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 480ded26
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Copyright (c) 2014-2017 Broadcom * Copyright (c) 2014-2017 Broadcom
*/ */
#include <linux/acpi.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -311,7 +311,8 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) ...@@ -311,7 +311,8 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
int bcmgenet_mii_probe(struct net_device *dev) int bcmgenet_mii_probe(struct net_device *dev)
{ {
struct bcmgenet_priv *priv = netdev_priv(dev); struct bcmgenet_priv *priv = netdev_priv(dev);
struct device_node *dn = priv->pdev->dev.of_node; struct device *kdev = &priv->pdev->dev;
struct device_node *dn = kdev->of_node;
struct phy_device *phydev; struct phy_device *phydev;
u32 phy_flags = 0; u32 phy_flags = 0;
int ret; int ret;
...@@ -333,8 +334,28 @@ int bcmgenet_mii_probe(struct net_device *dev) ...@@ -333,8 +334,28 @@ int bcmgenet_mii_probe(struct net_device *dev)
pr_err("could not attach to PHY\n"); pr_err("could not attach to PHY\n");
return -ENODEV; return -ENODEV;
} }
} else {
if (has_acpi_companion(kdev)) {
char mdio_bus_id[MII_BUS_ID_SIZE];
struct mii_bus *unimacbus;
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
unimacbus = mdio_find_bus(mdio_bus_id);
if (!unimacbus) {
pr_err("Unable to find mii\n");
return -ENODEV;
}
phydev = phy_find_first(unimacbus);
put_device(&unimacbus->dev);
if (!phydev) {
pr_err("Unable to find PHY\n");
return -ENODEV;
}
} else { } else {
phydev = dev->phydev; phydev = dev->phydev;
}
phydev->dev_flags = phy_flags; phydev->dev_flags = phy_flags;
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup, ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
...@@ -455,9 +476,12 @@ static int bcmgenet_mii_register(struct bcmgenet_priv *priv) ...@@ -455,9 +476,12 @@ static int bcmgenet_mii_register(struct bcmgenet_priv *priv)
/* Retain this platform_device pointer for later cleanup */ /* Retain this platform_device pointer for later cleanup */
priv->mii_pdev = ppdev; priv->mii_pdev = ppdev;
ppdev->dev.parent = &pdev->dev; ppdev->dev.parent = &pdev->dev;
if (dn)
ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv); ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv);
if (pdata) else if (pdata)
bcmgenet_mii_pdata_init(priv, &ppd); bcmgenet_mii_pdata_init(priv, &ppd);
else
ppd.phy_mask = ~0;
ret = platform_device_add_resources(ppdev, &res, 1); ret = platform_device_add_resources(ppdev, &res, 1);
if (ret) if (ret)
...@@ -591,10 +615,13 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv) ...@@ -591,10 +615,13 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv) static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
{ {
struct device_node *dn = priv->pdev->dev.of_node; struct device *kdev = &priv->pdev->dev;
struct device_node *dn = kdev->of_node;
if (dn) if (dn)
return bcmgenet_mii_of_init(priv); return bcmgenet_mii_of_init(priv);
else if (has_acpi_companion(kdev))
return bcmgenet_phy_interface_init(priv);
else else
return bcmgenet_mii_pd_init(priv); return bcmgenet_mii_pd_init(priv);
} }
......
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