From 6369f322b0e8a7109fd3aa960ca2681e13f5c3e2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 09:25:04 +0200 Subject: usb: gadget: fsl_udc: Drop using global variable No need to use the global udc_controller variable when we are provided an usb_gadget. Signed-off-by: Sascha Hauer --- drivers/usb/gadget/fsl_udc.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index 9b59669773..7782d4bdd9 100644 --- a/drivers/usb/gadget/fsl_udc.c +++ b/drivers/usb/gadget/fsl_udc.c @@ -450,6 +450,11 @@ struct fsl_udc { u8 device_address; /* Device USB address */ }; +static inline struct fsl_udc *to_fsl_udc(struct usb_gadget *gadget) +{ + return container_of(gadget, struct fsl_udc, gadget); +} + /*-------------------------------------------------------------------------*/ #ifdef DEBUG @@ -1943,12 +1948,9 @@ static void dtd_complete_irq(struct fsl_udc *udc) */ static void fsl_udc_gadget_poll(struct usb_gadget *gadget) { - struct fsl_udc *udc = udc_controller; + struct fsl_udc *udc = to_fsl_udc(gadget); u32 irq_src; - if (!udc) - return; - /* Disable ISR for OTG host mode */ if (udc->stopped) return; @@ -1981,7 +1983,7 @@ static void fsl_udc_gadget_poll(struct usb_gadget *gadget) /* Sleep Enable (Suspend) */ if (irq_src & USB_STS_SUSPEND) - udc->driver->disconnect(&udc_controller->gadget); + udc->driver->disconnect(gadget); if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) printf("Error IRQ %x\n", irq_src); @@ -1993,6 +1995,8 @@ static void fsl_udc_gadget_poll(struct usb_gadget *gadget) *----------------------------------------------------------------*/ static int fsl_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { + struct fsl_udc *udc = to_fsl_udc(gadget); + /* * We currently have PHY no driver which could call vbus_connect, * so when the USB gadget core calls usb_gadget_connect() the @@ -2002,13 +2006,13 @@ static int fsl_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *dr usb_gadget_vbus_connect(gadget); /* hook up the driver */ - udc_controller->driver = driver; + udc->driver = driver; /* Enable DR IRQ reg and Set usbcmd reg Run bit */ - dr_controller_run(udc_controller); - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; + dr_controller_run(udc); + udc->usb_state = USB_STATE_ATTACHED; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = 0; return 0; } @@ -2016,20 +2020,21 @@ static int fsl_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *dr /* Disconnect from gadget driver */ static int fsl_udc_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { + struct fsl_udc *udc = to_fsl_udc(gadget); struct fsl_ep *loop_ep; /* stop DR, disable intr */ - dr_controller_stop(udc_controller); + dr_controller_stop(udc); /* in fact, no needed */ - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; + udc->usb_state = USB_STATE_ATTACHED; + udc->ep0_state = WAIT_FOR_SETUP; + udc->ep0_dir = 0; /* stand operation */ - udc_controller->gadget.speed = USB_SPEED_UNKNOWN; - nuke(&udc_controller->eps[0], -ESHUTDOWN); - list_for_each_entry(loop_ep, &udc_controller->gadget.ep_list, + udc->gadget.speed = USB_SPEED_UNKNOWN; + nuke(&udc->eps[0], -ESHUTDOWN); + list_for_each_entry(loop_ep, &udc->gadget.ep_list, ep.ep_list) nuke(loop_ep, -ESHUTDOWN); -- cgit v1.2.3 From 5d91d9982b33d00960124c120fd406594bea0f26 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 10:10:01 +0200 Subject: usb: host: ehci: rename ehci_priv to ehci_host As we are going to export the structure as a cookie to others rename it to ehci_host. Signed-off-by: Sascha Hauer --- drivers/usb/host/ehci-hcd.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9bbdda365c..c20d4392d2 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -34,7 +34,7 @@ #include "ehci.h" -struct ehci_priv { +struct ehci_host { int rootdev; struct device_d *dev; struct ehci_hccr *hccr; @@ -63,7 +63,7 @@ struct int_queue { struct qTD *tds; }; -#define to_ehci(ptr) container_of(ptr, struct ehci_priv, host) +#define to_ehci(ptr) container_of(ptr, struct ehci_host, host) #define NUM_QH 2 #define NUM_TD 3 @@ -155,7 +155,7 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) } } -static int ehci_reset(struct ehci_priv *ehci) +static int ehci_reset(struct ehci_host *ehci) { uint32_t cmd; uint32_t tmp; @@ -218,7 +218,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req, int timeout_ms) { struct usb_host *host = dev->host; - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); struct QH *qh; struct qTD *td; volatile struct qTD *vtd; @@ -460,7 +460,7 @@ fail: * boards. * See http://lists.infradead.org/pipermail/linux-arm-kernel/2011-January/037341.html */ -static void ehci_powerup_fixup(struct ehci_priv *ehci) +static void ehci_powerup_fixup(struct ehci_host *ehci) { void *viewport = (void *)ehci->hcor + 0x30; @@ -471,12 +471,12 @@ static void ehci_powerup_fixup(struct ehci_priv *ehci) viewport); } #else -static inline void ehci_powerup_fixup(struct ehci_priv *ehci) +static inline void ehci_powerup_fixup(struct ehci_host *ehci) { } #endif -static void pass_to_companion(struct ehci_priv *ehci, int port) +static void pass_to_companion(struct ehci_host *ehci, int port) { uint32_t *status_reg = (uint32_t *)&ehci->hcor->or_portsc[port - 1]; uint32_t reg = ehci_readl(status_reg); @@ -493,7 +493,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { struct usb_host *host = dev->host; - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); uint8_t tmpbuf[4]; u16 typeReq; void *srcptr = NULL; @@ -772,7 +772,7 @@ unknown: } /* force HC to halt state from unknown (EHCI spec section 2.3) */ -static int ehci_halt(struct ehci_priv *ehci) +static int ehci_halt(struct ehci_host *ehci) { u32 temp = ehci_readl(&ehci->hcor->or_usbsts); @@ -792,7 +792,7 @@ static int ehci_halt(struct ehci_priv *ehci) static int ehci_init(struct usb_host *host) { - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); uint32_t reg; uint32_t cmd; int ret = 0; @@ -902,7 +902,7 @@ submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length, int timeout) { struct usb_host *host = dev->host; - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); if (usb_pipetype(pipe) != PIPE_BULK) { dev_dbg(ehci->dev, "non-bulk pipe (type=%lu)", usb_pipetype(pipe)); @@ -916,7 +916,7 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *setup, int timeout) { struct usb_host *host = dev->host; - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); if (usb_pipetype(pipe) != PIPE_CONTROL) { dev_dbg(ehci->dev, "non-control pipe (type=%lu)", usb_pipetype(pipe)); @@ -932,7 +932,7 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, } static int -disable_periodic(struct ehci_priv *ehci) +disable_periodic(struct ehci_host *ehci) { uint32_t cmd; struct ehci_hcor *hcor = ehci->hcor; @@ -954,7 +954,7 @@ disable_periodic(struct ehci_priv *ehci) #define NEXT_QH(qh) (struct QH *)((unsigned long)hc32_to_cpu((qh)->qh_link) & ~0x1f) static int -enable_periodic(struct ehci_priv *ehci) +enable_periodic(struct ehci_host *ehci) { uint32_t cmd; struct ehci_hcor *hcor = ehci->hcor; @@ -1018,7 +1018,7 @@ static struct int_queue *ehci_create_int_queue(struct usb_device *dev, void *buffer, int interval) { struct usb_host *host = dev->host; - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); struct int_queue *result = NULL; uint32_t i; struct QH *list = ehci->periodic_queue; @@ -1187,7 +1187,7 @@ static int ehci_destroy_int_queue(struct usb_device *dev, { int result = -EINVAL; struct usb_host *host = dev->host; - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); struct QH *cur = ehci->periodic_queue; if (disable_periodic(ehci) < 0) { @@ -1230,7 +1230,7 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length, int interval) { struct usb_host *host = dev->host; - struct ehci_priv *ehci = to_ehci(host); + struct ehci_host *ehci = to_ehci(host); struct int_queue *queue; uint64_t start; void *backbuffer; @@ -1275,7 +1275,7 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, static int ehci_detect(struct device_d *dev) { - struct ehci_priv *ehci = dev->priv; + struct ehci_host *ehci = dev->priv; return usb_host_detect(&ehci->host); } @@ -1283,10 +1283,10 @@ static int ehci_detect(struct device_d *dev) int ehci_register(struct device_d *dev, struct ehci_data *data) { struct usb_host *host; - struct ehci_priv *ehci; + struct ehci_host *ehci; uint32_t reg; - ehci = xzalloc(sizeof(struct ehci_priv)); + ehci = xzalloc(sizeof(struct ehci_host)); host = &ehci->host; dev->priv = ehci; ehci->flags = data->flags; @@ -1369,7 +1369,7 @@ static int ehci_probe(struct device_d *dev) static void ehci_remove(struct device_d *dev) { - struct ehci_priv *ehci = dev->priv; + struct ehci_host *ehci = dev->priv; ehci_halt(ehci); } -- cgit v1.2.3 From e44fddbd8965f40e09082763013da2957f8bc8e0 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 10:14:57 +0200 Subject: usb: Add usb_unregister_host() We have usb_register_host() which puts a new host on the list of hosts we should also have the opposite which removes the host from the list again. Signed-off-by: Sascha Hauer --- drivers/usb/core/usb.c | 5 +++++ include/usb/usb.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 70ded6ded1..1e48c1d0a8 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -102,6 +102,11 @@ int usb_register_host(struct usb_host *host) return 0; } +void usb_unregister_host(struct usb_host *host) +{ + list_del(&host->list); +} + /** * set configuration number to configuration */ diff --git a/include/usb/usb.h b/include/usb/usb.h index 9aab06c87c..eb2eeb8db3 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -157,6 +157,7 @@ struct usb_host { }; int usb_register_host(struct usb_host *); +void usb_unregister_host(struct usb_host *host); int usb_host_detect(struct usb_host *host); -- cgit v1.2.3 From e3eb0c729bc2e3dac0e0dfb0a04be40bfcffcf1c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 10:35:03 +0200 Subject: usb: host: ehci: add ehci_unregister() ehci_register() allocates data and registers a ehci host. Add ehci_unregister() to properly halt the controller and to free the memory again.. To do so, change ehci_register() to return the ehci host rather than an error code. Signed-off-by: Sascha Hauer --- drivers/usb/host/ehci-atmel.c | 10 +++++++++- drivers/usb/host/ehci-hcd.c | 23 +++++++++++++++++++---- drivers/usb/imx/chipidea-imx.c | 11 ++++++++--- include/usb/ehci.h | 14 +++++++++++--- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 1132879c9b..bfa235d954 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -30,6 +30,7 @@ #include "ehci.h" struct atmel_ehci_priv { + struct ehci_host *ehci; struct device_d *dev; struct clk *iclk; struct clk *uclk; @@ -66,6 +67,7 @@ static int atmel_ehci_probe(struct device_d *dev) struct ehci_data data; struct atmel_ehci_priv *atehci; const char *uclk_name; + struct ehci_host *ehci; uclk_name = (dev->device_node) ? "usb_clk" : "uhpck"; @@ -99,7 +101,13 @@ static int atmel_ehci_probe(struct device_d *dev) return PTR_ERR(iores); data.hccr = IOMEM(iores->start); - return ehci_register(dev, &data); + ehci = ehci_register(dev, &data); + if (IS_ERR(ehci)) + return PTR_ERR(ehci); + + atehci->ehci = ehci; + + return 0; } static void atmel_ehci_remove(struct device_d *dev) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c20d4392d2..59268bf5ec 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1280,7 +1280,7 @@ static int ehci_detect(struct device_d *dev) return usb_host_detect(&ehci->host); } -int ehci_register(struct device_d *dev, struct ehci_data *data) +struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data) { struct usb_host *host; struct ehci_host *ehci; @@ -1328,7 +1328,16 @@ int ehci_register(struct device_d *dev, struct ehci_data *data) reg = HC_VERSION(ehci_readl(&ehci->hccr->cr_capbase)); dev_info(dev, "USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); - return 0; + return ehci; +} + +void ehci_unregister(struct ehci_host *ehci) +{ + ehci_halt(ehci); + + usb_unregister_host(&ehci->host); + + free(ehci); } static int ehci_probe(struct device_d *dev) @@ -1337,6 +1346,7 @@ static int ehci_probe(struct device_d *dev) struct ehci_data data = {}; struct ehci_platform_data *pdata = dev->platform_data; struct device_node *dn = dev->device_node; + struct ehci_host *ehci; if (pdata) data.flags = pdata->flags; @@ -1364,13 +1374,18 @@ static int ehci_probe(struct device_d *dev) else data.hcor = NULL; - return ehci_register(dev, &data); + ehci = ehci_register(dev, &data); + if (IS_ERR(ehci)) + return PTR_ERR(ehci); + + return 0; } static void ehci_remove(struct device_d *dev) { struct ehci_host *ehci = dev->priv; - ehci_halt(ehci); + + ehci_unregister(ehci); } static __maybe_unused struct of_device_id ehci_platform_dt_ids[] = { diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 3e3e6a365f..a8914e25b6 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -46,6 +46,7 @@ struct imx_chipidea { struct phy *phy; struct usb_phy *usbphy; struct clk *clk; + struct ehci_host *ehci; }; static int imx_chipidea_port_init(void *drvdata) @@ -184,14 +185,18 @@ static int ci_register_role(struct imx_chipidea *ci) if (ci->mode == IMX_USB_MODE_HOST) { if (IS_ENABLED(CONFIG_USB_EHCI)) { + struct ehci_host *ehci; + ci->role_registered = IMX_USB_MODE_HOST; ret = regulator_enable(ci->vbus); if (ret) return ret; - ret = ehci_register(ci->dev, &ci->data); - if (!ret) - return 0; + ehci = ehci_register(ci->dev, &ci->data); + if (IS_ERR(ehci)) + return PTR_ERR(ehci); + + ci->ehci = ehci; regulator_disable(ci->vbus); } else { diff --git a/include/usb/ehci.h b/include/usb/ehci.h index 1008e92f02..327500d49a 100644 --- a/include/usb/ehci.h +++ b/include/usb/ehci.h @@ -19,12 +19,20 @@ struct ehci_data { void *drvdata; }; +struct ehci_host; + #ifdef CONFIG_USB_EHCI -int ehci_register(struct device_d *dev, struct ehci_data *data); +struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data); +void ehci_unregister(struct ehci_host *); #else -static inline int ehci_register(struct device_d *dev, struct ehci_data *data) +static inline struct ehci_host *ehci_register(struct device_d *dev, + struct ehci_data *data) +{ + return ERR_PTR(-ENOSYS); +} + +static inline void ehci_unregister(struct ehci_host *ehci) { - return -ENOSYS; } #endif -- cgit v1.2.3 From 610a2b2b696268f00d798e68db51a2cf90642648 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 10:50:19 +0200 Subject: usb: host: ehci: do not use dev->priv An ehci can be registered with ehci_register which is passed a struct device_d *. In that case the priv pointer may already be used by the caller, so we must not use it in the ehci code. At least for the Atmel ehci driver this fixes a bug, here dev->priv is set two times to different values. Since we need dev->priv in the ehci code to get the controller in ehci_detect() we can no longer implement that without the help of the caller, hence we eport ehci_detect() and epect it to be called by the code which registers a ehci host. Signed-off-by: Sascha Hauer --- drivers/usb/host/ehci-atmel.c | 8 ++++++++ drivers/usb/host/ehci-hcd.c | 17 +++++++++++------ drivers/usb/imx/chipidea-imx.c | 10 ++++++++++ include/usb/ehci.h | 6 ++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index bfa235d954..36c9166e74 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -60,6 +60,13 @@ static void atmel_stop_clock(struct atmel_ehci_priv *atehci) clk_disable(atehci->uclk); } +static int atmel_ehci_detect(struct device_d *dev) +{ + struct atmel_ehci_priv *atehci = dev->priv; + + return ehci_detect(atehci->ehci); +} + static int atmel_ehci_probe(struct device_d *dev) { int ret; @@ -74,6 +81,7 @@ static int atmel_ehci_probe(struct device_d *dev) atehci = xzalloc(sizeof(*atehci)); atehci->dev = dev; dev->priv = atehci; + dev->detect = atmel_ehci_detect; atehci->iclk = clk_get(dev, "ehci_clk"); if (IS_ERR(atehci->iclk)) { diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 59268bf5ec..87af95d2ed 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1273,10 +1273,8 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return result; } -static int ehci_detect(struct device_d *dev) +int ehci_detect(struct ehci_host *ehci) { - struct ehci_host *ehci = dev->priv; - return usb_host_detect(&ehci->host); } @@ -1288,7 +1286,6 @@ struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data) ehci = xzalloc(sizeof(struct ehci_host)); host = &ehci->host; - dev->priv = ehci; ehci->flags = data->flags; ehci->hccr = data->hccr; ehci->dev = dev; @@ -1321,8 +1318,6 @@ struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data) ehci_reset(ehci); } - dev->detect = ehci_detect; - usb_register_host(host); reg = HC_VERSION(ehci_readl(&ehci->hccr->cr_capbase)); @@ -1340,6 +1335,13 @@ void ehci_unregister(struct ehci_host *ehci) free(ehci); } +static int ehci_dev_detect(struct device_d *dev) +{ + struct ehci_host *ehci = dev->priv; + + return ehci_detect(ehci); +} + static int ehci_probe(struct device_d *dev) { struct resource *iores; @@ -1378,6 +1380,9 @@ static int ehci_probe(struct device_d *dev) if (IS_ERR(ehci)) return PTR_ERR(ehci); + dev->priv = ehci; + dev->detect = ehci_dev_detect; + return 0; } diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index a8914e25b6..321a8ada3f 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -176,6 +176,13 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci) return 0; } +static int ci_ehci_detect(struct device_d *dev) +{ + struct imx_chipidea *ci = dev->priv; + + return ehci_detect(ci->ehci); +} + static int ci_register_role(struct imx_chipidea *ci) { int ret; @@ -198,6 +205,8 @@ static int ci_register_role(struct imx_chipidea *ci) ci->ehci = ehci; + ci->dev->detect = ci_ehci_detect; + regulator_disable(ci->vbus); } else { dev_err(ci->dev, "Host support not available\n"); @@ -271,6 +280,7 @@ static int imx_chipidea_probe(struct device_d *dev) ci = xzalloc(sizeof(*ci)); ci->dev = dev; + dev->priv = ci; ci->role_registered = IMX_USB_MODE_OTG; if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) { diff --git a/include/usb/ehci.h b/include/usb/ehci.h index 327500d49a..9ca9252eb1 100644 --- a/include/usb/ehci.h +++ b/include/usb/ehci.h @@ -24,6 +24,7 @@ struct ehci_host; #ifdef CONFIG_USB_EHCI struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data); void ehci_unregister(struct ehci_host *); +int ehci_detect(struct ehci_host *ehci); #else static inline struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data) @@ -34,6 +35,11 @@ static inline struct ehci_host *ehci_register(struct device_d *dev, static inline void ehci_unregister(struct ehci_host *ehci) { } + +static inline int ehci_detect(struct ehci_host *ehci) +{ + return 0; +} #endif #endif /* __USB_EHCI_H */ -- cgit v1.2.3 From 94f808bafaac85bdceb70d74375549eaddcc209c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 10:52:27 +0200 Subject: usb: host: ehci-atmel: unregister host on device remove The ehci code does DMA and really must be properly stopped when we leave barebox, so call ehci_unregister on device removal. Signed-off-by: Sascha Hauer --- drivers/usb/host/ehci-atmel.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 36c9166e74..6c88d646c9 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -120,10 +120,14 @@ static int atmel_ehci_probe(struct device_d *dev) static void atmel_ehci_remove(struct device_d *dev) { + struct atmel_ehci_priv *atehci = dev->priv; + + ehci_unregister(atehci->ehci); + /* * Stop the USB clocks. */ - atmel_stop_clock(dev->priv); + atmel_stop_clock(atehci); } static const struct of_device_id atmel_ehci_dt_ids[] = { -- cgit v1.2.3 From 7da5b5cd93050ce264ba36556f2f2720a0a39acd Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 11:19:49 +0200 Subject: usb: imx: unregister ehci controller on device removal ehci does DMA and hence must be properly quiesced before we leave barebox. Call ehci_unregister() on device removal when we previously registered a ehci controller. Signed-off-by: Sascha Hauer --- drivers/usb/imx/chipidea-imx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 321a8ada3f..7bf2ef76c5 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -364,6 +364,11 @@ static int imx_chipidea_probe(struct device_d *dev) static void imx_chipidea_remove(struct device_d *dev) { + struct imx_chipidea *ci = dev->priv; + + if (ci->ehci) + ehci_unregister(ci->ehci); + if (IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC)) ci_udc_unregister(); } -- cgit v1.2.3 From 28b38c1804d761257397f41ae2bbc071cd009935 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Oct 2018 10:57:00 +0200 Subject: usb: gadget: fsl_udc: pass controller instance to unregister ci_udc_unregister() used to unregister "the controller". Since we may register multiple chipidea devices we called ci_udc_unregister() for each of them. This led to messages like: ERROR: imx-usb 53f80000.usb: gadget not registered. Fix this by returning the registered controller. This allows us to call ci_udc_unregister() only when we actually registered one before. Signed-off-by: Sascha Hauer --- drivers/usb/gadget/fsl_udc.c | 30 ++++++++++++++++++++---------- drivers/usb/imx/chipidea-imx.c | 13 ++++++++++--- include/usb/fsl_usb2.h | 6 ++++-- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index 7782d4bdd9..061ee5185f 100644 --- a/drivers/usb/gadget/fsl_udc.c +++ b/drivers/usb/gadget/fsl_udc.c @@ -528,7 +528,6 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) #define get_pipe_by_ep(EP) (ep_index(EP) * 2 + ep_is_in(EP)) static struct usb_dr_device __iomem *dr_regs; -static struct fsl_udc *udc_controller = NULL; static const struct usb_endpoint_descriptor fsl_ep0_desc = { @@ -2226,8 +2225,9 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index, return 0; } -int ci_udc_register(struct device_d *dev, void __iomem *regs) +struct fsl_udc *ci_udc_register(struct device_d *dev, void __iomem *regs) { + struct fsl_udc *udc_controller; int ret, i; u32 dccparams; @@ -2293,31 +2293,41 @@ int ci_udc_register(struct device_d *dev, void __iomem *regs) if (ret) goto err_out; - return 0; + return udc_controller; err_out: - return ret; + free(udc_controller); + + return ERR_PTR(ret); } -void ci_udc_unregister(void) +void ci_udc_unregister(struct fsl_udc *udc) { - if (udc_controller) - usb_del_gadget_udc(&udc_controller->gadget); - + usb_del_gadget_udc(&udc->gadget); + free(udc); } static int fsl_udc_probe(struct device_d *dev) { + struct fsl_udc *udc; void __iomem *regs = dev_request_mem_region(dev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); - return ci_udc_register(dev, regs); + udc = ci_udc_register(dev, regs); + if (IS_ERR(udc)) + return PTR_ERR(udc); + + dev->priv = udc; + + return 0; } static void fsl_udc_remove(struct device_d *dev) { - ci_udc_unregister(); + struct fsl_udc *udc = dev->priv; + + ci_udc_unregister(udc); } static struct driver_d fsl_udc_driver = { diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 7bf2ef76c5..8792217706 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -47,6 +47,7 @@ struct imx_chipidea { struct usb_phy *usbphy; struct clk *clk; struct ehci_host *ehci; + struct fsl_udc *udc; }; static int imx_chipidea_port_init(void *drvdata) @@ -216,8 +217,14 @@ static int ci_register_role(struct imx_chipidea *ci) if (ci->mode == IMX_USB_MODE_DEVICE) { if (IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC)) { + struct fsl_udc *udc; ci->role_registered = IMX_USB_MODE_DEVICE; - return ci_udc_register(ci->dev, ci->base); + + udc = ci_udc_register(ci->dev, ci->base); + if (IS_ERR(udc)) + return PTR_ERR(udc); + + ci->udc = udc; } else { dev_err(ci->dev, "USB device support not available\n"); return -ENODEV; @@ -369,8 +376,8 @@ static void imx_chipidea_remove(struct device_d *dev) if (ci->ehci) ehci_unregister(ci->ehci); - if (IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC)) - ci_udc_unregister(); + if (IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC) && ci->udc) + ci_udc_unregister(ci->udc); } static __maybe_unused struct of_device_id imx_chipidea_dt_ids[] = { diff --git a/include/usb/fsl_usb2.h b/include/usb/fsl_usb2.h index 881a5d4fdf..39757f71ad 100644 --- a/include/usb/fsl_usb2.h +++ b/include/usb/fsl_usb2.h @@ -23,7 +23,9 @@ struct fsl_usb2_platform_data { unsigned int port_enables; }; -int ci_udc_register(struct device_d *dev, void __iomem *regs); -void ci_udc_unregister(void); +struct fsl_udc; + +struct fsl_udc *ci_udc_register(struct device_d *dev, void __iomem *regs); +void ci_udc_unregister(struct fsl_udc *); #endif /* __USB_FSL_USB2_H */ -- cgit v1.2.3 From eb188069f36a1250d5b2b668ae589e73256135d9 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Wed, 24 Oct 2018 22:41:47 +0200 Subject: usb: gadget: set maxpacket_limit Gadget update to 3.15 imported Linux patch e117e742d310 ("usb: gadget: add "maxpacket_limit" field to struct usb_ep"): This patch adds "maxpacket_limit" to struct usb_ep. This field contains maximum value of maxpacket supported by driver, and is set in driver probe. This value should be used by autoconfig() function, because value of field "maxpacket" is set to value from endpoint descriptor when endpoint becomes enabled. So when autoconfig() function will be called again for this endpoint, "maxpacket" value will contain wMaxPacketSize from descriptior instead of maximum packet size for this endpoint. For this reason this patch adds new field "maxpacket_limit" which contains value of maximum packet size (which defines maximum endpoint capabilities). This value is used in ep_matches() function used by autoconfig(). Value of "maxpacket_limit" should be set in UDC driver probe function, using usb_ep_set_maxpacket_limit() function, defined in gadget.h. This function set choosen value to both "maxpacket_limit" and "maxpacket" fields. However said update didn't bring in all driver changes. Do it now. Fixes: 2776d53d7ac8 ("USB: gadget: Update to 3.15") Signed-off-by: Ladislav Michl Signed-off-by: Sascha Hauer --- drivers/usb/gadget/at91_udc.c | 2 +- drivers/usb/gadget/fsl_udc.c | 3 ++- drivers/usb/gadget/pxa27x_udc.c | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 18427114d1..d3fbcda214 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -619,7 +619,7 @@ static void udc_reinit(struct at91_udc *udc) ep->desc = NULL; ep->stopped = 0; ep->fifo_bank = 0; - ep->ep.maxpacket = ep->maxpacket; + usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket); ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i); /* initialize one queue per endpoint */ INIT_LIST_HEAD(&ep->queue); diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index 061ee5185f..705f6c0ba7 100644 --- a/drivers/usb/gadget/fsl_udc.c +++ b/drivers/usb/gadget/fsl_udc.c @@ -2275,7 +2275,8 @@ struct fsl_udc *ci_udc_register(struct device_d *dev, void __iomem *regs) * for other eps, gadget layer called ep_enable with defined desc */ udc_controller->eps[0].desc = &fsl_ep0_desc; - udc_controller->eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD; + usb_ep_set_maxpacket_limit(&udc_controller->eps[0].ep, + USB_MAX_CTRL_PAYLOAD); /* setup the udc->eps[] for non-control endpoints and link * to gadget.ep_list */ diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 4e6b858868..442c90ca05 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -940,9 +940,12 @@ static __init void udc_init_data(struct pxa_udc *dev) } /* USB endpoints init */ - for (i = 1; i < NR_USB_ENDPOINTS; i++) + for (i = 1; i < NR_USB_ENDPOINTS; i++) { list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list, &dev->gadget.ep_list); + usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep, + dev->udc_usb_ep[i].usb_ep.maxpacket); + } } static void udc_enable(struct pxa_udc *udc) -- cgit v1.2.3 From 3e24dfe93d85e699c1510b795810382099167521 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Fri, 26 Oct 2018 17:35:08 +0200 Subject: Documentation: USB gadget: document usbgadget.fastboot_bbu variable Signed-off-by: Ladislav Michl Signed-off-by: Sascha Hauer --- Documentation/user/usb.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst index 8396f3897c..b89d46bb6c 100644 --- a/Documentation/user/usb.rst +++ b/Documentation/user/usb.rst @@ -266,3 +266,5 @@ USB Gadget autostart Options See :ref:`command_usbgadget` -a. (Default 0). ``global.usbgadget.fastboot_function`` Function description for fastboot. See :ref:`command_usbgadget` -A [desc]. +``global.usbgadget.fastboot_bbu`` + Export barebox update handlers. See :ref:`command_usbgadget` -b. (Default 0). -- cgit v1.2.3 From 44add42d43300a330647704141c5a285358361db Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Fri, 26 Oct 2018 17:39:10 +0200 Subject: usbgadget: autostart: add DFU support Use global variable dfu_function to autostart DFU. As similar code is used to start multifunction gadget using command, move common code to common/usbgadget.c and consolidate it. It turned out that '-s' option of usbgadget command does nothing, so remove its help text and make it function as '-a'. Signed-off-by: Ladislav Michl Signed-off-by: Sascha Hauer --- Documentation/user/usb.rst | 2 + commands/Kconfig | 1 - commands/usbgadget.c | 72 ++++----------------- common/Kconfig | 7 ++ common/Makefile | 1 + common/usbgadget.c | 144 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/Kconfig | 8 +-- drivers/usb/gadget/Makefile | 1 - drivers/usb/gadget/autostart.c | 98 ---------------------------- include/usb/gadget-multi.h | 4 ++ 10 files changed, 172 insertions(+), 166 deletions(-) create mode 100644 common/usbgadget.c delete mode 100644 drivers/usb/gadget/autostart.c diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst index b89d46bb6c..029e463540 100644 --- a/Documentation/user/usb.rst +++ b/Documentation/user/usb.rst @@ -264,6 +264,8 @@ USB Gadget autostart Options ``global.usbgadget.acm`` Boolean flag. If set to 1, CDC ACM function will be created. See :ref:`command_usbgadget` -a. (Default 0). +``global.usbgadget.dfu_function`` + Function description for DFU. See :ref:`command_usbgadget` -D [desc]. ``global.usbgadget.fastboot_function`` Function description for fastboot. See :ref:`command_usbgadget` -A [desc]. ``global.usbgadget.fastboot_bbu`` diff --git a/commands/Kconfig b/commands/Kconfig index 675bd1ca76..1de4b9d604 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -1910,7 +1910,6 @@ config CMD_USB config CMD_USBGADGET bool depends on USB_GADGET - select FILE_LIST prompt "usbgadget" config CMD_WD diff --git a/commands/usbgadget.c b/commands/usbgadget.c index a1744cbe13..e8e1e9adac 100644 --- a/commands/usbgadget.c +++ b/commands/usbgadget.c @@ -32,30 +32,26 @@ static int do_usbgadget(int argc, char *argv[]) { - int opt, ret; - int acm = 1, create_serial = 0, fastboot_set = 0, fastboot_export_bbu = 0; + int opt; + bool acm = false, dfu = false, fastboot = false, export_bbu = false; const char *fastboot_opts = NULL, *dfu_opts = NULL; - struct f_multi_opts *opts; - while ((opt = getopt(argc, argv, "asdA::D:b")) > 0) { + while ((opt = getopt(argc, argv, "asdA::D::b")) > 0) { switch (opt) { case 'a': - acm = 1; - create_serial = 1; - break; case 's': - acm = 0; - create_serial = 1; + acm = true; break; case 'D': + dfu = true; dfu_opts = optarg; break; case 'A': + fastboot = true; fastboot_opts = optarg; - fastboot_set = 1; break; case 'b': - fastboot_export_bbu = 1; + export_bbu = true; break; case 'd': usb_multi_unregister(); @@ -65,54 +61,8 @@ static int do_usbgadget(int argc, char *argv[]) } } - if (fastboot_set && !fastboot_opts) - fastboot_opts = getenv("global.usbgadget.fastboot_function"); - - if (!dfu_opts && !fastboot_opts && !create_serial) - return COMMAND_ERROR_USAGE; - - /* - * Creating a gadget with both DFU and Fastboot doesn't work. - * Both client tools seem to assume that the device only has - * a single configuration - */ - if (fastboot_opts && dfu_opts) { - printf("Only one of Fastboot and DFU allowed\n"); - return -EINVAL; - } - - opts = xzalloc(sizeof(*opts)); - opts->release = usb_multi_opts_release; - - if (fastboot_opts) { - opts->fastboot_opts.files = file_list_parse(fastboot_opts); - if (IS_ERR(opts->fastboot_opts.files)) - goto err_parse; - opts->fastboot_opts.export_bbu = fastboot_export_bbu; - } - - if (dfu_opts) { - opts->dfu_opts.files = file_list_parse(dfu_opts); - if (IS_ERR(opts->dfu_opts.files)) - goto err_parse; - } - - if (create_serial) { - opts->create_acm = acm; - } - - ret = usb_multi_register(opts); - if (ret) - usb_multi_opts_release(opts); - - return ret; - -err_parse: - printf("Cannot parse file list \"%s\": %s\n", fastboot_opts, strerrorp(opts->fastboot_opts.files)); - - free(opts); - - return 1; + return usbgadget_register(dfu, dfu_opts, fastboot, fastboot_opts, acm, + export_bbu); } BAREBOX_CMD_HELP_START(usbgadget) @@ -120,11 +70,11 @@ BAREBOX_CMD_HELP_TEXT("Enable / disable a USB composite gadget on the USB device BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-a\t", "Create CDC ACM function") -BAREBOX_CMD_HELP_OPT ("-s\t", "Create Generic Serial function") BAREBOX_CMD_HELP_OPT ("-A ", "Create Android Fastboot function. If 'desc' is not provided, " "try to use 'global.usbgadget.fastboot_function' variable.") BAREBOX_CMD_HELP_OPT ("-b\t", "include registered barebox update handlers (fastboot specific)") -BAREBOX_CMD_HELP_OPT ("-D ", "Create DFU function") +BAREBOX_CMD_HELP_OPT ("-D ", "Create DFU function. If 'desc' is not provided, " + "try to use 'global.usbgadget.dfu_function' variable.") BAREBOX_CMD_HELP_OPT ("-d\t", "Disable the currently running gadget") BAREBOX_CMD_HELP_END diff --git a/common/Kconfig b/common/Kconfig index 4909c82322..4e5f4a72ee 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -115,6 +115,13 @@ config UBIFORMAT depends on MTD_UBI default y +config USBGADGET_START + bool + depends on CMD_USBGADGET || USB_GADGET_AUTOSTART + select ENVIRONMENT_VARIABLES + select FILE_LIST + default y + config BOOT bool diff --git a/common/Makefile b/common/Makefile index 13920cc5a6..2b0f4cc988 100644 --- a/common/Makefile +++ b/common/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_UBIFORMAT) += ubiformat.o obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o obj-$(CONFIG_BOOT) += boot.o obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o +obj-$(CONFIG_USBGADGET_START) += usbgadget.o ifdef CONFIG_PASSWORD diff --git a/common/usbgadget.c b/common/usbgadget.c new file mode 100644 index 0000000000..a8f104cf1c --- /dev/null +++ b/common/usbgadget.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2017 Oleksij Rempel , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#define pr_fmt(fmt) "usbgadget: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int autostart; +static int acm; +static char *dfu_function; +static char *fastboot_function; +static int fastboot_bbu; + +static struct file_list *parse(const char *files) +{ + struct file_list *list = file_list_parse(files); + if (IS_ERR(list)) { + pr_err("Parsing file list \"%s\" failed: %s\n", files, + strerrorp(list)); + return NULL; + } + return list; +} + +int usbgadget_register(bool dfu, const char *dfu_opts, + bool fastboot, const char *fastboot_opts, + bool acm, bool export_bbu) +{ + int ret; + struct device_d *dev; + struct f_multi_opts *opts; + + if (dfu && !dfu_opts && dfu_function && *dfu_function) + dfu_opts = dfu_function; + + if (fastboot && !fastboot_opts && + fastboot_function && *fastboot_function) + fastboot_opts = fastboot_function; + + if (!dfu_opts && !fastboot_opts && !acm) + return COMMAND_ERROR_USAGE; + + /* + * Creating a gadget with both DFU and Fastboot doesn't work. + * Both client tools seem to assume that the device only has + * a single configuration + */ + if (fastboot_opts && dfu_opts) { + pr_err("Only one of Fastboot and DFU allowed\n"); + return -EINVAL; + } + + opts = xzalloc(sizeof(*opts)); + opts->release = usb_multi_opts_release; + + if (fastboot_opts) { + opts->fastboot_opts.files = parse(fastboot_opts); + opts->fastboot_opts.export_bbu = export_bbu; + } + + if (dfu_opts) + opts->dfu_opts.files = parse(dfu_opts); + + if (!opts->dfu_opts.files && !opts->fastboot_opts.files && !acm) { + pr_warn("No functions to register\n"); + free(opts); + return 0; + } + + opts->create_acm = acm; + + dev = get_device_by_name("otg"); + if (dev) + dev_set_param(dev, "mode", "peripheral"); + + ret = usb_multi_register(opts); + if (ret) + usb_multi_opts_release(opts); + + return ret; +} + +static int usbgadget_autostart(void) +{ + if (!IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART) || !autostart) + return 0; + + return usbgadget_register(true, NULL, true, NULL, acm, fastboot_bbu); +} +postenvironment_initcall(usbgadget_autostart); + +static int usbgadget_globalvars_init(void) +{ + if (IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART)) { + globalvar_add_simple_bool("usbgadget.autostart", &autostart); + globalvar_add_simple_bool("usbgadget.acm", &acm); + globalvar_add_simple_bool("usbgadget.fastboot_bbu", + &fastboot_bbu); + } + globalvar_add_simple_string("usbgadget.dfu_function", &dfu_function); + globalvar_add_simple_string("usbgadget.fastboot_function", + &fastboot_function); + + return 0; +} +device_initcall(usbgadget_globalvars_init); + +BAREBOX_MAGICVAR_NAMED(global_usbgadget_autostart, + global.usbgadget.autostart, + "usbgadget: Automatically start usbgadget on boot"); +BAREBOX_MAGICVAR_NAMED(global_usbgadget_acm, + global.usbgadget.acm, + "usbgadget: Create CDC ACM function"); +BAREBOX_MAGICVAR_NAMED(global_usbgadget_dfu_function, + global.usbgadget.dfu_function, + "usbgadget: Create DFU function"); +BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_function, + global.usbgadget.fastboot_function, + "usbgadget: Create Android Fastboot function"); +BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_bbu, + global.usbgadget.fastboot_bbu, + "usbgadget: export barebox update handlers via fastboot"); diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b0408e3bbe..ca1bfc1b4e 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -33,13 +33,11 @@ config USB_GADGET_DRIVER_PXA27X config USB_GADGET_AUTOSTART bool default y - select ENVIRONMENT_VARIABLES - select FILE_LIST prompt "Automatically start usbgadget on boot" help - Enabling this option allows to automatically start a fastboot - gadget during boot. This behaviour is controlled with the - global.usbgadget.fastboot_function variable. + Enabling this option allows to automatically start a dfu or + fastboot gadget during boot. This behaviour is controlled with + the global.usbgadget.{dfu,fastboot}_function variable. comment "USB Gadget drivers" diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index e74cf02664..9ef594575b 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -1,6 +1,5 @@ obj-$(CONFIG_USB_GADGET) += composite.o config.o usbstring.o epautoconf.o udc-core.o functions.o config.o multi.o -obj-$(CONFIG_USB_GADGET_AUTOSTART) += autostart.o obj-$(CONFIG_USB_GADGET_SERIAL) += u_serial.o serial.o f_serial.o f_acm.o obj-$(CONFIG_USB_GADGET_DFU) += dfu.o obj-$(CONFIG_USB_GADGET_FASTBOOT) += f_fastboot.o diff --git a/drivers/usb/gadget/autostart.c b/drivers/usb/gadget/autostart.c deleted file mode 100644 index f640a9667d..0000000000 --- a/drivers/usb/gadget/autostart.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2017 Oleksij Rempel , Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#define pr_fmt(fmt) "usbgadget autostart: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int autostart; -static int acm; -static char *fastboot_function; -static int fastboot_bbu; - -static int usbgadget_autostart(void) -{ - struct f_multi_opts *opts; - int ret; - - if (!autostart) - return 0; - - opts = xzalloc(sizeof(*opts)); - opts->release = usb_multi_opts_release; - - if (fastboot_function) { - opts->fastboot_opts.files = file_list_parse(fastboot_function); - if (IS_ERR(opts->fastboot_opts.files)) { - pr_err("Parsing file list \"%s\" failed: %s\n", fastboot_function, - strerrorp(opts->fastboot_opts.files)); - opts->fastboot_opts.files = NULL; - } - - opts->fastboot_opts.export_bbu = fastboot_bbu; - } - - opts->create_acm = acm; - - if (!opts->fastboot_opts.files && !opts->create_acm) { - pr_warn("No functions to register\n"); - return 0; - } - - setenv("otg.mode", "peripheral"); - - ret = usb_multi_register(opts); - if (ret) - usb_multi_opts_release(opts); - - return ret; -} -postenvironment_initcall(usbgadget_autostart); - -static int usbgadget_globalvars_init(void) -{ - - globalvar_add_simple_bool("usbgadget.autostart", &autostart); - globalvar_add_simple_bool("usbgadget.acm", &acm); - globalvar_add_simple_string("usbgadget.fastboot_function", - &fastboot_function); - globalvar_add_simple_bool("usbgadget.fastboot_bbu", &fastboot_bbu); - - return 0; -} -device_initcall(usbgadget_globalvars_init); - -BAREBOX_MAGICVAR_NAMED(global_usbgadget_autostart, - global.usbgadget.autostart, - "usbgadget: Automatically start usbgadget on boot"); -BAREBOX_MAGICVAR_NAMED(global_usbgadget_acm, - global.usbgadget.acm, - "usbgadget: Create CDC ACM function"); -BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_function, - global.usbgadget.fastboot_function, - "usbgadget: Create Android Fastboot function"); -BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_bbu, - global.usbgadget.fastboot_bbu, - "usbgadget: export barebox update handlers via fastboot"); diff --git a/include/usb/gadget-multi.h b/include/usb/gadget-multi.h index 81beddc7cf..030e604fe7 100644 --- a/include/usb/gadget-multi.h +++ b/include/usb/gadget-multi.h @@ -16,4 +16,8 @@ int usb_multi_register(struct f_multi_opts *opts); void usb_multi_unregister(void); void usb_multi_opts_release(struct f_multi_opts *opts); +int usbgadget_register(bool dfu, const char *dfu_opts, + bool fastboot, const char *fastboot_opts, + bool acm, bool export_bbu); + #endif /* __USB_GADGET_MULTI_H */ -- cgit v1.2.3