diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2018-11-09 10:55:12 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2018-11-09 10:55:12 +0100 |
commit | b4bea4a52101a01626667a625622e5415b868185 (patch) | |
tree | 5f5de0ccca7de6875dd5788ae8b5b316e3927a97 /drivers | |
parent | a024d889a02a0c7e1e2406ae0be358906150d713 (diff) | |
parent | 44add42d43300a330647704141c5a285358361db (diff) | |
download | barebox-b4bea4a52101a01626667a625622e5415b868185.tar.gz barebox-b4bea4a52101a01626667a625622e5415b868185.tar.xz |
Merge branch 'for-next/usb'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/usb.c | 5 | ||||
-rw-r--r-- | drivers/usb/gadget/Kconfig | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/at91_udc.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/autostart.c | 101 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_udc.c | 72 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa27x_udc.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ehci-atmel.c | 24 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 80 | ||||
-rw-r--r-- | drivers/usb/imx/chipidea-imx.c | 39 |
10 files changed, 162 insertions, 175 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0ee8808a6b..7b008435fd 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/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/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 645275a016..729f752128 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -622,7 +622,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/autostart.c b/drivers/usb/gadget/autostart.c deleted file mode 100644 index 272b0ea8fa..0000000000 --- a/drivers/usb/gadget/autostart.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017 Oleksij Rempel <o.rempel@pengutronix.de>, 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 <common.h> -#include <command.h> -#include <errno.h> -#include <environment.h> -#include <malloc.h> -#include <getopt.h> -#include <fs.h> -#include <xfuncs.h> -#include <usb/usbserial.h> -#include <usb/dfu.h> -#include <usb/gadget-multi.h> -#include <globalvar.h> -#include <magicvar.h> - -static int autostart; -static int acm; -static char *fastboot_function; -static int fastboot_bbu; - -static int usbgadget_autostart(void) -{ - struct f_multi_opts *opts; - struct device_d *dev; - 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; - } - - 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; -} -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/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index 9b59669773..705f6c0ba7 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 @@ -523,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 = { @@ -1943,12 +1947,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 +1982,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 +1994,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 +2005,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 +2019,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); @@ -2221,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; @@ -2270,7 +2275,8 @@ int 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 */ @@ -2288,31 +2294,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/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) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 1132879c9b..6c88d646c9 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; @@ -59,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; @@ -66,12 +74,14 @@ 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"; 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)) { @@ -99,15 +109,25 @@ 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) { + 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[] = { diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9bbdda365c..87af95d2ed 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; @@ -1273,22 +1273,19 @@ 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_priv *ehci = dev->priv; - 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_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; ehci->hccr = data->hccr; ehci->dev = dev; @@ -1321,14 +1318,28 @@ int 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)); 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_dev_detect(struct device_d *dev) +{ + struct ehci_host *ehci = dev->priv; + + return ehci_detect(ehci); } static int ehci_probe(struct device_d *dev) @@ -1337,6 +1348,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 +1376,21 @@ 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); + + dev->priv = ehci; + dev->detect = ehci_dev_detect; + + return 0; } static void ehci_remove(struct device_d *dev) { - struct ehci_priv *ehci = dev->priv; - ehci_halt(ehci); + struct ehci_host *ehci = dev->priv; + + 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..8792217706 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -46,6 +46,8 @@ struct imx_chipidea { struct phy *phy; struct usb_phy *usbphy; struct clk *clk; + struct ehci_host *ehci; + struct fsl_udc *udc; }; static int imx_chipidea_port_init(void *drvdata) @@ -175,6 +177,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; @@ -184,14 +193,20 @@ 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; + + ci->dev->detect = ci_ehci_detect; regulator_disable(ci->vbus); } else { @@ -202,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; @@ -266,6 +287,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) { @@ -349,8 +371,13 @@ static int imx_chipidea_probe(struct device_d *dev) static void imx_chipidea_remove(struct device_d *dev) { - if (IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC)) - ci_udc_unregister(); + struct imx_chipidea *ci = dev->priv; + + if (ci->ehci) + ehci_unregister(ci->ehci); + + 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[] = { |