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>
This commit is contained in:

committed by
Felipe Balbi

parent
0062f6e56f
commit
4c49a5f0ef
@@ -311,26 +311,10 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
|
static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
|
||||||
{
|
{
|
||||||
struct usb_udc *udc = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!driver || !driver->bind || !driver->setup)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
mutex_lock(&udc_lock);
|
|
||||||
list_for_each_entry(udc, &udc_list, list) {
|
|
||||||
/* For now we take the first one */
|
|
||||||
if (!udc->driver)
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("couldn't find an available UDC\n");
|
|
||||||
mutex_unlock(&udc_lock);
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
found:
|
|
||||||
dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
|
dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
|
||||||
driver->function);
|
driver->function);
|
||||||
|
|
||||||
@@ -352,18 +336,64 @@ found:
|
|||||||
ret = usb_gadget_start(udc->gadget, driver, driver->bind);
|
ret = usb_gadget_start(udc->gadget, driver, driver->bind);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
|
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
|
||||||
mutex_unlock(&udc_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err1:
|
err1:
|
||||||
dev_err(&udc->dev, "failed to start %s: %d\n",
|
dev_err(&udc->dev, "failed to start %s: %d\n",
|
||||||
udc->driver->function, ret);
|
udc->driver->function, ret);
|
||||||
udc->driver = NULL;
|
udc->driver = NULL;
|
||||||
udc->dev.driver = NULL;
|
udc->dev.driver = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
|
||||||
|
{
|
||||||
|
struct usb_udc *udc = NULL;
|
||||||
|
int ret = -ENODEV;
|
||||||
|
|
||||||
|
mutex_lock(&udc_lock);
|
||||||
|
list_for_each_entry(udc, &udc_list, list) {
|
||||||
|
ret = strcmp(name, dev_name(&udc->dev));
|
||||||
|
if (!ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (udc->driver) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = udc_bind_to_driver(udc, driver);
|
||||||
|
out:
|
||||||
|
mutex_unlock(&udc_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(udc_attach_driver);
|
||||||
|
|
||||||
|
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
|
||||||
|
{
|
||||||
|
struct usb_udc *udc = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!driver || !driver->bind || !driver->setup)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&udc_lock);
|
||||||
|
list_for_each_entry(udc, &udc_list, list) {
|
||||||
|
/* For now we take the first one */
|
||||||
|
if (!udc->driver)
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("couldn't find an available UDC\n");
|
||||||
|
mutex_unlock(&udc_lock);
|
||||||
|
return -ENODEV;
|
||||||
|
found:
|
||||||
|
ret = udc_bind_to_driver(udc, driver);
|
||||||
mutex_unlock(&udc_lock);
|
mutex_unlock(&udc_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -880,6 +880,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
|
|||||||
|
|
||||||
extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
|
extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
|
||||||
extern void usb_del_gadget_udc(struct usb_gadget *gadget);
|
extern void usb_del_gadget_udc(struct usb_gadget *gadget);
|
||||||
|
extern int udc_attach_driver(const char *name,
|
||||||
|
struct usb_gadget_driver *driver);
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user