diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 13:14:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-18 13:14:02 -0700 |
commit | 4a5219edcdae52bfb5eea0dfc2a7bd575961dad7 (patch) | |
tree | 863f6efeac5fe9ba4f1f8d23b32b2947130ed510 /drivers/phy/phy-core.c | |
parent | 9797f6b0504122e4ad9ff047a3d0521ad6706386 (diff) | |
parent | 5420f9fd159761b88978c312c3b350546f8615bb (diff) | |
download | lwn-4a5219edcdae52bfb5eea0dfc2a7bd575961dad7.tar.gz lwn-4a5219edcdae52bfb5eea0dfc2a7bd575961dad7.zip |
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Arnd Bergmann:
"Driver updates for ARM SoCs, these contain various things that touch
the drivers/ directory but got merged through arm-soc for practical
reasons.
For the most part, this is now related to power management
controllers, which have not yet been abstracted into a separate
subsystem, and typically require some code in drivers/soc or arch/arm
to control the power domains.
Another large chunk here is a rework of the NVIDIA Tegra USB3.0
support, which was surprisingly tricky and took a long time to get
done.
Finally, reset controller handling as always gets merged through here
as well"
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (97 commits)
arm-ccn: Enable building as module
soc/tegra: pmc: Add generic PM domain support
usb: xhci: tegra: Add Tegra210 support
usb: xhci: Add NVIDIA Tegra XUSB controller driver
dt-bindings: usb: xhci-tegra: Add Tegra210 XUSB controller support
dt-bindings: usb: Add NVIDIA Tegra XUSB controller binding
PCI: tegra: Support per-lane PHYs
dt-bindings: pci: tegra: Update for per-lane PHYs
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
drivers: firmware: psci: make two helper functions inline
soc: renesas: rcar-sysc: Add support for R-Car H3 power areas
soc: renesas: rcar-sysc: Add support for R-Car E2 power areas
soc: renesas: rcar-sysc: Add support for R-Car M2-N power areas
soc: renesas: rcar-sysc: Add support for R-Car M2-W power areas
soc: renesas: rcar-sysc: Add support for R-Car H2 power areas
...
Diffstat (limited to 'drivers/phy/phy-core.c')
-rw-r--r-- | drivers/phy/phy-core.c | 50 |
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); } |