phy: core: Allow children node to be overridden
authorThierry Reding <treding@nvidia.com>
Tue, 5 Apr 2016 15:17:34 +0000 (17:17 +0200)
committerThierry Reding <treding@nvidia.com>
Fri, 29 Apr 2016 14:39:39 +0000 (16:39 +0200)
In order to more flexibly support device tree bindings, allow drivers to
override the container of the child nodes. By default the device node of
the PHY provider is assumed to be the parent for children, but bindings
may decide to add additional levels for better organization.

Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Documentation/phy.txt
drivers/phy/phy-core.c
include/linux/phy/phy.h

index b388c5a..0aa994b 100644 (file)
@@ -31,16 +31,28 @@ should provide its own implementation of of_xlate. of_xlate is used only for
 dt boot case.
 
 #define of_phy_provider_register(dev, xlate)    \
-        __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+        __of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
 
 #define devm_of_phy_provider_register(dev, xlate)       \
-        __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
+        __devm_of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
 
 of_phy_provider_register and devm_of_phy_provider_register macros can be used to
 register the phy_provider and it takes device and of_xlate as
 arguments. For the dt boot case, all PHY providers should use one of the above
 2 macros to register the PHY provider.
 
+Often the device tree nodes associated with a PHY provider will contain a set
+of children that each represent a single PHY. Some bindings may nest the child
+nodes within extra levels for context and extensibility, in which case the low
+level of_phy_provider_register_full() and devm_of_phy_provider_register_full()
+macros can be used to override the node containing the children.
+
+#define of_phy_provider_register_full(dev, children, xlate) \
+       __of_phy_provider_register(dev, children, THIS_MODULE, xlate)
+
+#define devm_of_phy_provider_register_full(dev, children, xlate) \
+       __devm_of_phy_provider_register_full(dev, children, THIS_MODULE, xlate)
+
 void devm_of_phy_provider_unregister(struct device *dev,
        struct phy_provider *phy_provider);
 void of_phy_provider_unregister(struct phy_provider *phy_provider);
index e7e574d..b72e9a3 100644 (file)
@@ -141,7 +141,7 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
                if (phy_provider->dev->of_node == node)
                        return phy_provider;
 
-               for_each_child_of_node(phy_provider->dev->of_node, child)
+               for_each_child_of_node(phy_provider->children, child)
                        if (child == node)
                                return phy_provider;
        }
