]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/of/of_mdio.c
Merge tag 'char-misc-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[karo-tx-linux.git] / drivers / of / of_mdio.c
index a87a868fed64f50f22b66741aa357fbff7d5a0bb..86829f8064a61eb324a0a9ea28f63f0bf3ceadbd 100644 (file)
@@ -62,11 +62,9 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
        rc = irq_of_parse_and_map(child, 0);
        if (rc > 0) {
                phy->irq = rc;
-               if (mdio->irq)
-                       mdio->irq[addr] = rc;
+               mdio->irq[addr] = rc;
        } else {
-               if (mdio->irq)
-                       phy->irq = mdio->irq[addr];
+               phy->irq = mdio->irq[addr];
        }
 
        if (of_property_read_bool(child, "broken-turn-around"))
@@ -75,7 +73,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
        /* Associate the OF node with the device structure so it
         * can be looked up later */
        of_node_get(child);
-       phy->dev.of_node = child;
+       phy->mdio.dev.of_node = child;
 
        /* All data is now stored in the phy struct;
         * register it */
@@ -92,6 +90,37 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
        return 0;
 }
 
+static int of_mdiobus_register_device(struct mii_bus *mdio,
+                                     struct device_node *child,
+                                     u32 addr)
+{
+       struct mdio_device *mdiodev;
+       int rc;
+
+       mdiodev = mdio_device_create(mdio, addr);
+       if (!mdiodev || IS_ERR(mdiodev))
+               return 1;
+
+       /* Associate the OF node with the device structure so it
+        * can be looked up later.
+        */
+       of_node_get(child);
+       mdiodev->dev.of_node = child;
+
+       /* All data is now stored in the mdiodev struct; register it. */
+       rc = mdio_device_register(mdiodev);
+       if (rc) {
+               mdio_device_free(mdiodev);
+               of_node_put(child);
+               return 1;
+       }
+
+       dev_dbg(&mdio->dev, "registered mdio device %s at address %i\n",
+               child->name, addr);
+
+       return 0;
+}
+
 int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
 {
        u32 addr;
@@ -114,6 +143,35 @@ int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
 }
 EXPORT_SYMBOL(of_mdio_parse_addr);
 
+/*
+ * Return true if the child node is for a phy. It must either:
+ * o Compatible string of "ethernet-phy-idX.X"
+ * o Compatible string of "ethernet-phy-ieee802.3-c45"
+ * o Compatible string of "ethernet-phy-ieee802.3-c22"
+ * o No compatibility string
+ *
+ * A device which is not a phy is expected to have a compatible string
+ * indicating what sort of device it is.
+ */
+static bool of_mdiobus_child_is_phy(struct device_node *child)
+{
+       u32 phy_id;
+
+       if (of_get_phy_id(child, &phy_id) != -EINVAL)
+               return true;
+
+       if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"))
+               return true;
+
+       if (of_device_is_compatible(child, "ethernet-phy-ieee802.3-c22"))
+               return true;
+
+       if (!of_find_property(child, "compatible", NULL))
+               return true;
+
+       return false;
+}
+
 /**
  * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
  * @mdio: pointer to mii_bus structure
@@ -127,17 +185,12 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
        struct device_node *child;
        const __be32 *paddr;
        bool scanphys = false;
-       int addr, rc, i;
+       int addr, rc;
 
        /* Mask out all PHYs from auto probing.  Instead the PHYs listed in
         * the device tree are populated after the bus has been registered */
        mdio->phy_mask = ~0;
 
-       /* Clear all the IRQ properties */
-       if (mdio->irq)
-               for (i=0; i<PHY_MAX_ADDR; i++)
-                       mdio->irq[i] = PHY_POLL;
-
        mdio->dev.of_node = np;
 
        /* Register the MDIO bus */
@@ -145,7 +198,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
        if (rc)
                return rc;
 
-       /* Loop over the child nodes and register a phy_device for each one */
+       /* Loop over the child nodes and register a phy_device for each phy */
        for_each_available_child_of_node(np, child) {
                addr = of_mdio_parse_addr(&mdio->dev, child);
                if (addr < 0) {
@@ -153,9 +206,10 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
                        continue;
                }
 
-               rc = of_mdiobus_register_phy(mdio, child, addr);
-               if (rc)
-                       continue;
+               if (of_mdiobus_child_is_phy(child))
+                       of_mdiobus_register_phy(mdio, child, addr);
+               else
+                       of_mdiobus_register_device(mdio, child, addr);
        }
 
        if (!scanphys)
@@ -170,16 +224,15 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 
                for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
                        /* skip already registered PHYs */
-                       if (mdio->phy_map[addr])
+                       if (mdiobus_is_registered_device(mdio, addr))
                                continue;
 
                        /* be noisy to encourage people to set reg property */
                        dev_info(&mdio->dev, "scan phy %s at address %i\n",
                                 child->name, addr);
 
-                       rc = of_mdiobus_register_phy(mdio, child, addr);
-                       if (rc)
-                               continue;
+                       if (of_mdiobus_child_is_phy(child))
+                               of_mdiobus_register_phy(mdio, child, addr);
                }
        }
 
@@ -238,7 +291,7 @@ struct phy_device *of_phy_connect(struct net_device *dev,
        ret = phy_connect_direct(dev, phy, hndlr, iface);
 
        /* refcount is held by phy_connect_direct() on success */
-       put_device(&phy->dev);
+       put_device(&phy->mdio.dev);
 
        return ret ? NULL : phy;
 }
@@ -268,7 +321,7 @@ struct phy_device *of_phy_attach(struct net_device *dev,
        ret = phy_attach_direct(dev, phy, flags, iface);
 
        /* refcount is held by phy_attach_direct() on success */
-       put_device(&phy->dev);
+       put_device(&phy->mdio.dev);
 
        return ret ? NULL : phy;
 }