aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-12-23 15:10:19 -0500
committerFelipe Balbi <balbi@ti.com>2013-01-21 13:52:46 -0500
commit4c49a5f0ef1bc61395329ea7a9fce2893e97eaa6 (patch)
tree064349fb779ad5d628ea9f9b7b137205c7a14647 /drivers/usb/gadget
parent0062f6e56f70bd2230ba1ebd1667d1b32a1af3b2 (diff)
usb: gadget: udc-core: introduce UDC binding by name
This patch adds udc_attach_driver() which allows to bind an UDC which is specified by name to a driver. The name of available UDCs can be obtained from /sys/class/udc. This interface is intended for configfs interface. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/udc-core.c72
1 files changed, 51 insertions, 21 deletions
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 4d90a800063c..e7c591621a3b 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -311,26 +311,10 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
311 311
312/* ------------------------------------------------------------------------- */ 312/* ------------------------------------------------------------------------- */
313 313
314int usb_gadget_probe_driver(struct usb_gadget_driver *driver) 314static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
315{ 315{
316 struct usb_udc *udc = NULL; 316 int ret;
317 int ret;
318
319 if (!driver || !driver->bind || !driver->setup)
320 return -EINVAL;
321 317
322 mutex_lock(&udc_lock);
323 list_for_each_entry(udc, &udc_list, list) {
324 /* For now we take the first one */
325 if (!udc->driver)
326 goto found;
327 }
328
329 pr_debug("couldn't find an available UDC\n");
330 mutex_unlock(&udc_lock);
331 return -ENODEV;
332
333found:
334 dev_dbg(&udc->dev, "registering UDC driver [%s]\n", 318 dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
335 driver->function); 319 driver->function);
336 320
@@ -352,18 +336,64 @@ found:
352 ret = usb_gadget_start(udc->gadget, driver, driver->bind); 336 ret = usb_gadget_start(udc->gadget, driver, driver->bind);
353 if (ret) 337 if (ret)
354 goto err1; 338 goto err1;
355
356 } 339 }
357 340
358 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); 341 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
359 mutex_unlock(&udc_lock);
360 return 0; 342 return 0;
361
362err1: 343err1:
363 dev_err(&udc->dev, "failed to start %s: %d\n", 344 dev_err(&udc->dev, "failed to start %s: %d\n",
364 udc->driver->function, ret); 345 udc->driver->function, ret);
365 udc->driver = NULL; 346 udc->driver = NULL;
366 udc->dev.driver = NULL; 347 udc->dev.driver = NULL;
348 return ret;
349}
350
351int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
352{
353 struct usb_udc *udc = NULL;
354 int ret = -ENODEV;
355
356 mutex_lock(&udc_lock);
357 list_for_each_entry(udc, &udc_list, list) {
358 ret = strcmp(name, dev_name(&udc->dev));
359 if (!ret)
360 break;
361 }
362 if (ret) {
363 ret = -ENODEV;
364 goto out;
365 }
366 if (udc->driver) {
367 ret = -EBUSY;
368 goto out;
369 }
370 ret = udc_bind_to_driver(udc, driver);
371out:
372 mutex_unlock(&udc_lock);
373 return ret;
374}
375EXPORT_SYMBOL_GPL(udc_attach_driver);
376
377int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
378{
379 struct usb_udc *udc = NULL;
380 int ret;
381
382 if (!driver || !driver->bind || !driver->setup)
383 return -EINVAL;
384
385 mutex_lock(&udc_lock);
386 list_for_each_entry(udc, &udc_list, list) {
387 /* For now we take the first one */
388 if (!udc->driver)
389 goto found;
390 }
391
392 pr_debug("couldn't find an available UDC\n");
393 mutex_unlock(&udc_lock);
394 return -ENODEV;
395found:
396 ret = udc_bind_to_driver(udc, driver);
367 mutex_unlock(&udc_lock); 397 mutex_unlock(&udc_lock);
368 return ret; 398 return ret;
369} 399}