On Thursday 28 April 2016 07:01 PM, Thierry Reding wrote: > From: Thierry Reding <tred...@nvidia.com> > > 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. > > Cc: Kishon Vijay Abraham I <kis...@ti.com> > Signed-off-by: Thierry Reding <tred...@nvidia.com>
Acked-by: Kishon Vijay Abraham I <kis...@ti.com> > --- > Hi Kishon, > > I'm looking for an Acked-by from you on this patch. It's recently become > a requirement for the new Tegra PHY driver. As a precaution and to speed > things up I preemptively took it into linux-next and I think it's pretty > well-cooked by now. I have this sitting in a branch that I can stabilize > and send your way as a pull request. > > Thanks, > Thierry > > Changes in v2: > - check that specified node is a child (or further descendant) of the > PHY provider (Kishon) > > Documentation/phy.txt | 16 ++++++++++++++-- > drivers/phy/phy-core.c | 50 > +++++++++++++++++++++++++++++++++++++++++++------ > include/linux/phy/phy.h | 31 ++++++++++++++++++++---------- > 3 files changed, 79 insertions(+), 18 deletions(-) > > diff --git a/Documentation/phy.txt b/Documentation/phy.txt > index b388c5af9e72..0aa994bd9a91 100644 > --- a/Documentation/phy.txt > +++ b/Documentation/phy.txt > @@ -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); > diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c > index e7e574dc667a..b72e9a3b6429 100644 > --- a/drivers/phy/phy-core.c > +++ b/drivers/phy/phy-core.c > @@ -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); > } > diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h > index 8cf05e341cff..a810f2a18842 100644 > --- a/include/linux/phy/phy.h > +++ b/include/linux/phy/phy.h > @@ -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); > } >