@@ -811,24 +811,59 @@ EXPORT_SYMBOL_GPL(devm_phy_destroy);
 /**
  * __of_phy_provider_register() - create/register phy provider with the framework
  * @dev: struct device of the phy provider
+ * @children: device node containing children (if different from dev->of_node)
  * @owner: the module owner containing of_xlate
  * @of_xlate: function pointer to obtain phy instance from phy provider
  *
  * Creates struct phy_provider from dev and of_xlate function pointer.
  * This is used in the case of dt boot for finding the phy instance from
  * phy provider.
+ *
+ * If the PHY provider doesn't nest children directly but uses a separate
+ * child node to contain the individual children, the @children parameter
+ * can be used to override the default. If NULL, the default (dev->of_node)
+ * will be used. If non-NULL, the device node must be a child (or further
+ * descendant) of dev->of_node. Otherwise an ERR_PTR()-encoded -EINVAL
+ * error code is returned.
  */
 struct phy_provider *__of_phy_provider_register(struct device *dev,
-       struct module *owner, struct phy * (*of_xlate)(struct device *dev,
-       struct of_phandle_args *args))
+       struct device_node *children, struct module *owner,
+       struct phy * (*of_xlate)(struct device *dev,
+                                struct of_phandle_args *args))
 {
        struct phy_provider *phy_provider;
 
+       /*
+        * If specified, the device node containing the children must itself
+        * be the provider's device node or a child (or further descendant)
+        * thereof.
+        */
+       if (children) {
+               struct device_node *parent = of_node_get(children), *next;
+
+               while (parent) {
+                       if (parent == dev->of_node)
+                               break;
+
+                       next = of_get_parent(parent);
+                       of_node_put(parent);
+                       parent = next;
+               }
+
+               if (!parent)
+                       return ERR_PTR(-EINVAL);
+
+               of_node_put(parent);
+       } else {
+               children = dev->of_node;
+       }
+
        phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
        if (!phy_provider)
                return ERR_PTR(-ENOMEM);
 
        phy_provider->dev = dev;
+       phy_provider->children = of_node_get(children);
        phy_provider->owner = owner;
        phy_provider->of_xlate = of_xlate;
 
@@ -854,8 +889,9 @@ EXPORT_SYMBOL_GPL(__of_phy_provider_register);
  * on the devres data, then, devres data is freed.
  */
 struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
-       struct module *owner, struct phy * (*of_xlate)(struct device *dev,
-       struct of_phandle_args *args))
+       struct device_node *children, struct module *owner,
+       struct phy * (*of_xlate)(struct device *dev,
+                                struct of_phandle_args *args))
 {
        struct phy_provider **ptr, *phy_provider;
 
@@ -863,7 +899,8 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
        if (!ptr)
                return ERR_PTR(-ENOMEM);
 
-       phy_provider = __of_phy_provider_register(dev, owner, of_xlate);
+       phy_provider = __of_phy_provider_register(dev, children, owner,
+                                                 of_xlate);
        if (!IS_ERR(phy_provider)) {
                *ptr = phy_provider;
                devres_add(dev, ptr);
@@ -888,6 +925,7 @@ void of_phy_provider_unregister(struct phy_provider *phy_provider)
 
        mutex_lock(&phy_provider_mutex);
        list_del(&phy_provider->list);
+       of_node_put(phy_provider->children);
        kfree(phy_provider);
        mutex_unlock(&phy_provider_mutex);
 }
index 8cf05e3..a810f2a 100644 (file)
@@ -77,6 +77,7 @@ struct phy {
  */
 struct phy_provider {
        struct device           *dev;
+       struct device_node      *children;
        struct module           *owner;
        struct list_head        list;
        struct phy * (*of_xlate)(struct device *dev,
@@ -93,10 +94,16 @@ struct phy_lookup {
 #define        to_phy(a)       (container_of((a), struct phy, dev))
 
 #define        of_phy_provider_register(dev, xlate)    \
-       __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+       __of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
 
 #define        devm_of_phy_provider_register(dev, xlate)       \
-       __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
+       __devm_of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
+
+#define of_phy_provider_register_full(dev, children, xlate) \
+       __of_phy_provider_register(dev, children, THIS_MODULE, xlate)
+
+#define devm_of_phy_provider_register_full(dev, children, xlate) \
+       __devm_of_phy_provider_register(dev, children, THIS_MODULE, xlate)
 
 static inline void phy_set_drvdata(struct phy *phy, void *data)
 {
@@ -147,11 +154,13 @@ struct phy *devm_phy_create(struct device *dev, struct device_node *node,
 void phy_destroy(struct phy *phy);
 void devm_phy_destroy(struct device *dev, struct phy *phy);
 struct phy_provider *__of_phy_provider_register(struct device *dev,
-       struct module *owner, struct phy * (*of_xlate)(struct device *dev,
-       struct of_phandle_args *args));
+       struct device_node *children, struct module *owner,
+       struct phy * (*of_xlate)(struct device *dev,
+                                struct of_phandle_args *args));
 struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
-       struct module *owner, struct phy * (*of_xlate)(struct device *dev,
-       struct of_phandle_args *args));
+       struct device_node *children, struct module *owner,
+       struct phy * (*of_xlate)(struct device *dev,
+                                struct of_phandle_args *args));
 void of_phy_provider_unregister(struct phy_provider *phy_provider);
 void devm_of_phy_provider_unregister(struct device *dev,
        struct phy_provider *phy_provider);
@@ -312,15 +321,17 @@ static inline void devm_phy_destroy(struct device *dev, struct phy *phy)
 }
 
 static inline struct phy_provider *__of_phy_provider_register(
-       struct device *dev, struct module *owner, struct phy * (*of_xlate)(
-       struct device *dev, struct of_phandle_args *args))
+       struct device *dev, struct device_node *children, struct module *owner,
+       struct phy * (*of_xlate)(struct device *dev,
+                                struct of_phandle_args *args))
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct phy_provider *__devm_of_phy_provider_register(struct device
-       *dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev,
-       struct of_phandle_args *args))
+       *dev, struct device_node *children, struct module *owner,
+       struct phy * (*of_xlate)(struct device *dev,
+                                struct of_phandle_args *args))
 {
        return ERR_PTR(-ENOSYS);
 }