xref: /OK3568_Linux_fs/u-boot/drivers/usb/gadget/udc/udc-core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /**
2  * udc-core.c - Core UDC Framework
3  *
4  * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
5  *
6  * Author: Felipe Balbi <balbi@ti.com>
7  *
8  * Taken from Linux Kernel v3.19-rc1 (drivers/usb/gadget/udc-core.c) and ported
9  * to uboot.
10  *
11  * commit 02e8c96627 : usb: gadget: udc: core: prepend udc_attach_driver with
12  *		       usb_
13  *
14  * SPDX-License-Identifier:     GPL-2.0
15  */
16 
17 #include <linux/compat.h>
18 #include <malloc.h>
19 #include <asm/cache.h>
20 #include <asm/dma-mapping.h>
21 #include <common.h>
22 #include <dm.h>
23 #include <dm/device-internal.h>
24 #include <linux/usb/ch9.h>
25 #include <linux/usb/gadget.h>
26 
27 /**
28  * struct usb_udc - describes one usb device controller
29  * @driver - the gadget driver pointer. For use by the class code
30  * @dev - the child device to the actual controller
31  * @gadget - the gadget. For use by the class code
32  * @list - for use by the udc class driver
33  *
34  * This represents the internal data structure which is used by the UDC-class
35  * to hold information about udc driver and gadget together.
36  */
37 struct usb_udc {
38 	struct usb_gadget_driver	*driver;
39 	struct usb_gadget		*gadget;
40 	struct device			dev;
41 	struct list_head		list;
42 };
43 
44 static struct class *udc_class;
45 static LIST_HEAD(udc_list);
46 DEFINE_MUTEX(udc_lock);
47 
48 /* ------------------------------------------------------------------------- */
49 
usb_gadget_map_request(struct usb_gadget * gadget,struct usb_request * req,int is_in)50 int usb_gadget_map_request(struct usb_gadget *gadget,
51 		struct usb_request *req, int is_in)
52 {
53 	if (req->length == 0)
54 		return 0;
55 
56 	req->dma = dma_map_single(req->buf, req->length,
57 				  is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
58 
59 	return 0;
60 }
61 EXPORT_SYMBOL_GPL(usb_gadget_map_request);
62 
usb_gadget_unmap_request(struct usb_gadget * gadget,struct usb_request * req,int is_in)63 void usb_gadget_unmap_request(struct usb_gadget *gadget,
64 		struct usb_request *req, int is_in)
65 {
66 	if (req->length == 0)
67 		return;
68 
69 	dma_unmap_single((void *)(uintptr_t)req->dma, req->length,
70 			 is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
71 }
72 EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
73 
74 /* ------------------------------------------------------------------------- */
75 
76 /**
77  * usb_gadget_giveback_request - give the request back to the gadget layer
78  * Context: in_interrupt()
79  *
80  * This is called by device controller drivers in order to return the
81  * completed request back to the gadget layer.
82  */
usb_gadget_giveback_request(struct usb_ep * ep,struct usb_request * req)83 void usb_gadget_giveback_request(struct usb_ep *ep,
84 		struct usb_request *req)
85 {
86 	req->complete(ep, req);
87 }
88 EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
89 
90 /* ------------------------------------------------------------------------- */
91 
usb_gadget_set_state(struct usb_gadget * gadget,enum usb_device_state state)92 void usb_gadget_set_state(struct usb_gadget *gadget,
93 		enum usb_device_state state)
94 {
95 	gadget->state = state;
96 }
97 EXPORT_SYMBOL_GPL(usb_gadget_set_state);
98 
99 /* ------------------------------------------------------------------------- */
100 
101 /**
102  * usb_gadget_udc_reset - notifies the udc core that bus reset occurs
103  * @gadget: The gadget which bus reset occurs
104  * @driver: The gadget driver we want to notify
105  *
106  * If the udc driver has bus reset handler, it needs to call this when the bus
107  * reset occurs, it notifies the gadget driver that the bus reset occurs as
108  * well as updates gadget state.
109  */
usb_gadget_udc_reset(struct usb_gadget * gadget,struct usb_gadget_driver * driver)110 void usb_gadget_udc_reset(struct usb_gadget *gadget,
111 		struct usb_gadget_driver *driver)
112 {
113 	driver->reset(gadget);
114 	usb_gadget_set_state(gadget, USB_STATE_DEFAULT);
115 }
116 EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
117 
118 /**
119  * usb_gadget_udc_start - tells usb device controller to start up
120  * @udc: The UDC to be started
121  *
122  * This call is issued by the UDC Class driver when it's about
123  * to register a gadget driver to the device controller, before
124  * calling gadget driver's bind() method.
125  *
126  * It allows the controller to be powered off until strictly
127  * necessary to have it powered on.
128  *
129  * Returns zero on success, else negative errno.
130  */
usb_gadget_udc_start(struct usb_udc * udc)131 static inline int usb_gadget_udc_start(struct usb_udc *udc)
132 {
133 	return udc->gadget->ops->udc_start(udc->gadget, udc->driver);
134 }
135 
136 /**
137  * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
138  * @gadget: The device we want to stop activity
139  * @driver: The driver to unbind from @gadget
140  *
141  * This call is issued by the UDC Class driver after calling
142  * gadget driver's unbind() method.
143  *
144  * The details are implementation specific, but it can go as
145  * far as powering off UDC completely and disable its data
146  * line pullups.
147  */
usb_gadget_udc_stop(struct usb_udc * udc)148 static inline void usb_gadget_udc_stop(struct usb_udc *udc)
149 {
150 	udc->gadget->ops->udc_stop(udc->gadget);
151 }
152 
153 /**
154  * usb_udc_release - release the usb_udc struct
155  * @dev: the dev member within usb_udc
156  *
157  * This is called by driver's core in order to free memory once the last
158  * reference is released.
159  */
usb_udc_release(struct device * dev)160 static void usb_udc_release(struct device *dev)
161 {
162 	struct usb_udc *udc;
163 
164 	udc = container_of(dev, struct usb_udc, dev);
165 	kfree(udc);
166 }
167 
168 /**
169  * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
170  * @parent: the parent device to this udc. Usually the controller driver's
171  * device.
172  * @gadget: the gadget to be added to the list.
173  * @release: a gadget release function.
174  *
175  * Returns zero on success, negative errno otherwise.
176  */
usb_add_gadget_udc_release(struct device * parent,struct usb_gadget * gadget,void (* release)(struct device * dev))177 int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
178 		void (*release)(struct device *dev))
179 {
180 	struct usb_udc		*udc;
181 	int			ret = -ENOMEM;
182 
183 	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
184 	if (!udc)
185 		goto err1;
186 
187 	dev_set_name(&gadget->dev, "gadget");
188 	gadget->dev.parent = parent;
189 
190 	udc->dev.release = usb_udc_release;
191 	udc->dev.class = udc_class;
192 	udc->dev.parent = parent;
193 
194 	udc->gadget = gadget;
195 
196 	mutex_lock(&udc_lock);
197 	list_add_tail(&udc->list, &udc_list);
198 
199 	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
200 
201 	mutex_unlock(&udc_lock);
202 
203 	return 0;
204 
205 err1:
206 	return ret;
207 }
208 EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
209 
210 /**
211  * usb_add_gadget_udc - adds a new gadget to the udc class driver list
212  * @parent: the parent device to this udc. Usually the controller
213  * driver's device.
214  * @gadget: the gadget to be added to the list
215  *
216  * Returns zero on success, negative errno otherwise.
217  */
usb_add_gadget_udc(struct device * parent,struct usb_gadget * gadget)218 int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
219 {
220 	return usb_add_gadget_udc_release(parent, gadget, NULL);
221 }
222 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
223 
usb_gadget_remove_driver(struct usb_udc * udc)224 static void usb_gadget_remove_driver(struct usb_udc *udc)
225 {
226 	dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
227 			udc->driver->function);
228 
229 	usb_gadget_disconnect(udc->gadget);
230 	udc->driver->disconnect(udc->gadget);
231 	udc->driver->unbind(udc->gadget);
232 	usb_gadget_udc_stop(udc);
233 
234 	udc->driver = NULL;
235 }
236 
237 /**
238  * usb_del_gadget_udc - deletes @udc from udc_list
239  * @gadget: the gadget to be removed.
240  *
241  * This, will call usb_gadget_unregister_driver() if
242  * the @udc is still busy.
243  */
usb_del_gadget_udc(struct usb_gadget * gadget)244 void usb_del_gadget_udc(struct usb_gadget *gadget)
245 {
246 	struct usb_udc		*udc = NULL;
247 
248 	mutex_lock(&udc_lock);
249 	list_for_each_entry(udc, &udc_list, list)
250 		if (udc->gadget == gadget)
251 			goto found;
252 
253 	dev_err(gadget->dev.parent, "gadget not registered.\n");
254 	mutex_unlock(&udc_lock);
255 
256 	return;
257 
258 found:
259 	dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
260 
261 	list_del(&udc->list);
262 	mutex_unlock(&udc_lock);
263 
264 	if (udc->driver)
265 		usb_gadget_remove_driver(udc);
266 }
267 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
268 
269 /* ------------------------------------------------------------------------- */
270 
271 /**
272  * usb_gadget_udc_set_speed - tells usb device controller speed supported by
273  *    current driver
274  * @udc: The device we want to set maximum speed
275  * @speed: The maximum speed to allowed to run
276  *
277  * This call is issued by the UDC Class driver before calling
278  * usb_gadget_udc_start() in order to make sure that we don't try to
279  * connect on speeds the gadget driver doesn't support.
280  */
usb_gadget_udc_set_speed(struct usb_udc * udc,enum usb_device_speed speed)281 static inline void usb_gadget_udc_set_speed(struct usb_udc *udc,
282 					    enum usb_device_speed speed)
283 {
284 	if (udc->gadget->ops->udc_set_speed) {
285 		enum usb_device_speed s;
286 
287 		s = min(speed, udc->gadget->max_speed);
288 		udc->gadget->ops->udc_set_speed(udc->gadget, s);
289 	}
290 }
291 
udc_bind_to_driver(struct usb_udc * udc,struct usb_gadget_driver * driver)292 static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
293 {
294 	int ret;
295 
296 	dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
297 			driver->function);
298 
299 	udc->driver = driver;
300 
301 	usb_gadget_udc_set_speed(udc, driver->speed);
302 
303 	ret = driver->bind(udc->gadget);
304 	if (ret)
305 		goto err1;
306 	ret = usb_gadget_udc_start(udc);
307 	if (ret) {
308 		driver->unbind(udc->gadget);
309 		goto err1;
310 	}
311 	usb_gadget_connect(udc->gadget);
312 
313 	return 0;
314 err1:
315 	if (ret != -EISNAM)
316 		dev_err(&udc->dev, "failed to start %s: %d\n",
317 			udc->driver->function, ret);
318 	udc->driver = NULL;
319 	return ret;
320 }
321 
usb_gadget_probe_driver(struct usb_gadget_driver * driver)322 int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
323 {
324 	struct usb_udc		*udc = NULL;
325 	int			ret;
326 
327 	if (!driver || !driver->bind || !driver->setup)
328 		return -EINVAL;
329 
330 	mutex_lock(&udc_lock);
331 	list_for_each_entry(udc, &udc_list, list) {
332 		/* For now we take the first one */
333 		if (!udc->driver)
334 			goto found;
335 	}
336 
337 	printf("couldn't find an available UDC\n");
338 	mutex_unlock(&udc_lock);
339 	return -ENODEV;
340 found:
341 	ret = udc_bind_to_driver(udc, driver);
342 	mutex_unlock(&udc_lock);
343 	return ret;
344 }
345 EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
346 
usb_gadget_register_driver(struct usb_gadget_driver * driver)347 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
348 {
349 	return usb_gadget_probe_driver(driver);
350 }
351 EXPORT_SYMBOL_GPL(usb_gadget_register_driver);
352 
usb_gadget_unregister_driver(struct usb_gadget_driver * driver)353 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
354 {
355 	struct usb_udc		*udc = NULL;
356 	int			ret = -ENODEV;
357 
358 	if (!driver || !driver->unbind)
359 		return -EINVAL;
360 
361 	mutex_lock(&udc_lock);
362 	list_for_each_entry(udc, &udc_list, list)
363 		if (udc->driver == driver) {
364 			usb_gadget_remove_driver(udc);
365 			usb_gadget_set_state(udc->gadget,
366 					USB_STATE_NOTATTACHED);
367 			ret = 0;
368 			break;
369 		}
370 
371 	mutex_unlock(&udc_lock);
372 	return ret;
373 }
374 EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
375 
376 MODULE_DESCRIPTION("UDC Framework");
377 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
378 MODULE_LICENSE("GPL v2");
379