diff options
Diffstat (limited to 'patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch')
-rw-r--r-- | patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch b/patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch new file mode 100644 index 0000000..4ef518d --- /dev/null +++ b/patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch @@ -0,0 +1,204 @@ +From 5a2e1bc30bd48edd71c3eaef3d5141d6fbe3edb2 Mon Sep 17 00:00:00 2001 +From: Ajay Kumar Gupta <ajay.gupta@ti.com> +Date: Tue, 10 Jul 2012 14:10:38 +0530 +Subject: [PATCH] drivers: usb: otg: add device tree support to otg library + +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 <richard.zhao@freescale.com> +Cc: Marek Vasut <marex@denx.de> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> +--- + drivers/usb/otg/otg.c | 95 ++++++++++++++++++++++++++++++++++++++++------- + include/linux/usb/otg.h | 32 ++++++++++++++++ + 2 files changed, 113 insertions(+), 14 deletions(-) + +diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c +index a30c041..ff08b34 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; +@@ -111,6 +127,65 @@ err0: + 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() +@@ -155,32 +230,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->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 e8a5fe8..bae7599 100644 +--- a/include/linux/usb/otg.h ++++ b/include/linux/usb/otg.h +@@ -37,8 +37,40 @@ struct usb_otg { + }; + + #ifdef CONFIG_USB_OTG_UTILS ++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); + #else ++static inline struct usb_phy *usb_get_phy(enum usb_phy_type type) ++{ ++ return NULL; ++} ++ ++static inline struct usb_phy *devm_usb_get_phy(struct device *dev, ++ enum usb_phy_type type) ++{ ++ 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) ++{ ++} ++ ++static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) ++{ ++} ++ + static inline const char *otg_state_string(enum usb_otg_state state) + { + return NULL; |