These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / of / of_mdio.c
index bec8ec2..a87a868 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/of_mdio.h>
 #include <linux/module.h>
@@ -68,6 +69,9 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
                        phy->irq = mdio->irq[addr];
        }
 
+       if (of_property_read_bool(child, "broken-turn-around"))
+               mdio->phy_ignore_ta_mask |= 1 << addr;
+
        /* Associate the OF node with the device structure so it
         * can be looked up later */
        of_node_get(child);
@@ -193,7 +197,8 @@ static int of_phy_match(struct device *dev, void *phy_np)
  * of_phy_find_device - Give a PHY node, find the phy_device
  * @phy_np: Pointer to the phy's device tree node
  *
- * Returns a pointer to the phy_device.
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
  */
 struct phy_device *of_phy_find_device(struct device_node *phy_np)
 {
@@ -213,7 +218,9 @@ EXPORT_SYMBOL(of_phy_find_device);
  * @hndlr: Link state callback for the network device
  * @iface: PHY data interface type
  *
- * Returns a pointer to the phy_device if successful.  NULL otherwise
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure. The
+ * refcount must be dropped by calling phy_disconnect() or phy_detach().
  */
 struct phy_device *of_phy_connect(struct net_device *dev,
                                  struct device_node *phy_np,
@@ -221,13 +228,19 @@ struct phy_device *of_phy_connect(struct net_device *dev,
                                  phy_interface_t iface)
 {
        struct phy_device *phy = of_phy_find_device(phy_np);
+       int ret;
 
        if (!phy)
                return NULL;
 
        phy->dev_flags = flags;
 
-       return phy_connect_direct(dev, phy, hndlr, iface) ? NULL : phy;
+       ret = phy_connect_direct(dev, phy, hndlr, iface);
+
+       /* refcount is held by phy_connect_direct() on success */
+       put_device(&phy->dev);
+
+       return ret ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect);
 
@@ -237,17 +250,27 @@ EXPORT_SYMBOL(of_phy_connect);
  * @phy_np: Node pointer for the PHY
  * @flags: flags to pass to the PHY
  * @iface: PHY data interface type
+ *
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure. The
+ * refcount must be dropped by calling phy_disconnect() or phy_detach().
  */
 struct phy_device *of_phy_attach(struct net_device *dev,
                                 struct device_node *phy_np, u32 flags,
                                 phy_interface_t iface)
 {
        struct phy_device *phy = of_phy_find_device(phy_np);
+       int ret;
 
        if (!phy)
                return NULL;
 
-       return phy_attach_direct(dev, phy, flags, iface) ? NULL : phy;
+       ret = phy_attach_direct(dev, phy, flags, iface);
+
+       /* refcount is held by phy_attach_direct() on success */
+       put_device(&phy->dev);
+
+       return ret ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_attach);
 
@@ -291,6 +314,7 @@ int of_phy_register_fixed_link(struct device_node *np)
        struct fixed_phy_status status = {};
        struct device_node *fixed_link_node;
        const __be32 *fixed_link_prop;
+       int link_gpio;
        int len, err;
        struct phy_device *phy;
        const char *managed;
@@ -299,7 +323,7 @@ int of_phy_register_fixed_link(struct device_node *np)
        if (err == 0) {
                if (strcmp(managed, "in-band-status") == 0) {
                        /* status is zeroed, namely its .link member */
-                       phy = fixed_phy_register(PHY_POLL, &status, np);
+                       phy = fixed_phy_register(PHY_POLL, &status, -1, np);
                        return IS_ERR(phy) ? PTR_ERR(phy) : 0;
                }
        }
@@ -315,8 +339,13 @@ int of_phy_register_fixed_link(struct device_node *np)
                status.pause = of_property_read_bool(fixed_link_node, "pause");
                status.asym_pause = of_property_read_bool(fixed_link_node,
                                                          "asym-pause");
+               link_gpio = of_get_named_gpio_flags(fixed_link_node,
+                                                   "link-gpios", 0, NULL);
                of_node_put(fixed_link_node);
-               phy = fixed_phy_register(PHY_POLL, &status, np);
+               if (link_gpio == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               phy = fixed_phy_register(PHY_POLL, &status, link_gpio, np);
                return IS_ERR(phy) ? PTR_ERR(phy) : 0;
        }
 
@@ -328,7 +357,7 @@ int of_phy_register_fixed_link(struct device_node *np)
                status.speed = be32_to_cpu(fixed_link_prop[2]);
                status.pause = be32_to_cpu(fixed_link_prop[3]);
                status.asym_pause = be32_to_cpu(fixed_link_prop[4]);
-               phy = fixed_phy_register(PHY_POLL, &status, np);
+               phy = fixed_phy_register(PHY_POLL, &status, -1, np);
                return IS_ERR(phy) ? PTR_ERR(phy) : 0;
        }