aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2013-01-24 21:33:25 -0500
committerFelipe Balbi <balbi@ti.com>2013-01-25 03:20:14 -0500
commit5d3c28b5a42df5ceaa854901ba2cccb76883c77e (patch)
treeae1e50d90d5ce1e5925dd552971224f775b574f3 /drivers/usb/otg
parent0fa4fab4ee46470ccd463c83be95434936942e05 (diff)
usb: otg: add device tree support to otg library
Added an API devm_usb_get_phy_by_phandle(), to get usb phy by passing a device node phandle value. This function will return a pointer to the phy on success, -EPROBE_DEFER if there is a device_node for the phandle, but the phy has not been added, or a ERR_PTR() otherwise. Cc: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r--drivers/usb/otg/otg.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index 4bb4333c9653..e1814397ca3a 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -13,7 +13,9 @@
13#include <linux/export.h> 13#include <linux/export.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/module.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/of.h>
17 19
18#include <linux/usb/otg.h> 20#include <linux/usb/otg.h>
19 21
@@ -54,6 +56,20 @@ static struct usb_phy *__usb_find_phy_dev(struct device *dev,
54 return ERR_PTR(-ENODEV); 56 return ERR_PTR(-ENODEV);
55} 57}
56 58
59static struct usb_phy *__of_usb_find_phy(struct device_node *node)
60{
61 struct usb_phy *phy;
62
63 list_for_each_entry(phy, &phy_list, head) {
64 if (node != phy->dev->of_node)
65 continue;
66
67 return phy;
68 }
69
70 return ERR_PTR(-ENODEV);
71}
72
57static void devm_usb_phy_release(struct device *dev, void *res) 73static void devm_usb_phy_release(struct device *dev, void *res)
58{ 74{
59 struct usb_phy *phy = *(struct usb_phy **)res; 75 struct usb_phy *phy = *(struct usb_phy **)res;
@@ -129,6 +145,70 @@ err0:
129} 145}
130EXPORT_SYMBOL(usb_get_phy); 146EXPORT_SYMBOL(usb_get_phy);
131 147
148 /**
149 * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
150 * @dev - device that requests this phy
151 * @phandle - name of the property holding the phy phandle value
152 * @index - the index of the phy
153 *
154 * Returns the phy driver associated with the given phandle value,
155 * after getting a refcount to it, -ENODEV if there is no such phy or
156 * -EPROBE_DEFER if there is a phandle to the phy, but the device is
157 * not yet loaded. While at that, it also associates the device with
158 * the phy using devres. On driver detach, release function is invoked
159 * on the devres data, then, devres data is freed.
160 *
161 * For use by USB host and peripheral drivers.
162 */
163struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
164 const char *phandle, u8 index)
165{
166 struct usb_phy *phy = ERR_PTR(-ENOMEM), **ptr;
167 unsigned long flags;
168 struct device_node *node;
169
170 if (!dev->of_node) {
171 dev_dbg(dev, "device does not have a device node entry\n");
172 return ERR_PTR(-EINVAL);
173 }
174
175 node = of_parse_phandle(dev->of_node, phandle, index);
176 if (!node) {
177 dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
178 dev->of_node->full_name);
179 return ERR_PTR(-ENODEV);
180 }
181
182 ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
183 if (!ptr) {
184 dev_dbg(dev, "failed to allocate memory for devres\n");
185 goto err0;
186 }
187
188 spin_lock_irqsave(&phy_lock, flags);
189
190 phy = __of_usb_find_phy(node);
191 if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
192 phy = ERR_PTR(-EPROBE_DEFER);
193 devres_free(ptr);
194 goto err1;
195 }
196
197 *ptr = phy;
198 devres_add(dev, ptr);
199
200 get_device(phy->dev);
201
202err1:
203 spin_unlock_irqrestore(&phy_lock, flags);
204
205err0:
206 of_node_put(node);
207
208 return phy;
209}
210EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
211
132/** 212/**
133 * usb_get_phy_dev - find the USB PHY 213 * usb_get_phy_dev - find the USB PHY
134 * @dev - device that requests this phy 214 * @dev - device that requests this phy