diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-12-23 15:10:19 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-01-21 13:52:46 -0500 |
commit | 4c49a5f0ef1bc61395329ea7a9fce2893e97eaa6 (patch) | |
tree | 064349fb779ad5d628ea9f9b7b137205c7a14647 /drivers/usb/gadget | |
parent | 0062f6e56f70bd2230ba1ebd1667d1b32a1af3b2 (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.c | 72 |
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 | ||
314 | int usb_gadget_probe_driver(struct usb_gadget_driver *driver) | 314 | static 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 | |||
333 | found: | ||
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 | |||
362 | err1: | 343 | err1: |
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 | |||
351 | int 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); | ||
371 | out: | ||
372 | mutex_unlock(&udc_lock); | ||
373 | return ret; | ||
374 | } | ||
375 | EXPORT_SYMBOL_GPL(udc_attach_driver); | ||
376 | |||
377 | int 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; | ||
395 | found: | ||
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 | } |