]> Pileus Git - ~andy/linux/blob - drivers/usb/otg/otg.c
Merge tag 'usb-3.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[~andy/linux] / drivers / usb / otg / otg.c
1 /*
2  * otg.c -- USB OTG utility code
3  *
4  * Copyright (C) 2004 Texas Instruments
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/export.h>
14 #include <linux/err.h>
15 #include <linux/device.h>
16 #include <linux/slab.h>
17
18 #include <linux/usb/otg.h>
19
20 static LIST_HEAD(phy_list);
21 static DEFINE_SPINLOCK(phy_lock);
22
23 static struct usb_phy *__usb_find_phy(struct list_head *list,
24         enum usb_phy_type type)
25 {
26         struct usb_phy  *phy = NULL;
27
28         list_for_each_entry(phy, list, head) {
29                 if (phy->type != type)
30                         continue;
31
32                 return phy;
33         }
34
35         return ERR_PTR(-ENODEV);
36 }
37
38 static void devm_usb_phy_release(struct device *dev, void *res)
39 {
40         struct usb_phy *phy = *(struct usb_phy **)res;
41
42         usb_put_phy(phy);
43 }
44
45 static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
46 {
47         return res == match_data;
48 }
49
50 /**
51  * devm_usb_get_phy - find the USB PHY
52  * @dev - device that requests this phy
53  * @type - the type of the phy the controller requires
54  *
55  * Gets the phy using usb_get_phy(), and associates a device with it using
56  * devres. On driver detach, release function is invoked on the devres data,
57  * then, devres data is freed.
58  *
59  * For use by USB host and peripheral drivers.
60  */
61 struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
62 {
63         struct usb_phy **ptr, *phy;
64
65         ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
66         if (!ptr)
67                 return NULL;
68
69         phy = usb_get_phy(type);
70         if (!IS_ERR(phy)) {
71                 *ptr = phy;
72                 devres_add(dev, ptr);
73         } else
74                 devres_free(ptr);
75
76         return phy;
77 }
78 EXPORT_SYMBOL(devm_usb_get_phy);
79
80 /**
81  * usb_get_phy - find the USB PHY
82  * @type - the type of the phy the controller requires
83  *
84  * Returns the phy driver, after getting a refcount to it; or
85  * -ENODEV if there is no such phy.  The caller is responsible for
86  * calling usb_put_phy() to release that count.
87  *
88  * For use by USB host and peripheral drivers.
89  */
90 struct usb_phy *usb_get_phy(enum usb_phy_type type)
91 {
92         struct usb_phy  *phy = NULL;
93         unsigned long   flags;
94
95         spin_lock_irqsave(&phy_lock, flags);
96
97         phy = __usb_find_phy(&phy_list, type);
98         if (IS_ERR(phy)) {
99                 pr_err("unable to find transceiver of type %s\n",
100                         usb_phy_type_string(type));
101                 goto err0;
102         }
103
104         get_device(phy->dev);
105
106 err0:
107         spin_unlock_irqrestore(&phy_lock, flags);
108
109         return phy;
110 }
111 EXPORT_SYMBOL(usb_get_phy);
112
113 /**
114  * devm_usb_put_phy - release the USB PHY
115  * @dev - device that wants to release this phy
116  * @phy - the phy returned by devm_usb_get_phy()
117  *
118  * destroys the devres associated with this phy and invokes usb_put_phy
119  * to release the phy.
120  *
121  * For use by USB host and peripheral drivers.
122  */
123 void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
124 {
125         int r;
126
127         r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
128         dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
129 }
130 EXPORT_SYMBOL(devm_usb_put_phy);
131
132 /**
133  * usb_put_phy - release the USB PHY
134  * @x: the phy returned by usb_get_phy()
135  *
136  * Releases a refcount the caller received from usb_get_phy().
137  *
138  * For use by USB host and peripheral drivers.
139  */
140 void usb_put_phy(struct usb_phy *x)
141 {
142         if (x)
143                 put_device(x->dev);
144 }
145 EXPORT_SYMBOL(usb_put_phy);
146
147 /**
148  * usb_add_phy - declare the USB PHY
149  * @x: the USB phy to be used; or NULL
150  * @type - the type of this PHY
151  *
152  * This call is exclusively for use by phy drivers, which
153  * coordinate the activities of drivers for host and peripheral
154  * controllers, and in some cases for VBUS current regulation.
155  */
156 int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
157 {
158         int             ret = 0;
159         unsigned long   flags;
160         struct usb_phy  *phy;
161
162         if (x->type != USB_PHY_TYPE_UNDEFINED) {
163                 dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
164                 return -EINVAL;
165         }
166
167         spin_lock_irqsave(&phy_lock, flags);
168
169         list_for_each_entry(phy, &phy_list, head) {
170                 if (phy->type == type) {
171                         ret = -EBUSY;
172                         dev_err(x->dev, "transceiver type %s already exists\n",
173                                                 usb_phy_type_string(type));
174                         goto out;
175                 }
176         }
177
178         x->type = type;
179         list_add_tail(&x->head, &phy_list);
180
181 out:
182         spin_unlock_irqrestore(&phy_lock, flags);
183         return ret;
184 }
185 EXPORT_SYMBOL(usb_add_phy);
186
187 /**
188  * usb_remove_phy - remove the OTG PHY
189  * @x: the USB OTG PHY to be removed;
190  *
191  * This reverts the effects of usb_add_phy
192  */
193 void usb_remove_phy(struct usb_phy *x)
194 {
195         unsigned long   flags;
196
197         spin_lock_irqsave(&phy_lock, flags);
198         if (x)
199                 list_del(&x->head);
200         spin_unlock_irqrestore(&phy_lock, flags);
201 }
202 EXPORT_SYMBOL(usb_remove_phy);
203
204 const char *otg_state_string(enum usb_otg_state state)
205 {
206         switch (state) {
207         case OTG_STATE_A_IDLE:
208                 return "a_idle";
209         case OTG_STATE_A_WAIT_VRISE:
210                 return "a_wait_vrise";
211         case OTG_STATE_A_WAIT_BCON:
212                 return "a_wait_bcon";
213         case OTG_STATE_A_HOST:
214                 return "a_host";
215         case OTG_STATE_A_SUSPEND:
216                 return "a_suspend";
217         case OTG_STATE_A_PERIPHERAL:
218                 return "a_peripheral";
219         case OTG_STATE_A_WAIT_VFALL:
220                 return "a_wait_vfall";
221         case OTG_STATE_A_VBUS_ERR:
222                 return "a_vbus_err";
223         case OTG_STATE_B_IDLE:
224                 return "b_idle";
225         case OTG_STATE_B_SRP_INIT:
226                 return "b_srp_init";
227         case OTG_STATE_B_PERIPHERAL:
228                 return "b_peripheral";
229         case OTG_STATE_B_WAIT_ACON:
230                 return "b_wait_acon";
231         case OTG_STATE_B_HOST:
232                 return "b_host";
233         default:
234                 return "UNDEFINED";
235         }
236 }
237 EXPORT_SYMBOL(otg_state_string);