diff options
Diffstat (limited to 'drivers/usb/gadget/udc-core.c')
-rw-r--r-- | drivers/usb/gadget/udc-core.c | 355 |
1 files changed, 0 insertions, 355 deletions
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c deleted file mode 100644 index 30b17dbc5a..0000000000 --- a/drivers/usb/gadget/udc-core.c +++ /dev/null @@ -1,355 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/** - * udc.c - Core UDC Framework - * - * Copyright (C) 2010 Texas Instruments - * Author: Felipe Balbi <balbi@ti.com> - */ -#define VERBOSE_DEBUG -#include <common.h> -#include <driver.h> -#include <init.h> -#include <poller.h> -#include <usb/ch9.h> -#include <usb/gadget.h> - -/** - * struct usb_udc - describes one usb device controller - * @driver - the gadget driver pointer. For use by the class code - * @dev - the child device to the actual controller - * @gadget - the gadget. For use by the class code - * @list - for use by the udc class driver - * - * This represents the internal data structure which is used by the UDC-class - * to hold information about udc driver and gadget together. - */ -struct usb_udc { - struct usb_gadget_driver *driver; - struct usb_gadget *gadget; - struct device dev; - struct list_head list; - struct poller_struct poller; -}; - -static LIST_HEAD(udc_list); - -/* ------------------------------------------------------------------------- */ - -void usb_gadget_set_state(struct usb_gadget *gadget, - enum usb_device_state state) -{ - gadget->state = state; -} -EXPORT_SYMBOL_GPL(usb_gadget_set_state); - -/** - * usb_gadget_udc_reset - notifies the udc core that bus reset occurs - * @gadget: The gadget which bus reset occurs - * @driver: The gadget driver we want to notify - * - * If the udc driver has bus reset handler, it needs to call this when the bus - * reset occurs, it notifies the gadget driver that the bus reset occurs as - * well as updates gadget state. - */ -void usb_gadget_udc_reset(struct usb_gadget *gadget, - struct usb_gadget_driver *driver) -{ - usb_gadget_set_state(gadget, USB_STATE_DEFAULT); -} -EXPORT_SYMBOL_GPL(usb_gadget_udc_reset); -/* ------------------------------------------------------------------------- */ - -/** - * usb_gadget_udc_start - tells usb device controller to start up - * @gadget: The gadget we want to get started - * @driver: The driver we want to bind to @gadget - * - * This call is issued by the UDC Class driver when it's about - * to register a gadget driver to the device controller, before - * calling gadget driver's bind() method. - * - * It allows the controller to be powered off until strictly - * necessary to have it powered on. - * - * Returns zero on success, else negative errno. - */ -static inline int usb_gadget_udc_start(struct usb_gadget *gadget, - struct usb_gadget_driver *driver) -{ - return gadget->ops->udc_start(gadget, driver); -} - -/** - * usb_gadget_udc_stop - tells usb device controller we don't need it anymore - * @gadget: The device we want to stop activity - * @driver: The driver to unbind from @gadget - * - * This call is issued by the UDC Class driver after calling - * gadget driver's unbind() method. - * - * The details are implementation specific, but it can go as - * far as powering off UDC completely and disable its data - * line pullups. - */ -static inline void usb_gadget_udc_stop(struct usb_gadget *gadget, - struct usb_gadget_driver *driver) -{ - gadget->ops->udc_stop(gadget, driver); -} - -int usb_gadget_poll(void) -{ - struct usb_udc *udc; - - list_for_each_entry(udc, &udc_list, list) { - if (udc->gadget->ops->udc_poll) - udc->gadget->ops->udc_poll(udc->gadget); - } - - return 0; -} - -/** - * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list - * @parent: the parent device to this udc. Usually the controller driver's - * device. - * @gadget: the gadget to be added to the list. - * @release: a gadget release function. - * - * Returns zero on success, negative errno otherwise. - */ -int usb_add_gadget_udc_release(struct device *parent, - struct usb_gadget *gadget, - void (*release)(struct device *dev)) -{ - struct usb_udc *udc; - int ret = -ENOMEM; - - udc = kzalloc(sizeof(*udc), GFP_KERNEL); - if (!udc) - goto err1; - - dev_set_name(&gadget->dev, "usbgadget"); - gadget->dev.id = DEVICE_ID_SINGLE; - gadget->dev.parent = parent; - - ret = register_device(&gadget->dev); - if (ret) - goto err2; - - dev_add_param_uint32(&gadget->dev, "product", NULL, NULL, - &gadget->product_id, "0x%04x", NULL); - dev_add_param_uint32(&gadget->dev, "vendor", NULL, NULL, - &gadget->vendor_id, "0x%04x", NULL); - gadget->manufacturer = xstrdup("barebox"); - dev_add_param_string(&gadget->dev, "manufacturer", NULL, NULL, - &gadget->manufacturer, NULL); - gadget->productname = xstrdup(barebox_get_model()); - dev_add_param_string(&gadget->dev, "productname", NULL, NULL, - &gadget->productname, NULL); - gadget->serialnumber = xstrdup(""); - dev_add_param_string(&gadget->dev, "serialnumber", NULL, NULL, - &gadget->serialnumber, NULL); - - dev_set_name(&udc->dev, "udc"); - udc->dev.id = DEVICE_ID_DYNAMIC; - - udc->gadget = gadget; - - list_add_tail(&udc->list, &udc_list); - - register_device(&udc->dev); - - usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); - - return 0; -err2: - kfree(udc); - -err1: - return ret; -} -EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release); - -/** - * usb_add_gadget_udc - adds a new gadget to the udc class driver list - * @parent: the parent device to this udc. Usually the controller - * driver's device. - * @gadget: the gadget to be added to the list - * - * Returns zero on success, negative errno otherwise. - */ -int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) -{ - return usb_add_gadget_udc_release(parent, gadget, NULL); -} -EXPORT_SYMBOL_GPL(usb_add_gadget_udc); - -static void usb_gadget_remove_driver(struct usb_udc *udc) -{ - dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n", - udc->gadget->name); - - if (udc->gadget->ops->udc_poll) - poller_unregister(&udc->poller); - - usb_gadget_disconnect(udc->gadget); - udc->driver->disconnect(udc->gadget); - udc->driver->unbind(udc->gadget); - usb_gadget_udc_stop(udc->gadget, NULL); - - udc->driver = NULL; - udc->dev.driver = NULL; - udc->gadget->dev.driver = NULL; -} - -/** - * usb_del_gadget_udc - deletes @udc from udc_list - * @gadget: the gadget to be removed. - * - * This, will call usb_gadget_unregister_driver() if - * the @udc is still busy. - */ -void usb_del_gadget_udc(struct usb_gadget *gadget) -{ - struct usb_udc *udc = NULL; - - list_for_each_entry(udc, &udc_list, list) - if (udc->gadget == gadget) - goto found; - - dev_err(gadget->dev.parent, "gadget not registered.\n"); - - return; - -found: - dev_vdbg(gadget->dev.parent, "unregistering gadget\n"); - - list_del(&udc->list); - - if (udc->driver) - usb_gadget_remove_driver(udc); - - unregister_device(&udc->dev); - unregister_device(&gadget->dev); -} -EXPORT_SYMBOL_GPL(usb_del_gadget_udc); - -/* ------------------------------------------------------------------------- */ - -static void udc_poll_driver(struct poller_struct *poller) -{ - struct usb_udc *udc = container_of(poller, struct usb_udc, poller); - - udc->gadget->ops->udc_poll(udc->gadget); -} - -static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver) -{ - int ret; - - dev_dbg(&udc->dev, "registering UDC driver [%s]\n", - driver->function); - - udc->driver = driver; - udc->dev.driver = &driver->driver; - udc->gadget->dev.driver = &driver->driver; - - if (udc->gadget->ops->udc_poll) { - udc->poller.func = udc_poll_driver; - ret = poller_register(&udc->poller, dev_name(&udc->dev)); - if (ret) - return ret; - } - - ret = driver->bind(udc->gadget, driver); - if (ret) - goto err1; - - ret = usb_gadget_udc_start(udc->gadget, driver); - if (ret) { - driver->unbind(udc->gadget); - goto err1; - } - usb_gadget_connect(udc->gadget); - - return 0; -err1: - if (udc->gadget->ops->udc_poll) - poller_unregister(&udc->poller); - - if (ret != -EISNAM) - dev_err(&udc->dev, "failed to start %s: %d\n", - udc->driver->function, ret); - udc->driver = NULL; - udc->dev.driver = NULL; - udc->gadget->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; - - 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: - 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; - - 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"); - - return -ENODEV; -found: - ret = udc_bind_to_driver(udc, driver); - - return ret; -} -EXPORT_SYMBOL_GPL(usb_gadget_probe_driver); - -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - struct usb_udc *udc = NULL; - int ret = -ENODEV; - - if (!driver || !driver->unbind) - return -EINVAL; - - list_for_each_entry(udc, &udc_list, list) - if (udc->driver == driver) { - usb_gadget_remove_driver(udc); - ret = 0; - break; - } - - return ret; -} -EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver); |