summaryrefslogtreecommitdiff
path: root/drivers/phy/phy-core.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2016-05-09 16:18:37 +0200
committerArnd Bergmann <arnd@arndb.de>2016-05-09 16:18:37 +0200
commit4ace926172a7d93182381a3c7a2d05acb2dd91a4 (patch)
tree8718330c15c8dbffd5612d56cd4ff62f741affda /drivers/phy/phy-core.c
parentf0653f6768ee9d66e25b2476facb74c9c2d88118 (diff)
parent87d66f280672800c9c2ad1ce3b7a993ce1e04769 (diff)
Merge tag 'tegra-for-4.7-phy' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers
Merge "phy: tegra: Changes for v4.7-rc1" from Thierry Reding: This set of patches adds support for the Tegra XUSB pad controller. The controller provides a set of pads (lanes) that are used for I/O by other IP blocks within Tegra SoCs (PCIe, SATA and XUSB). * tag 'tegra-for-4.7-phy' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: phy: tegra: Add Tegra210 support phy: Add Tegra XUSB pad controller support dt-bindings: phy: tegra-xusb-padctl: Add Tegra210 support dt-bindings: phy: Add NVIDIA Tegra XUSB pad controller binding phy: core: Allow children node to be overridden clk: tegra: Add interface to enable hardware control of SATA/XUSB PLLs
Diffstat (limited to 'drivers/phy/phy-core.c')
-rw-r--r--drivers/phy/phy-core.c50
1 files changed, 44 insertions, 6 deletions
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);
}