On 06/26/2012 11:37 AM, Kishon Vijay Abraham I wrote: > Adds an API to get usb phy by passing a device node phandle value. Since > now it's possible to obtain phy by phandle, the checks in usb_add_phy > for a valid phy type is removed (now it's just a debug message if a user > tries to add a phy with undefined type). > This also allows to add multiple phys of same type. > > Cc: Richard Zhao <[email protected]> > Cc: Marek Vasut <[email protected]> > Signed-off-by: Kishon Vijay Abraham I <[email protected]> > --- > Had to remove the restricion on adding multiple phys of same type as now it > would be possible to get the phys by phandle value. However there is no > clear way to get a phy when there are multiple phys of same type without > a phandle (non-dt). So in non-dt environment, adding and getting phy API's > should be used with caution. Currently multiple-phys of the same type > doesn't exist in kernel.
What's the status of this patch?
Marc
> drivers/usb/otg/otg.c | 95
> ++++++++++++++++++++++++++++++++++++++++-------
> include/linux/usb/otg.h | 8 ++++
> 2 files changed, 89 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
> index 0fa4d8c..b36a647 100644
> --- a/drivers/usb/otg/otg.c
> +++ b/drivers/usb/otg/otg.c
> @@ -14,6 +14,7 @@
> #include <linux/err.h>
> #include <linux/device.h>
> #include <linux/slab.h>
> +#include <linux/of.h>
>
> #include <linux/usb/otg.h>
>
> @@ -35,6 +36,21 @@ static struct usb_phy *__usb_find_phy(struct list_head
> *list,
> return ERR_PTR(-ENODEV);
> }
>
> +static struct usb_phy *__of_usb_find_phy(struct list_head *list,
> + struct device_node *node)
> +{
> + struct usb_phy *phy;
> +
> + list_for_each_entry(phy, list, head) {
> + if (node != phy->dev->of_node)
> + continue;
> +
> + return phy;
> + }
> +
> + return ERR_PTR(-ENODEV);
> +}
> +
> static void devm_usb_phy_release(struct device *dev, void *res)
> {
> struct usb_phy *phy = *(struct usb_phy **)res;
> @@ -110,6 +126,65 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)
> EXPORT_SYMBOL(usb_get_phy);
>
> /**
> + * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
> + * @dev - device that requests this phy
> + * @phandle - name of the property holding the phy phandle value
> + *
> + * Returns the phy driver associated with the given phandle value,
> + * after getting a refcount to it; or -ENODEV/NULL if there is no such phy.
> + * While at that, it also associates the device with the phy using
> + * devres. On driver detach, release function is invoked on the devres data,
> + * then, devres data is freed.
> + *
> + * For use by USB host and peripheral drivers.
> + */
> +struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
> + const char *phandle)
> +{
> + struct usb_phy *phy = NULL, **ptr;
> + unsigned long flags;
> + struct device_node *node;
> +
> + if (!dev->of_node) {
> + dev_dbg(dev, "device does not have a device node entry\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
> + if (!ptr) {
> + dev_dbg(dev, "failed to allocate memory for devres\n");
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + spin_lock_irqsave(&phy_lock, flags);
> +
> + node = of_parse_phandle(dev->of_node, phandle, 0);
> + if (!node) {
> + dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
> + dev->of_node->full_name);
> + goto err0;
> + }
> +
> + phy = __of_usb_find_phy(&phy_list, node);
> + if (!IS_ERR(phy)) {
> + *ptr = phy;
> + devres_add(dev, ptr);
> + } else {
> + pr_err("unable to find transceiver with phandle %s\n", phandle);
> + devres_free(ptr);
> + goto err0;
> + }
> +
> + get_device(phy->dev);
> +
> +err0:
> + spin_unlock_irqrestore(&phy_lock, flags);
> +
> + return phy;
> +}
> +EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
> +
> +/**
> * devm_usb_put_phy - release the USB PHY
> * @dev - device that wants to release this phy
> * @phy - the phy returned by devm_usb_get_phy()
> @@ -154,32 +229,24 @@ EXPORT_SYMBOL(usb_put_phy);
> */
> int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
> {
> - int ret = 0;
> unsigned long flags;
> struct usb_phy *phy;
>
> - if (x && x->type != USB_PHY_TYPE_UNDEFINED) {
> - dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
> - return -EINVAL;
> - }
> + if (x && x->type != USB_PHY_TYPE_UNDEFINED)
> + dev_dbg(x->dev, "add a phy with undefined type %s\n", x->label);
>
> spin_lock_irqsave(&phy_lock, flags);
>
> - list_for_each_entry(phy, &phy_list, head) {
> - if (phy->type == type) {
> - ret = -EBUSY;
> - dev_err(x->dev, "transceiver type %s already exists\n",
> + list_for_each_entry(phy, &phy_list, head)
> + if (phy->type == type)
> + dev_dbg(x->dev, "transceiver type %s already exists\n",
> usb_phy_type_string(type));
> - goto out;
> - }
> - }
>
> x->type = type;
> list_add_tail(&x->head, &phy_list);
>
> -out:
> spin_unlock_irqrestore(&phy_lock, flags);
> - return ret;
> + return 0;
> }
> EXPORT_SYMBOL(usb_add_phy);
>
> diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
> index 0cb2ec2..4636d39 100644
> --- a/include/linux/usb/otg.h
> +++ b/include/linux/usb/otg.h
> @@ -187,6 +187,8 @@ usb_phy_shutdown(struct usb_phy *x)
> extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
> extern struct usb_phy *devm_usb_get_phy(struct device *dev,
> enum usb_phy_type type);
> +extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
> + const char *phandle);
> extern void usb_put_phy(struct usb_phy *);
> extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
> extern const char *otg_state_string(enum usb_otg_state state);
> @@ -202,6 +204,12 @@ static inline struct usb_phy *devm_usb_get_phy(struct
> device *dev,
> return NULL;
> }
>
> +extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
> + const char *phandle)
> +{
> + return NULL;
> +}
> +
> static inline void usb_put_phy(struct usb_phy *x)
> {
> }
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
signature.asc
Description: OpenPGP digital signature
