summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-11-09 10:55:12 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-11-09 10:55:12 +0100
commitb4bea4a52101a01626667a625622e5415b868185 (patch)
tree5f5de0ccca7de6875dd5788ae8b5b316e3927a97 /drivers
parenta024d889a02a0c7e1e2406ae0be358906150d713 (diff)
parent44add42d43300a330647704141c5a285358361db (diff)
downloadbarebox-b4bea4a52101a01626667a625622e5415b868185.tar.gz
barebox-b4bea4a52101a01626667a625622e5415b868185.tar.xz
Merge branch 'for-next/usb'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/usb.c5
-rw-r--r--drivers/usb/gadget/Kconfig8
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/at91_udc.c2
-rw-r--r--drivers/usb/gadget/autostart.c101
-rw-r--r--drivers/usb/gadget/fsl_udc.c72
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c5
-rw-r--r--drivers/usb/host/ehci-atmel.c24
-rw-r--r--drivers/usb/host/ehci-hcd.c80
-rw-r--r--drivers/usb/imx/chipidea-imx.c39
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[] = {