]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/of/of_mdio.c
Merge tag 'gpio-v3.16-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[karo-tx-linux.git] / drivers / of / of_mdio.c
index b85709458639b0b9df9d3fe1da54e766b721a17d..fb4a5983064824cad8338cad9327121a615566b4 100644 (file)
@@ -46,7 +46,6 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
        struct phy_device *phy;
        bool is_c45;
        int rc;
-       u32 max_speed = 0;
        u32 phy_id;
 
        is_c45 = of_device_is_compatible(child,
@@ -89,6 +88,27 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
        return 0;
 }
 
+static int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
+{
+       u32 addr;
+       int ret;
+
+       ret = of_property_read_u32(np, "reg", &addr);
+       if (ret < 0) {
+               dev_err(dev, "%s has invalid PHY address\n", np->full_name);
+               return ret;
+       }
+
+       /* A PHY must have a reg property in the range [0-31] */
+       if (addr >= PHY_MAX_ADDR) {
+               dev_err(dev, "%s PHY address %i is too large\n",
+                       np->full_name, addr);
+               return -EINVAL;
+       }
+
+       return addr;
+}
+
 /**
  * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
  * @mdio: pointer to mii_bus structure
@@ -101,9 +121,8 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 {
        struct device_node *child;
        const __be32 *paddr;
-       u32 addr;
        bool scanphys = false;
-       int rc, i, len;
+       int addr, rc, i;
 
        /* Mask out all PHYs from auto probing.  Instead the PHYs listed in
         * the device tree are populated after the bus has been registered */
@@ -123,19 +142,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 
        /* Loop over the child nodes and register a phy_device for each one */
        for_each_available_child_of_node(np, child) {
-               /* A PHY must have a reg property in the range [0-31] */
-               paddr = of_get_property(child, "reg", &len);
-               if (!paddr || len < sizeof(*paddr)) {
+               addr = of_mdio_parse_addr(&mdio->dev, child);
+               if (addr < 0) {
                        scanphys = true;
-                       dev_err(&mdio->dev, "%s has invalid PHY address\n",
-                               child->full_name);
-                       continue;
-               }
-
-               addr = be32_to_cpup(paddr);
-               if (addr >= PHY_MAX_ADDR) {
-                       dev_err(&mdio->dev, "%s PHY address %i is too large\n",
-                               child->full_name, addr);
                        continue;
                }
 
@@ -150,7 +159,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
        /* auto scan for PHYs with empty reg property */
        for_each_available_child_of_node(np, child) {
                /* Skip PHYs with reg property set */
-               paddr = of_get_property(child, "reg", &len);
+               paddr = of_get_property(child, "reg", NULL);
                if (paddr)
                        continue;
 
@@ -173,6 +182,40 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 }
 EXPORT_SYMBOL(of_mdiobus_register);
 
+/**
+ * of_mdiobus_link_phydev - Find a device node for a phy
+ * @mdio: pointer to mii_bus structure
+ * @phydev: phydev for which the of_node pointer should be set
+ *
+ * Walk the list of subnodes of a mdio bus and look for a node that matches the
+ * phy's address with its 'reg' property. If found, set the of_node pointer for
+ * the phy. This allows auto-probed pyh devices to be supplied with information
+ * passed in via DT.
+ */
+void of_mdiobus_link_phydev(struct mii_bus *mdio,
+                           struct phy_device *phydev)
+{
+       struct device *dev = &phydev->dev;
+       struct device_node *child;
+
+       if (dev->of_node || !mdio->dev.of_node)
+               return;
+
+       for_each_available_child_of_node(mdio->dev.of_node, child) {
+               int addr;
+
+               addr = of_mdio_parse_addr(&mdio->dev, child);
+               if (addr < 0)
+                       continue;
+
+               if (addr == phydev->addr) {
+                       dev->of_node = child;
+                       return;
+               }
+       }
+}
+EXPORT_SYMBOL(of_mdiobus_link_phydev);
+
 /* Helper function for of_phy_find_device */
 static int of_phy_match(struct device *dev, void *phy_np)
 {