[U-Boot] [PATCH v5 00/15] usb: ohci dm support & add sunxi ehci + ohci support

Hi All,
Here is a new series which applies on top of u-boot-dm/master, this contains all my usb (dm) ohci / ehci / sunxi patches which have been posted before and not yet merged. The series is at v5 because for a couple of patches from my first posting of the ehci sunxi dm series this is the 5th posting, for most patches this is the 2nd posting.
Marek, can we please have your ack for patches 1-4 and 11-12, then Simon can merge the entire series through the u-boot-dm tree.
Changes since the previous posting of these patches:
-"usb: usb: usb_control_msg() propagate controller error code" New patch in this version -"usb: legacy_hub_port_reset() check and propagate usb_set_port_feature() errors" New patch in this version -"usb: Stop reset procedure when a dev is handed over to a companion hcd" Rewritten to not use an usb_companion_device_count global variable -"dm: usb: Add support for interrupt queues to the dm ehci code": squashed into "dm: usb: Add support for interrupt queues to the dm usb code" so as to not have a not building intermediate state -"dm: usb: Add support for companion controllers" Check device_active() before touching the controllers -"dm: usb: Do not scan companion buses if no devices where handed over" Make companion_device_count an uclass private variable -"usb: ohci: Do not resubmit and leak urbs for interrupt packets" Improved commit message -"usb: ohci: Remove unnecessary delays from hc_start and power power-on paths" Improved commit message -"usb: ohci: Skip unnecessary mdelay(1) calls in various places" Add a ohci_mdelay helper macro -"usb: ohci: Add dm support" Fixed TODO about freeing resources on deregister -"sunxi: ohci: Add ohci usb host controller support" Fixed build failure on sun6i / sun8i, added some extra comments to the code
Thanks & Regards,
Hans

When after a reset the port status connection bit is still set and the enable bit is not then we're dealing with a full-speed device and should hand it over to the companion controller.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- drivers/usb/host/ehci-hcd.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 46d01d4..ce760d0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -897,11 +897,21 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe, */ ret = handshake(status_reg, EHCI_PS_PR, 0, 2 * 1000); - if (!ret) - ctrl->portreset |= 1 << port; - else + if (!ret) { + reg = ehci_readl(status_reg); + if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) + == EHCI_PS_CS && !ehci_is_TDI()) { + debug("port %d full speed --> companion\n", port - 1); + reg &= ~EHCI_PS_CLEAR; + reg |= EHCI_PS_PO; + ehci_writel(status_reg, reg); + } else { + ctrl->portreset |= 1 << port; + } + } else { printf("port(%d) reset error\n", port - 1); + } } break; case USB_PORT_FEAT_TEST:

On Sunday, May 10, 2015 at 02:10:13 PM, Hans de Goede wrote:
When after a reset the port status connection bit is still set and the enable bit is not then we're dealing with a full-speed device and should hand it over to the companion controller.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Best regards, Marek Vasut

On 10 May 2015 at 10:12, Marek Vasut marex@denx.de wrote:
On Sunday, May 10, 2015 at 02:10:13 PM, Hans de Goede wrote:
When after a reset the port status connection bit is still set and the enable bit is not then we're dealing with a full-speed device and should hand it over to the companion controller.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Applied to u-boot-dm, thanks!

Propagate the error returned by submit_control_msg() ratehr then always returning -EIO when the hcd code indicates an error.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- common/usb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/common/usb.c b/common/usb.c index 1b26bfa..20c614c 100644 --- a/common/usb.c +++ b/common/usb.c @@ -192,6 +192,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, void *data, unsigned short size, int timeout) { ALLOC_CACHE_ALIGN_BUFFER(struct devrequest, setup_packet, 1); + int err;
if ((timeout == 0) && (!asynch_allowed)) { /* request for a asynch control pipe is not allowed */ @@ -209,8 +210,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, request, requesttype, value, index, size); dev->status = USB_ST_NOT_PROC; /*not yet processed */
- if (submit_control_msg(dev, pipe, data, size, setup_packet) < 0) - return -EIO; + err = submit_control_msg(dev, pipe, data, size, setup_packet); + if (err < 0) + return err; if (timeout == 0) return (int)size;

On Sunday, May 10, 2015 at 02:10:14 PM, Hans de Goede wrote:
Propagate the error returned by submit_control_msg() ratehr then always
... rather ... ;-)
returning -EIO when the hcd code indicates an error.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Best regards, Marek Vasut

On 10 May 2015 at 10:13, Marek Vasut marex@denx.de wrote:
On Sunday, May 10, 2015 at 02:10:14 PM, Hans de Goede wrote:
Propagate the error returned by submit_control_msg() ratehr then always
... rather ... ;-)
returning -EIO when the hcd code indicates an error.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Applied to u-boot-dm, thanks!
(fixed typo)

Actually check for usb_set_port_feature() errors and propagate these if they happen.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- common/usb_hub.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/common/usb_hub.c b/common/usb_hub.c index c9be530..7aac220 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -157,7 +157,7 @@ static inline char *portspeed(int portstatus) int legacy_hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat) { - int tries; + int err, tries; ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); unsigned short portstatus, portchange;
@@ -168,8 +168,10 @@ int legacy_hub_port_reset(struct usb_device *dev, int port, debug("%s: resetting port %d...\n", __func__, port + 1); #endif for (tries = 0; tries < MAX_TRIES; tries++) { + err = usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); + if (err < 0) + return err;
- usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); mdelay(200);
if (usb_get_port_status(dev, port + 1, portsts) < 0) {

On Sunday, May 10, 2015 at 02:10:15 PM, Hans de Goede wrote:
Actually check for usb_set_port_feature() errors and propagate these if they happen.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Best regards, Marek Vasut

On 10 May 2015 at 10:13, Marek Vasut marex@denx.de wrote:
On Sunday, May 10, 2015 at 02:10:15 PM, Hans de Goede wrote:
Actually check for usb_set_port_feature() errors and propagate these if they happen.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Applied to u-boot-dm, thanks!

Short circuit the retry loop in legacy_hub_port_reset() by returning an error from usb_control_msg() when a device was handed over to a companion by the ehci code. This avoids trying to reset low / fullspeed devices 5 times needlessly. Also do not print an error when a device has been handed over.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- common/usb_hub.c | 3 ++- drivers/usb/host/ehci-hcd.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/common/usb_hub.c b/common/usb_hub.c index 7aac220..af39c76 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -271,7 +271,8 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port) /* Reset the port */ ret = legacy_hub_port_reset(dev, port, &portstatus); if (ret < 0) { - printf("cannot reset port %i!?\n", port + 1); + if (ret != -ENXIO) + printf("cannot reset port %i!?\n", port + 1); return ret; }
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index ce760d0..e4c462f 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -875,7 +875,7 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe, port - 1); reg |= EHCI_PS_PO; ehci_writel(status_reg, reg); - break; + return -ENXIO; } else { int ret;
@@ -905,6 +905,7 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe, reg &= ~EHCI_PS_CLEAR; reg |= EHCI_PS_PO; ehci_writel(status_reg, reg); + return -ENXIO; } else { ctrl->portreset |= 1 << port; }

On Sunday, May 10, 2015 at 02:10:16 PM, Hans de Goede wrote:
Short circuit the retry loop in legacy_hub_port_reset() by returning an error from usb_control_msg() when a device was handed over to a companion by the ehci code. This avoids trying to reset low / fullspeed devices 5 times needlessly. Also do not print an error when a device has been handed over.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Best regards, Marek Vasut

On 10 May 2015 at 10:13, Marek Vasut marex@denx.de wrote:
On Sunday, May 10, 2015 at 02:10:16 PM, Hans de Goede wrote:
Short circuit the retry loop in legacy_hub_port_reset() by returning an error from usb_control_msg() when a device was handed over to a companion by the ehci code. This avoids trying to reset low / fullspeed devices 5 times needlessly. Also do not print an error when a device has been handed over.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Applied to u-boot-dm, thanks!

This is a preparation patch for adding interrupt-queue support to the ehci dm code.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org --- drivers/usb/host/ehci-hcd.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e4c462f..b6e965c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1263,9 +1263,9 @@ disable_periodic(struct ehci_ctrl *ctrl) return 0; }
-struct int_queue * -create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, - int elementsize, void *buffer, int interval) +static struct int_queue *_ehci_create_int_queue(struct usb_device *dev, + unsigned long pipe, int queuesize, int elementsize, + void *buffer, int interval) { struct ehci_ctrl *ctrl = ehci_get_ctrl(dev); struct int_queue *result = NULL; @@ -1421,7 +1421,8 @@ fail1: return NULL; }
-void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) +static void *_ehci_poll_int_queue(struct usb_device *dev, + struct int_queue *queue) { struct QH *cur = queue->current; struct qTD *cur_td; @@ -1456,8 +1457,8 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) }
/* Do not free buffers associated with QHs, they're owned by someone else */ -int -destroy_int_queue(struct usb_device *dev, struct int_queue *queue) +static int _ehci_destroy_int_queue(struct usb_device *dev, + struct int_queue *queue) { struct ehci_ctrl *ctrl = ehci_get_ctrl(dev); int result = -1; @@ -1558,6 +1559,24 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, { return _ehci_submit_int_msg(dev, pipe, buffer, length, interval); } + +struct int_queue *create_int_queue(struct usb_device *dev, + unsigned long pipe, int queuesize, int elementsize, + void *buffer, int interval) +{ + return _ehci_create_int_queue(dev, pipe, queuesize, elementsize, + buffer, interval); +} + +void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) +{ + return _ehci_poll_int_queue(dev, queue); +} + +int destroy_int_queue(struct usb_device *dev, struct int_queue *queue) +{ + return _ehci_destroy_int_queue(dev, queue); +} #endif
#ifdef CONFIG_DM_USB

Hi Hans,
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
This is a preparation patch for adding interrupt-queue support to the ehci dm code.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org
I still see some sort of bisect problem here:
Summary of 16 commits for 33 boards (32 threads, 1 job per thread) 01: dm: sf: Update default name of spi flash in structure udevice 02: usb: Fix handover of full-speed devices from ehci to companion 03: usb: usb_control_msg() propagate controller error code 04: usb: legacy_hub_port_reset() check and propagate usb_set_port_feature() errors 05: usb: Stop reset procedure when a dev is handed over to a companion hcd 06: dm: usb: Prefix ehci interrupt-queue functions with _ehci_ arm: + odroid-xu3 snow arndale odroid +drivers/usb/host/built-in.o: In function `_ehci_submit_int_msg': +build/../drivers/usb/host/ehci-hcd.c:1518: undefined reference to `create_int_queue' +build/../drivers/usb/host/ehci-hcd.c:1523: undefined reference to `poll_int_queue' +build/../drivers/usb/host/ehci-hcd.c:1536: undefined reference to `destroy_int_queue' +arm-linux-gnueabihf-ld.bfd: BFD (crosstool-NG linaro-1.13.1-4.7-2013.04-20130415 - Linaro GCC 2013.04) 2.23.1 assertion fail /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/src/binutils-2.23.1/bfd/elf32-arm.c:7677 +arm-linux-gnueabihf-ld.bfd: error: required section '.rel.plt' not found in the linker script +arm-linux-gnueabihf-ld.bfd: final link failed: Invalid operation +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 w+../drivers/usb/host/ehci-hcd.c:1266:26: warning: ‘_ehci_create_int_queue’ defined but not used [-Wunused-function] w+../drivers/usb/host/ehci-hcd.c:1424:14: warning: ‘_ehci_poll_int_queue’ defined but not used [-Wunused-function] w+../drivers/usb/host/ehci-hcd.c:1460:12: warning: ‘_ehci_destroy_int_queue’ defined but not used [-Wunused-function] 07: dm: usb: Add support for interrupt queues to the dm usb code arm: odroid-xu3 snow arndale odroid -drivers/usb/host/built-in.o: In function `_ehci_submit_int_msg': -build/../drivers/usb/host/ehci-hcd.c:1518: undefined reference to `create_int_queue' -build/../drivers/usb/host/ehci-hcd.c:1523: undefined reference to `poll_int_queue' -build/../drivers/usb/host/ehci-hcd.c:1536: undefined reference to `destroy_int_queue' -arm-linux-gnueabihf-ld.bfd: BFD (crosstool-NG linaro-1.13.1-4.7-2013.04-20130415 - Linaro GCC 2013.04) 2.23.1 assertion fail /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/src/binutils-2.23.1/bfd/elf32-arm.c:7677 -arm-linux-gnueabihf-ld.bfd: error: required section '.rel.plt' not found in the linker script -arm-linux-gnueabihf-ld.bfd: final link failed: Invalid operation -make[1]: *** [u-boot] Error 1 -make: *** [sub-make] Error 2 w-../drivers/usb/host/ehci-hcd.c:1266:26: warning: ‘_ehci_create_int_queue’ defined but not used [-Wunused-function] w-../drivers/usb/host/ehci-hcd.c:1424:14: warning: ‘_ehci_poll_int_queue’ defined but not used [-Wunused-function] w-../drivers/usb/host/ehci-hcd.c:1460:12: warning: ‘_ehci_destroy_int_queue’ defined but not used [-Wunused-function] 08: dm: usb: Move printing of usb scan status to usb_scan_bus()
Regards, Simon

Hi,
On 10-05-15 23:58, Simon Glass wrote:
Hi Hans,
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
This is a preparation patch for adding interrupt-queue support to the ehci dm code.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org
I still see some sort of bisect problem here:
Summary of 16 commits for 33 boards (32 threads, 1 job per thread) 01: dm: sf: Update default name of spi flash in structure udevice 02: usb: Fix handover of full-speed devices from ehci to companion 03: usb: usb_control_msg() propagate controller error code 04: usb: legacy_hub_port_reset() check and propagate usb_set_port_feature() errors 05: usb: Stop reset procedure when a dev is handed over to a companion hcd 06: dm: usb: Prefix ehci interrupt-queue functions with _ehci_ arm: + odroid-xu3 snow arndale odroid +drivers/usb/host/built-in.o: In function `_ehci_submit_int_msg': +build/../drivers/usb/host/ehci-hcd.c:1518: undefined reference to `create_int_queue' +build/../drivers/usb/host/ehci-hcd.c:1523: undefined reference to `poll_int_queue' +build/../drivers/usb/host/ehci-hcd.c:1536: undefined reference to `destroy_int_queue' +arm-linux-gnueabihf-ld.bfd: BFD (crosstool-NG linaro-1.13.1-4.7-2013.04-20130415 - Linaro GCC 2013.04) 2.23.1 assertion fail /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/src/binutils-2.23.1/bfd/elf32-arm.c:7677 +arm-linux-gnueabihf-ld.bfd: error: required section '.rel.plt' not found in the linker script +arm-linux-gnueabihf-ld.bfd: final link failed: Invalid operation +make[1]: *** [u-boot] Error 1 +make: *** [sub-make] Error 2 w+../drivers/usb/host/ehci-hcd.c:1266:26: warning: ‘_ehci_create_int_queue’ defined but not used [-Wunused-function] w+../drivers/usb/host/ehci-hcd.c:1424:14: warning: ‘_ehci_poll_int_queue’ defined but not used [-Wunused-function] w+../drivers/usb/host/ehci-hcd.c:1460:12: warning: ‘_ehci_destroy_int_queue’ defined but not used [-Wunused-function] 07: dm: usb: Add support for interrupt queues to the dm usb code arm: odroid-xu3 snow arndale odroid -drivers/usb/host/built-in.o: In function `_ehci_submit_int_msg': -build/../drivers/usb/host/ehci-hcd.c:1518: undefined reference to `create_int_queue' -build/../drivers/usb/host/ehci-hcd.c:1523: undefined reference to `poll_int_queue' -build/../drivers/usb/host/ehci-hcd.c:1536: undefined reference to `destroy_int_queue' -arm-linux-gnueabihf-ld.bfd: BFD (crosstool-NG linaro-1.13.1-4.7-2013.04-20130415 - Linaro GCC 2013.04) 2.23.1 assertion fail /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/src/binutils-2.23.1/bfd/elf32-arm.c:7677 -arm-linux-gnueabihf-ld.bfd: error: required section '.rel.plt' not found in the linker script -arm-linux-gnueabihf-ld.bfd: final link failed: Invalid operation -make[1]: *** [u-boot] Error 1 -make: *** [sub-make] Error 2 w-../drivers/usb/host/ehci-hcd.c:1266:26: warning: ‘_ehci_create_int_queue’ defined but not used [-Wunused-function] w-../drivers/usb/host/ehci-hcd.c:1424:14: warning: ‘_ehci_poll_int_queue’ defined but not used [-Wunused-function] w-../drivers/usb/host/ehci-hcd.c:1460:12: warning: ‘_ehci_destroy_int_queue’ defined but not used [-Wunused-function] 08: dm: usb: Move printing of usb scan status to usb_scan_bus()
Ah, looking closer at this I see the problem, _ehci_submit_int_msg() is implemented by calling create/poll/destroy_int_queue. This is working for CONFIG_DM_USB=y configs after my patchset by _ehci_submit_int_msg() calling the usb-uclass.c implementations of these, which then call the _ehci_ versions of them through the controller ops.
This does not work in the intermediate state with only this patch applied because then the usb-uclass.c implementations do not yet exist.
I'll send a v6 of this patch making ehci_submit_int_msg() use the _ehci_ prefixed versions which is the right thing to do even without the git bisect problem this causes.
Sorry about this.
Regards,
Hans

Interrupt endpoints typically are polled for a long time by the usb controller before they return anything, so calls to submit_int_msg() can take a long time to complete this.
To avoid this the u-boot code has the an interrupt queue mechanism / API, add support for this to the driver-model usb code and implement it for the dm ehci code.
See the added doc comments for more details.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org --- drivers/usb/host/ehci-hcd.c | 26 +++++++++++++++++++++++ drivers/usb/host/usb-uclass.c | 36 ++++++++++++++++++++++++++++++++ include/usb.h | 48 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b6e965c..85b9d7b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1605,6 +1605,29 @@ static int ehci_submit_int_msg(struct udevice *dev, struct usb_device *udev, return _ehci_submit_int_msg(udev, pipe, buffer, length, interval); }
+static struct int_queue *ehci_create_int_queue(struct udevice *dev, + struct usb_device *udev, unsigned long pipe, int queuesize, + int elementsize, void *buffer, int interval) +{ + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); + return _ehci_create_int_queue(udev, pipe, queuesize, elementsize, + buffer, interval); +} + +static void *ehci_poll_int_queue(struct udevice *dev, struct usb_device *udev, + struct int_queue *queue) +{ + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); + return _ehci_poll_int_queue(udev, queue); +} + +static int ehci_destroy_int_queue(struct udevice *dev, struct usb_device *udev, + struct int_queue *queue) +{ + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); + return _ehci_destroy_int_queue(udev, queue); +} + int ehci_register(struct udevice *dev, struct ehci_hccr *hccr, struct ehci_hcor *hcor, const struct ehci_ops *ops, uint tweaks, enum usb_init_type init) @@ -1653,6 +1676,9 @@ struct dm_usb_ops ehci_usb_ops = { .control = ehci_submit_control_msg, .bulk = ehci_submit_bulk_msg, .interrupt = ehci_submit_int_msg, + .create_int_queue = ehci_create_int_queue, + .poll_int_queue = ehci_poll_int_queue, + .destroy_int_queue = ehci_destroy_int_queue, };
#endif diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index c5ece58..9ee25ed 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -65,6 +65,42 @@ int submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, return ops->bulk(bus, udev, pipe, buffer, length); }
+struct int_queue *create_int_queue(struct usb_device *udev, + unsigned long pipe, int queuesize, int elementsize, + void *buffer, int interval) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->create_int_queue) + return NULL; + + return ops->create_int_queue(bus, udev, pipe, queuesize, elementsize, + buffer, interval); +} + +void *poll_int_queue(struct usb_device *udev, struct int_queue *queue) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->poll_int_queue) + return NULL; + + return ops->poll_int_queue(bus, udev, queue); +} + +int destroy_int_queue(struct usb_device *udev, struct int_queue *queue) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->destroy_int_queue) + return -ENOSYS; + + return ops->destroy_int_queue(bus, udev, queue); +} + int usb_alloc_device(struct usb_device *udev) { struct udevice *bus = udev->controller_dev; diff --git a/include/usb.h b/include/usb.h index 4c21050..609b13d 100644 --- a/include/usb.h +++ b/include/usb.h @@ -198,7 +198,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval);
-#if defined CONFIG_USB_EHCI || defined CONFIG_MUSB_HOST +#if defined CONFIG_USB_EHCI || defined CONFIG_MUSB_HOST || defined(CONFIG_DM_USB) struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, int elementsize, void *buffer, int interval); int destroy_int_queue(struct usb_device *dev, struct int_queue *queue); @@ -660,6 +660,52 @@ struct dm_usb_ops { int (*interrupt)(struct udevice *bus, struct usb_device *udev, unsigned long pipe, void *buffer, int length, int interval); + + /** + * create_int_queue() - Create and queue interrupt packets + * + * Create and queue @queuesize number of interrupt usb packets of + * @elementsize bytes each. @buffer must be atleast @queuesize * + * @elementsize bytes. + * + * Note some controllers only support a queuesize of 1. + * + * @interval: Interrupt interval + * + * @return A pointer to the created interrupt queue or NULL on error + */ + struct int_queue * (*create_int_queue)(struct udevice *bus, + struct usb_device *udev, unsigned long pipe, + int queuesize, int elementsize, void *buffer, + int interval); + + /** + * poll_int_queue() - Poll an interrupt queue for completed packets + * + * Poll an interrupt queue for completed packets. The return value + * points to the part of the buffer passed to create_int_queue() + * corresponding to the completed packet. + * + * @queue: queue to poll + * + * @return Pointer to the data of the first completed packet, or + * NULL if no packets are ready + */ + void * (*poll_int_queue)(struct udevice *bus, struct usb_device *udev, + struct int_queue *queue); + + /** + * destroy_int_queue() - Destroy an interrupt queue + * + * Destroy an interrupt queue created by create_int_queue(). + * + * @queue: queue to poll + * + * @return 0 if OK, -ve on error + */ + int (*destroy_int_queue)(struct udevice *bus, struct usb_device *udev, + struct int_queue *queue); + /** * alloc_device() - Allocate a new device context (XHCI) *

On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
Interrupt endpoints typically are polled for a long time by the usb controller before they return anything, so calls to submit_int_msg() can take a long time to complete this.
To avoid this the u-boot code has the an interrupt queue mechanism / API, add support for this to the driver-model usb code and implement it for the dm ehci code.
See the added doc comments for more details.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org
drivers/usb/host/ehci-hcd.c | 26 +++++++++++++++++++++++ drivers/usb/host/usb-uclass.c | 36 ++++++++++++++++++++++++++++++++ include/usb.h | 48 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 109 insertions(+), 1 deletion(-)
Applied to u-boot-dm, thanks!

Move printing of usb scan status to usb_scan_bus().
This is a preparation patch for adding companion controller support to the usb uclass.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org --- drivers/usb/host/usb-uclass.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 9ee25ed..ad778b4 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -147,7 +147,7 @@ int usb_stop(void) return err; }
-static int usb_scan_bus(struct udevice *bus, bool recurse) +static void usb_scan_bus(struct udevice *bus, bool recurse) { struct usb_bus_priv *priv; struct udevice *dev; @@ -157,11 +157,15 @@ static int usb_scan_bus(struct udevice *bus, bool recurse)
assert(recurse); /* TODO: Support non-recusive */
+ printf("scanning bus %d for devices... ", bus->seq); + debug("\n"); ret = usb_scan_device(bus, 0, USB_SPEED_FULL, &dev); if (ret) - return ret; - - return priv->next_addr; + printf("failed, error %d\n", ret); + else if (priv->next_addr == 0) + printf("No USB Device found\n"); + else + printf("%d USB Device(s) found\n", priv->next_addr); }
int usb_init(void) @@ -199,15 +203,7 @@ int usb_init(void) * i.e. search HUBs and configure them */ controllers_initialized++; - printf("scanning bus %d for devices... ", bus->seq); - debug("\n"); - ret = usb_scan_bus(bus, true); - if (ret < 0) - printf("failed, error %d\n", ret); - else if (!ret) - printf("No USB Device found\n"); - else - printf("%d USB Device(s) found\n", ret); + usb_scan_bus(bus, true); usb_started = true; }

On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
Move printing of usb scan status to usb_scan_bus().
This is a preparation patch for adding companion controller support to the usb uclass.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org
drivers/usb/host/usb-uclass.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
Applied to u-boot-dm, thanks!

USB companion controllers must be scanned after the main controller has been scanned, so that any devices which the main controller which to hand over to the companion have actually been handed over before we scan the companion.
As there are no guarantees that this will magically happen in the right order, split the scanning of the buses in 2 phases, first main controllers, and then companion controllers.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- drivers/usb/host/usb-uclass.c | 33 ++++++++++++++++++++++++++++----- include/usb.h | 3 +++ 2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index ad778b4..749257c 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -171,6 +171,7 @@ static void usb_scan_bus(struct udevice *bus, bool recurse) int usb_init(void) { int controllers_initialized = 0; + struct usb_bus_priv *priv; struct udevice *bus; struct uclass *uc; int count = 0; @@ -198,15 +199,37 @@ int usb_init(void) printf("probe failed, error %d\n", ret); continue; } - /* - * lowlevel init is OK, now scan the bus for devices - * i.e. search HUBs and configure them - */ controllers_initialized++; - usb_scan_bus(bus, true); usb_started = true; }
+ /* + * lowlevel init done, now scan the bus for devices i.e. search HUBs + * and configure them, first scan primary controllers. + */ + uclass_foreach_dev(bus, uc) { + if (!device_active(bus)) + continue; + + priv = dev_get_uclass_priv(bus); + if (!priv->companion) + usb_scan_bus(bus, true); + } + + /* + * Now that the primary controllers have been scanned and have handed + * over any devices they do not understand to their companions, scan + * the companions. + */ + uclass_foreach_dev(bus, uc) { + if (!device_active(bus)) + continue; + + priv = dev_get_uclass_priv(bus); + if (priv->companion) + usb_scan_bus(bus, true); + } + debug("scan end\n"); /* if we were not able to find at least one working bus, bail out */ if (!count) diff --git a/include/usb.h b/include/usb.h index 609b13d..5043bc3 100644 --- a/include/usb.h +++ b/include/usb.h @@ -608,10 +608,13 @@ struct usb_dev_platdata { * @desc_before_addr: true if we can read a device descriptor before it * has been assigned an address. For XHCI this is not possible * so this will be false. + * @companion: True if this is a companion controller to another USB + * controller */ struct usb_bus_priv { int next_addr; bool desc_before_addr; + bool companion; };
/**

On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
USB companion controllers must be scanned after the main controller has been scanned, so that any devices which the main controller which to hand over to the companion have actually been handed over before we scan the companion.
As there are no guarantees that this will magically happen in the right order, split the scanning of the buses in 2 phases, first main controllers, and then companion controllers.
Signed-off-by: Hans de Goede hdegoede@redhat.com
drivers/usb/host/usb-uclass.c | 33 ++++++++++++++++++++++++++++----- include/usb.h | 3 +++ 2 files changed, 31 insertions(+), 5 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

On 11 May 2015 at 16:33, Simon Glass sjg@chromium.org wrote:
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
USB companion controllers must be scanned after the main controller has been scanned, so that any devices which the main controller which to hand over to the companion have actually been handed over before we scan the companion.
As there are no guarantees that this will magically happen in the right order, split the scanning of the buses in 2 phases, first main controllers, and then companion controllers.
Signed-off-by: Hans de Goede hdegoede@redhat.com
drivers/usb/host/usb-uclass.c | 33 ++++++++++++++++++++++++++++----- include/usb.h | 3 +++ 2 files changed, 31 insertions(+), 5 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot-dm, thanks!

USB scanning is slow, and there is no need to scan the companion buses if no usb devices where handed over to the companinon controllers by any of the main controllers.
This saves e.g. 2 seconds when booting a A10 OLinuxIno Lime with no USB-1 devices plugged into the root usb ports.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- drivers/usb/host/usb-uclass.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-)
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 749257c..963464c 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -21,6 +21,10 @@ DECLARE_GLOBAL_DATA_PTR; extern bool usb_started; /* flag for the started/stopped USB status */ static bool asynch_allowed;
+struct usb_uclass_priv { + int companion_device_count; +}; + int usb_disable_asynch(int disable) { int old_value = asynch_allowed; @@ -46,11 +50,22 @@ int submit_control_msg(struct usb_device *udev, unsigned long pipe, { struct udevice *bus = udev->controller_dev; struct dm_usb_ops *ops = usb_get_ops(bus); + struct usb_uclass_priv *uc_priv = bus->uclass->priv; + int err;
if (!ops->control) return -ENOSYS;
- return ops->control(bus, udev, pipe, buffer, length, setup); + err = ops->control(bus, udev, pipe, buffer, length, setup); + if (setup->request == USB_REQ_SET_FEATURE && + setup->requesttype == USB_RT_PORT && + setup->value == cpu_to_le16(USB_PORT_FEAT_RESET) && + err == -ENXIO) { + /* Device handed over to companion after port reset */ + uc_priv->companion_device_count++; + } + + return err; }
int submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, @@ -117,12 +132,16 @@ int usb_stop(void) { struct udevice *bus; struct uclass *uc; + struct usb_uclass_priv *uc_priv; int err = 0, ret;
/* De-activate any devices that have been activated */ ret = uclass_get(UCLASS_USB, &uc); if (ret) return ret; + + uc_priv = uc->priv; + uclass_foreach_dev(bus, uc) { ret = device_remove(bus); if (ret && !err) @@ -142,6 +161,7 @@ int usb_stop(void) #endif usb_stor_reset(); usb_hub_reset(); + uc_priv->companion_device_count = 0; usb_started = 0;
return err; @@ -171,6 +191,7 @@ static void usb_scan_bus(struct udevice *bus, bool recurse) int usb_init(void) { int controllers_initialized = 0; + struct usb_uclass_priv *uc_priv; struct usb_bus_priv *priv; struct udevice *bus; struct uclass *uc; @@ -184,6 +205,8 @@ int usb_init(void) if (ret) return ret;
+ uc_priv = uc->priv; + uclass_foreach_dev(bus, uc) { /* init low_level USB */ printf("USB%d: ", count); @@ -219,15 +242,17 @@ int usb_init(void) /* * Now that the primary controllers have been scanned and have handed * over any devices they do not understand to their companions, scan - * the companions. + * the companions if necessary. */ - uclass_foreach_dev(bus, uc) { - if (!device_active(bus)) - continue; + if (uc_priv->companion_device_count) { + uclass_foreach_dev(bus, uc) { + if (!device_active(bus)) + continue;
- priv = dev_get_uclass_priv(bus); - if (priv->companion) - usb_scan_bus(bus, true); + priv = dev_get_uclass_priv(bus); + if (priv->companion) + usb_scan_bus(bus, true); + } }
debug("scan end\n"); @@ -685,6 +710,7 @@ UCLASS_DRIVER(usb) = { .name = "usb", .flags = DM_UC_FLAG_SEQ_ALIAS, .post_bind = usb_post_bind, + .priv_auto_alloc_size = sizeof(struct usb_uclass_priv), .per_child_auto_alloc_size = sizeof(struct usb_device), .per_device_auto_alloc_size = sizeof(struct usb_bus_priv), .child_post_bind = usb_child_post_bind,

On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
USB scanning is slow, and there is no need to scan the companion buses if no usb devices where handed over to the companinon controllers by any of the main controllers.
This saves e.g. 2 seconds when booting a A10 OLinuxIno Lime with no USB-1 devices plugged into the root usb ports.
Signed-off-by: Hans de Goede hdegoede@redhat.com
drivers/usb/host/usb-uclass.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

On 11 May 2015 at 16:33, Simon Glass sjg@chromium.org wrote:
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
USB scanning is slow, and there is no need to scan the companion buses if no usb devices where handed over to the companinon controllers by any of the main controllers.
This saves e.g. 2 seconds when booting a A10 OLinuxIno Lime with no USB-1 devices plugged into the root usb ports.
Signed-off-by: Hans de Goede hdegoede@redhat.com
drivers/usb/host/usb-uclass.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot-dm, thanks!

The u-boot usb code uses polling for all endpoints, including interrupt endpoints, so urbs should never be automatically resubmitted.
This also fixes a leak of the urb, as submit_int_msg() did not check if an already re-submitted urb exists before creating a new one.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de --- drivers/usb/host/ohci-hcd.c | 41 ++--------------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 494b760..da500c0 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -587,40 +587,6 @@ int sohci_submit_job(ohci_t *ohci, ohci_dev_t *ohci_dev, urb_priv_t *urb, return 0; }
-static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb) -{ - struct ohci_regs *regs = hc->regs; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - /* implicitly requeued */ - if (urb->dev->irq_handle && - (urb->dev->irq_act_len = urb->actual_length)) { - ohci_writel(OHCI_INTR_WDH, ®s->intrenable); - ohci_readl(®s->intrenable); /* PCI posting flush */ - urb->dev->irq_handle(urb->dev); - ohci_writel(OHCI_INTR_WDH, ®s->intrdisable); - ohci_readl(®s->intrdisable); /* PCI posting flush */ - } - urb->actual_length = 0; - td_submit_job( hc, - urb->dev, - urb->pipe, - urb->transfer_buffer, - urb->transfer_buffer_length, - NULL, - urb, - urb->interval); - break; - case PIPE_CONTROL: - case PIPE_BULK: - break; - default: - return 0; - } - return 1; -} - /*-------------------------------------------------------------------------*/
#ifdef DEBUG @@ -1153,7 +1119,7 @@ static td_t *dl_reverse_done_list(ohci_t *ohci) static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status) { if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL)) - urb->finished = sohci_return_job(ohci, urb); + urb->finished = 1; else dbg("finish_urb: strange.., ED state %x, \n", status); } @@ -1593,10 +1559,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, #else mdelay(1); #endif - - /* free TDs in urb_priv */ - if (!usb_pipeint(pipe)) - urb_free_priv(urb); + urb_free_priv(urb); return 0; }

On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
The u-boot usb code uses polling for all endpoints, including interrupt endpoints, so urbs should never be automatically resubmitted.
This also fixes a leak of the urb, as submit_int_msg() did not check if an already re-submitted urb exists before creating a new one.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de
drivers/usb/host/ohci-hcd.c | 41 ++--------------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-)
Applied to u-boot-dm, thanks!

The usb spec says that we must wait a minimum amount of time after port power on (exact time is in the hub descriptor), this is something which we must not only do for root ports but also for external hub ports, which is why the common usb_hub code already waits a full second after powering up ports. Having a separate wait for just the root hub in the ohci-hcd code only leads to doing the waiting twice for the root ports, so drop the wait from the ohci-hcd code.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- drivers/usb/host/ohci-hcd.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index da500c0..dc0892f 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1338,7 +1338,6 @@ pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, OK(0); case (RH_PORT_POWER): WR_RH_PORTSTAT(RH_PS_PPS); - mdelay(100); OK(0); case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ if (RD_RH_PORTSTAT & RH_PS_CCS) @@ -1737,9 +1736,6 @@ static int hc_start(ohci_t *ohci) ohci_writel(RH_HS_LPSC, &ohci->regs->roothub.status); #endif /* OHCI_USE_NPS */
- /* POTPGT delay is bits 24-31, in 2 ms units. */ - mdelay((roothub_a(ohci) >> 23) & 0x1fe); - /* connect the virtual root hub */ ohci->rh.devnum = 0;

On Sunday, May 10, 2015 at 02:10:23 PM, Hans de Goede wrote:
The usb spec says that we must wait a minimum amount of time after port power on (exact time is in the hub descriptor), this is something which we must not only do for root ports but also for external hub ports, which is why the common usb_hub code already waits a full second after powering up ports. Having a separate wait for just the root hub in the ohci-hcd code only leads to doing the waiting twice for the root ports, so drop the wait from the ohci-hcd code.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Best regards, Marek Vasut

On 10 May 2015 at 10:11, Marek Vasut marex@denx.de wrote:
On Sunday, May 10, 2015 at 02:10:23 PM, Hans de Goede wrote:
The usb spec says that we must wait a minimum amount of time after port power on (exact time is in the hub descriptor), this is something which we must not only do for root ports but also for external hub ports, which is why the common usb_hub code already waits a full second after powering up ports. Having a separate wait for just the root hub in the ohci-hcd code only leads to doing the waiting twice for the root ports, so drop the wait from the ohci-hcd code.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Marek Vasut marex@denx.de
Applied to u-boot-dm, thanks!

For some reason the ohci code is full with:
#ifdef DEBUG pkt_print(...) #else mdelay(1); #endif
AFAICT there is no reason for the mdelay(1) calls. This commit disables them when building the ohci code for new driver-model using boards. It leaves the mdelay(1) calls in place when building for older boards, so as to avoid causing any regressions there.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- drivers/usb/host/ohci-hcd.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index dc0892f..a56aac3 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -129,6 +129,17 @@ static struct pci_device_id ehci_pci_ids[] = { #define invalidate_dcache_iso_td(addr) invalidate_dcache_buffer(addr, 32) #define invalidate_dcache_hcca(addr) invalidate_dcache_buffer(addr, 256)
+#ifdef CONFIG_DM_USB +/* + * The various ohci_mdelay(1) calls in the code seem unnecessary. We keep + * them around when building for older boards not yet converted to the dm + * just in case (to avoid regressions), for dm this turns them into nops. + */ +#define ohci_mdelay(x) +#else +#define ohci_mdelay(x) mdelay(x) +#endif + /* global ohci_t */ static ohci_t gohci; /* this must be aligned to a 256 byte boundary */ @@ -1257,7 +1268,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); #else - mdelay(1); + ohci_mdelay(1); #endif if (usb_pipeint(pipe)) { info("Root-Hub submit IRQ: NOT implemented"); @@ -1442,7 +1453,7 @@ pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, #ifdef DEBUG ohci_dump_roothub(ohci, 1); #else - mdelay(1); + ohci_mdelay(1); #endif
len = min_t(int, len, leni); @@ -1455,7 +1466,7 @@ pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); #else - mdelay(1); + ohci_mdelay(1); #endif
return stat; @@ -1488,7 +1499,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); #else - mdelay(1); + ohci_mdelay(1); #endif if (!maxsize) { err("submit_common_message: pipesize for pipe %lx is zero", @@ -1556,7 +1567,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); #else - mdelay(1); + ohci_mdelay(1); #endif urb_free_priv(urb); return 0; @@ -1590,7 +1601,7 @@ static int _ohci_submit_control_msg(ohci_t *ohci, struct usb_device *dev, pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); #else - mdelay(1); + ohci_mdelay(1); #endif if (!maxsize) { err("submit_control_message: pipesize for pipe %lx is zero", @@ -1787,7 +1798,7 @@ static int hc_interrupt(ohci_t *ohci) #ifdef DEBUG ohci_dump(ohci, 1); #else - mdelay(1); + ohci_mdelay(1); #endif /* FIXME: be optimistic, hope that bug won't repeat often. */ /* Make some non-interrupt context restart the controller. */ @@ -1798,7 +1809,7 @@ static int hc_interrupt(ohci_t *ohci) }
if (ints & OHCI_INTR_WDH) { - mdelay(1); + ohci_mdelay(1); ohci_writel(OHCI_INTR_WDH, ®s->intrdisable); (void)ohci_readl(®s->intrdisable); /* flush */ stat = dl_done_list(ohci); @@ -1935,7 +1946,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) #ifdef DEBUG ohci_dump(&gohci, 1); #else - mdelay(1); + ohci_mdelay(1); #endif ohci_inited = 1; return 0;

On Sunday, May 10, 2015 at 02:10:24 PM, Hans de Goede wrote:
For some reason the ohci code is full with:
#ifdef DEBUG pkt_print(...) #else mdelay(1); #endif
AFAICT there is no reason for the mdelay(1) calls. This commit disables them when building the ohci code for new driver-model using boards. It leaves the mdelay(1) calls in place when building for older boards, so as to avoid causing any regressions there.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Maybe those debug prints can be abstracted into one single function instead of having the code littered with #ifdef-else-endif , but let's do that later or in another patch.
Acked-by: Marek Vasut marex@denx.de [...] Best regards, Marek Vasut

On 10 May 2015 at 10:12, Marek Vasut marex@denx.de wrote:
On Sunday, May 10, 2015 at 02:10:24 PM, Hans de Goede wrote:
For some reason the ohci code is full with:
#ifdef DEBUG pkt_print(...) #else mdelay(1); #endif
AFAICT there is no reason for the mdelay(1) calls. This commit disables them when building the ohci code for new driver-model using boards. It leaves the mdelay(1) calls in place when building for older boards, so as to avoid causing any regressions there.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Maybe those debug prints can be abstracted into one single function instead of having the code littered with #ifdef-else-endif , but let's do that later or in another patch.
Acked-by: Marek Vasut marex@denx.de
Applied to u-boot-dm, thanks!

Add driver-model support to the ohci code.
Signed-off-by: Hans de Goede hdegoede@redhat.com Reviewed-by: Marek Vasut marex@denx.de --- drivers/usb/host/ohci-hcd.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ohci.h | 7 ++++ 2 files changed, 91 insertions(+)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index a56aac3..2f976d2 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -30,6 +30,8 @@
#include <common.h> #include <asm/byteorder.h> +#include <dm.h> +#include <errno.h>
#if defined(CONFIG_PCI_OHCI) # include <pci.h> @@ -140,10 +142,12 @@ static struct pci_device_id ehci_pci_ids[] = { #define ohci_mdelay(x) mdelay(x) #endif
+#ifndef CONFIG_DM_USB /* global ohci_t */ static ohci_t gohci; /* this must be aligned to a 256 byte boundary */ struct ohci_hcca ghcca[1]; +#endif
/* mapping of the OHCI CC status to error codes */ static int cc_to_error[16] = { @@ -1573,6 +1577,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, return 0; }
+#ifndef CONFIG_DM_USB /* submit routines called from usb.c */ int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len) @@ -1589,6 +1594,7 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return submit_common_msg(&gohci, dev, pipe, buffer, transfer_len, NULL, interval); } +#endif
static int _ohci_submit_control_msg(ohci_t *ohci, struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, @@ -1839,6 +1845,8 @@ static int hc_interrupt(ohci_t *ohci)
/*-------------------------------------------------------------------------*/
+#ifndef CONFIG_DM_USB + /*-------------------------------------------------------------------------*/
/* De-allocate all resources.. */ @@ -1985,3 +1993,79 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, return _ohci_submit_control_msg(&gohci, dev, pipe, buffer, transfer_len, setup); } +#endif + +#ifdef CONFIG_DM_USB +static int ohci_submit_control_msg(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length, + struct devrequest *setup) +{ + ohci_t *ohci = dev_get_priv(usb_get_bus(dev)); + + return _ohci_submit_control_msg(ohci, udev, pipe, buffer, + length, setup); +} + +static int ohci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length) +{ + ohci_t *ohci = dev_get_priv(usb_get_bus(dev)); + + return submit_common_msg(ohci, udev, pipe, buffer, length, NULL, 0); +} + +static int ohci_submit_int_msg(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length, + int interval) +{ + ohci_t *ohci = dev_get_priv(usb_get_bus(dev)); + + return submit_common_msg(ohci, udev, pipe, buffer, length, + NULL, interval); +} + +int ohci_register(struct udevice *dev, struct ohci_regs *regs) +{ + struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + ohci_t *ohci = dev_get_priv(dev); + u32 reg; + + priv->desc_before_addr = true; + + ohci->regs = regs; + ohci->hcca = memalign(256, sizeof(struct ohci_hcca)); + if (!ohci->hcca) + return -ENOMEM; + memset(ohci->hcca, 0, sizeof(struct ohci_hcca)); + + if (hc_reset(ohci) < 0) + return -EIO; + + if (hc_start(ohci) < 0) + return -EIO; + + reg = ohci_readl(®s->revision); + printf("USB OHCI %x.%x\n", (reg >> 4) & 0xf, reg & 0xf); + + return 0; +} + +int ohci_deregister(struct udevice *dev) +{ + ohci_t *ohci = dev_get_priv(dev); + + if (hc_reset(ohci) < 0) + return -EIO; + + free(ohci->hcca); + + return 0; +} + +struct dm_usb_ops ohci_usb_ops = { + .control = ohci_submit_control_msg, + .bulk = ohci_submit_bulk_msg, + .interrupt = ohci_submit_int_msg, +}; + +#endif diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index f52b4c1..3f9869b 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -405,3 +405,10 @@ typedef struct ohci {
const char *slot_name; } ohci_t; + +#ifdef CONFIG_DM_USB +extern struct dm_usb_ops ohci_usb_ops; + +int ohci_register(struct udevice *dev, struct ohci_regs *regs); +int ohci_deregister(struct udevice *dev); +#endif

On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
Add driver-model support to the ohci code.
Signed-off-by: Hans de Goede hdegoede@redhat.com Reviewed-by: Marek Vasut marex@denx.de
drivers/usb/host/ohci-hcd.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ohci.h | 7 ++++ 2 files changed, 91 insertions(+)
Applied to u-boot-dm, thanks!

Convert sunxi-boards which use the sunxi-ehci code to the driver-model.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org --- board/sunxi/Kconfig | 3 ++ drivers/usb/host/ehci-sunxi.c | 93 +++++++++++++++++++++++++++++-------------- 2 files changed, 67 insertions(+), 29 deletions(-)
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index a60d028..4ca1ac1 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -555,4 +555,7 @@ config DM_ETH config DM_SERIAL default y
+config DM_USB + default y if !USB_MUSB_SUNXI + endif diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 0edb643..34130f8 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -14,53 +14,88 @@ #include <asm/arch/clock.h> #include <asm/arch/usb_phy.h> #include <asm/io.h> +#include <dm.h> #include "ehci.h"
-int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, - struct ehci_hcor **hcor) +struct ehci_sunxi_priv { + struct ehci_ctrl ehci; + int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ + int phy_index; /* Index of the usb-phy attached to this hcd */ +}; + +static int ehci_usb_probe(struct udevice *dev) { struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - int ahb_gate_offset; + struct usb_platdata *plat = dev_get_platdata(dev); + struct ehci_sunxi_priv *priv = dev_get_priv(dev); + struct ehci_hccr *hccr = (struct ehci_hccr *)dev_get_addr(dev); + struct ehci_hcor *hcor; + + /* + * This should go away once we've moved to the driver model for + * clocks resp. phys. + */ + if (hccr == (void *)SUNXI_USB1_BASE) { + priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0; + priv->phy_index = 1; + } else { + priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1; + priv->phy_index = 2; + }
- ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : - AHB_GATE_OFFSET_USB_EHCI0; - setbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); + setbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); #ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); + setbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif
- sunxi_usb_phy_init(index + 1); - sunxi_usb_phy_power_on(index + 1); - - if (index == 0) - *hccr = (void *)SUNXI_USB1_BASE; - else - *hccr = (void *)SUNXI_USB2_BASE; - - *hcor = (struct ehci_hcor *)((uint32_t) *hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + sunxi_usb_phy_init(priv->phy_index); + sunxi_usb_phy_power_on(priv->phy_index);
- debug("sunxi-ehci: init hccr %x and hcor %x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + hcor = (struct ehci_hcor *)((uint32_t)hccr + + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
- return 0; + return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type); }
-int ehci_hcd_stop(int index) +static int ehci_usb_remove(struct udevice *dev) { struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - int ahb_gate_offset; + struct ehci_sunxi_priv *priv = dev_get_priv(dev); + int ret; + + ret = ehci_deregister(dev); + if (ret) + return ret;
- sunxi_usb_phy_power_off(index + 1); - sunxi_usb_phy_exit(index + 1); + sunxi_usb_phy_power_off(priv->phy_index); + sunxi_usb_phy_exit(priv->phy_index);
- ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : - AHB_GATE_OFFSET_USB_EHCI0; #ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); + clrbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif - clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); + clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask);
return 0; } + +static const struct udevice_id ehci_usb_ids[] = { + { .compatible = "allwinner,sun4i-a10-ehci", }, + { .compatible = "allwinner,sun5i-a13-ehci", }, + { .compatible = "allwinner,sun6i-a31-ehci", }, + { .compatible = "allwinner,sun7i-a20-ehci", }, + { .compatible = "allwinner,sun8i-a23-ehci", }, + { .compatible = "allwinner,sun9i-a80-ehci", }, + { } +}; + +U_BOOT_DRIVER(usb_ehci) = { + .name = "ehci_sunxi", + .id = UCLASS_USB, + .of_match = ehci_usb_ids, + .probe = ehci_usb_probe, + .remove = ehci_usb_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct ehci_sunxi_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

On Sun, 2015-05-10 at 14:10 +0200, Hans de Goede wrote:
Convert sunxi-boards which use the sunxi-ehci code to the driver-model.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org
Acked-by: Ian Campbell ijc@hellion.org.uk

On 10 May 2015 at 06:22, Ian Campbell ijc@hellion.org.uk wrote:
On Sun, 2015-05-10 at 14:10 +0200, Hans de Goede wrote:
Convert sunxi-boards which use the sunxi-ehci code to the driver-model.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Simon Glass sjg@chromium.org
Acked-by: Ian Campbell ijc@hellion.org.uk
Applied to u-boot-dm, thanks!

This commit adds support for the OHCI companion controller, which makes usb-1 devices directly plugged into to usb root port work.
Note for now this switches usb-keyboard support for sunxi back from int-queue support to the old interrupt polling method. Adding int-queue support to the ohci code and switching back to int-queue support is in the works.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de Acked-by: Ian Campbell ijc@hellion.org.uk --- arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sunxi.c | 104 ++++++++++++++++++++++++++ include/configs/sunxi-common.h | 5 +- 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/host/ohci-sunxi.c
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h index c28ee05..63c3319 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h @@ -320,6 +320,8 @@ struct sunxi_ccm_reg { #define CCM_USB_CTRL_PHY0_RST (0x1 << 0) #define CCM_USB_CTRL_PHY1_RST (0x1 << 1) #define CCM_USB_CTRL_PHY2_RST (0x1 << 2) +#define CCM_USB_CTRL_OHCI0_CLK (0x1 << 6) +#define CCM_USB_CTRL_OHCI1_CLK (0x1 << 7) #define CCM_USB_CTRL_PHYGATE (0x1 << 8) /* These 3 are sun6i only, define them as 0 on sun4i */ #define CCM_USB_CTRL_PHY0_CLK 0 diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index 04c6d58..bacd70a 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -246,6 +246,8 @@ struct sunxi_ccm_reg { #define CCM_USB_CTRL_PHY0_CLK (0x1 << 8) #define CCM_USB_CTRL_PHY1_CLK (0x1 << 9) #define CCM_USB_CTRL_PHY2_CLK (0x1 << 10) +#define CCM_USB_CTRL_OHCI0_CLK (0x1 << 16) +#define CCM_USB_CTRL_OHCI1_CLK (0x1 << 17)
#define CCM_GMAC_CTRL_TX_CLK_SRC_MII 0x0 #define CCM_GMAC_CTRL_TX_CLK_SRC_EXT_RGMII 0x1 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 3b57e56..4d35d3e 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o obj-$(CONFIG_USB_OHCI_S3C24XX) += ohci-s3c24xx.o obj-$(CONFIG_USB_OHCI_EP93XX) += ohci-ep93xx.o +obj-$(CONFIG_USB_OHCI_SUNXI) += ohci-sunxi.o
# echi obj-$(CONFIG_USB_EHCI) += ehci-hcd.o diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c new file mode 100644 index 0000000..e33a8f7 --- /dev/null +++ b/drivers/usb/host/ohci-sunxi.c @@ -0,0 +1,104 @@ +/* + * Sunxi ohci glue + * + * Copyright (C) 2015 Hans de Goede hdegoede@redhat.com + * + * Based on code from + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/usb_phy.h> +#include <asm/io.h> +#include <dm.h> +#include <usb.h> +#include "ohci.h" + +struct ohci_sunxi_priv { + ohci_t ohci; + int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ + int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */ + int phy_index; /* Index of the usb-phy attached to this hcd */ +}; + +static int ohci_usb_probe(struct udevice *dev) +{ + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev); + struct ohci_sunxi_priv *priv = dev_get_priv(dev); + struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev); + + bus_priv->companion = true; + + /* + * This should go away once we've moved to the driver model for + * clocks resp. phys. + */ + if (regs == (void *)(SUNXI_USB1_BASE + 0x400)) { + priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0; + priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK; + priv->phy_index = 1; + } else { + priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI1; + priv->usb_gate_mask = CCM_USB_CTRL_OHCI1_CLK; + priv->phy_index = 2; + } + + setbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); + setbits_le32(&ccm->usb_clk_cfg, priv->usb_gate_mask); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); +#endif + + sunxi_usb_phy_init(priv->phy_index); + sunxi_usb_phy_power_on(priv->phy_index); + + return ohci_register(dev, regs); +} + +static int ohci_usb_remove(struct udevice *dev) +{ + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct ohci_sunxi_priv *priv = dev_get_priv(dev); + int ret; + + ret = ohci_deregister(dev); + if (ret) + return ret; + + sunxi_usb_phy_power_off(priv->phy_index); + sunxi_usb_phy_exit(priv->phy_index); + +#ifdef CONFIG_SUNXI_GEN_SUN6I + clrbits_le32(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); +#endif + clrbits_le32(&ccm->usb_clk_cfg, priv->usb_gate_mask); + clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); + + return 0; +} + +static const struct udevice_id ohci_usb_ids[] = { + { .compatible = "allwinner,sun4i-a10-ohci", }, + { .compatible = "allwinner,sun5i-a13-ohci", }, + { .compatible = "allwinner,sun6i-a31-ohci", }, + { .compatible = "allwinner,sun7i-a20-ohci", }, + { .compatible = "allwinner,sun8i-a23-ohci", }, + { .compatible = "allwinner,sun9i-a80-ohci", }, + { } +}; + +U_BOOT_DRIVER(usb_ohci) = { + .name = "ohci_sunxi", + .id = UCLASS_USB, + .of_match = ohci_usb_ids, + .probe = ohci_usb_probe, + .remove = ohci_usb_remove, + .ops = &ohci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct ohci_sunxi_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index c8ebb54..222e739 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -297,6 +297,9 @@ extern int soft_i2c_gpio_scl; #endif
#ifdef CONFIG_USB_EHCI +#define CONFIG_USB_OHCI_NEW +#define CONFIG_USB_OHCI_SUNXI +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1 #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 1 #endif
@@ -314,7 +317,7 @@ extern int soft_i2c_gpio_scl; #define CONFIG_CONSOLE_MUX #define CONFIG_PREBOOT #define CONFIG_SYS_STDIO_DEREGISTER -#define CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE +#define CONFIG_SYS_USB_EVENT_POLL #endif
#if !defined CONFIG_ENV_IS_IN_MMC && \

On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
This commit adds support for the OHCI companion controller, which makes usb-1 devices directly plugged into to usb root port work.
Note for now this switches usb-keyboard support for sunxi back from int-queue support to the old interrupt polling method. Adding int-queue support to the ohci code and switching back to int-queue support is in the works.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de Acked-by: Ian Campbell ijc@hellion.org.uk
arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sunxi.c | 104 ++++++++++++++++++++++++++ include/configs/sunxi-common.h | 5 +- 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/host/ohci-sunxi.c
Applied to u-boot-dm, thanks!

Hi Simon,
On 12-05-15 00:37, Simon Glass wrote:
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
This commit adds support for the OHCI companion controller, which makes usb-1 devices directly plugged into to usb root port work.
Note for now this switches usb-keyboard support for sunxi back from int-queue support to the old interrupt polling method. Adding int-queue support to the ohci code and switching back to int-queue support is in the works.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de Acked-by: Ian Campbell ijc@hellion.org.uk
arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sunxi.c | 104 ++++++++++++++++++++++++++ include/configs/sunxi-common.h | 5 +- 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/host/ohci-sunxi.c
Applied to u-boot-dm, thanks!
Thanks for merging this series!
Can you pick up these patches from yesterday too ? They have already been reviewed and acked by Marek, and they sit on to of this series :
http://patchwork.ozlabs.org/patch/471001/ http://patchwork.ozlabs.org/patch/471004/ http://patchwork.ozlabs.org/patch/471003/ http://patchwork.ozlabs.org/patch/471005/
Note the last one has queue misspelled (twice) in the commit msg you may want to amend that.
Thanks & Regards,
Hans

Hi Hans,
On 12 May 2015 at 01:23, Hans de Goede hdegoede@redhat.com wrote:
Hi Simon,
On 12-05-15 00:37, Simon Glass wrote:
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
This commit adds support for the OHCI companion controller, which makes usb-1 devices directly plugged into to usb root port work.
Note for now this switches usb-keyboard support for sunxi back from int-queue support to the old interrupt polling method. Adding int-queue support to the ohci code and switching back to int-queue support is in the works.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de Acked-by: Ian Campbell ijc@hellion.org.uk
arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sunxi.c | 104 ++++++++++++++++++++++++++ include/configs/sunxi-common.h | 5 +- 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/host/ohci-sunxi.c
Applied to u-boot-dm, thanks!
Thanks for merging this series!
Can you pick up these patches from yesterday too ? They have already been reviewed and acked by Marek, and they sit on to of this series :
http://patchwork.ozlabs.org/patch/471001/ http://patchwork.ozlabs.org/patch/471004/ http://patchwork.ozlabs.org/patch/471003/ http://patchwork.ozlabs.org/patch/471005/
Note the last one has queue misspelled (twice) in the commit msg you may want to amend that.
I get a build error with M5485BFE. I stopped the build after that so there may be others.
21: sunxi: Change usb-kbd interrupt polling to use an usb interrupt queue m68k: + M5485BFE -make[2]: *** [drivers/usb/musb-new/musb_host.o] Interrupt -make[1]: *** [drivers/usb/musb-new] Interrupt -make: *** wait: No child processes. Stop. -make[2]: *** Deleting file `drivers/mmc/mmc.o' -make[2]: *** [drivers/mmc/mmc.o] Interrupt -make[1]: *** [drivers/mmc] Interrupt +../drivers/usb/host/ohci-hcd.c:1637:46: error: 'struct usb_device' has no member named 'dev' +../drivers/usb/host/ohci-hcd.c: In function '_ohci_poll_int_queue': +../drivers/usb/host/ohci-hcd.c:1683:46: error: 'struct usb_device' has no member named 'dev' +make[2]: *** [drivers/usb/host/ohci-hcd.o] Error 1 +make[1]: *** [drivers/usb/host] Error 2 +make: *** [sub-make] Error 2 w+../drivers/usb/host/ohci-hcd.c: In function '_ohci_create_int_queue': w+../drivers/usb/host/ohci-hcd.c:1637:2: warning: implicit declaration of function 'usb_get_bus' [-Wimplicit-function-declaration]
Actually, it found these also:
arm: + pm9g45 at91sam9g20ek_2mmc_nandflash m68k: + M5485BFE powerpc: + PLU405 MPC8641HPCN_36BIT digsy_mtc_rev5 PMC440 yosemite
Am I missing a patch perhaps?
Regards, SImon

Hi,
On 13-05-15 00:39, Simon Glass wrote:
Hi Hans,
On 12 May 2015 at 01:23, Hans de Goede hdegoede@redhat.com wrote:
Hi Simon,
On 12-05-15 00:37, Simon Glass wrote:
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
This commit adds support for the OHCI companion controller, which makes usb-1 devices directly plugged into to usb root port work.
Note for now this switches usb-keyboard support for sunxi back from int-queue support to the old interrupt polling method. Adding int-queue support to the ohci code and switching back to int-queue support is in the works.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de Acked-by: Ian Campbell ijc@hellion.org.uk
arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sunxi.c | 104 ++++++++++++++++++++++++++ include/configs/sunxi-common.h | 5 +- 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/host/ohci-sunxi.c
Applied to u-boot-dm, thanks!
Thanks for merging this series!
Can you pick up these patches from yesterday too ? They have already been reviewed and acked by Marek, and they sit on to of this series :
http://patchwork.ozlabs.org/patch/471001/ http://patchwork.ozlabs.org/patch/471004/ http://patchwork.ozlabs.org/patch/471003/ http://patchwork.ozlabs.org/patch/471005/
Note the last one has queue misspelled (twice) in the commit msg you may want to amend that.
I get a build error with M5485BFE. I stopped the build after that so there may be others.
21: sunxi: Change usb-kbd interrupt polling to use an usb interrupt queue m68k: + M5485BFE -make[2]: *** [drivers/usb/musb-new/musb_host.o] Interrupt -make[1]: *** [drivers/usb/musb-new] Interrupt -make: *** wait: No child processes. Stop. -make[2]: *** Deleting file `drivers/mmc/mmc.o' -make[2]: *** [drivers/mmc/mmc.o] Interrupt -make[1]: *** [drivers/mmc] Interrupt +../drivers/usb/host/ohci-hcd.c:1637:46: error: 'struct usb_device' has no member named 'dev' +../drivers/usb/host/ohci-hcd.c: In function '_ohci_poll_int_queue': +../drivers/usb/host/ohci-hcd.c:1683:46: error: 'struct usb_device' has no member named 'dev' +make[2]: *** [drivers/usb/host/ohci-hcd.o] Error 1 +make[1]: *** [drivers/usb/host] Error 2 +make: *** [sub-make] Error 2 w+../drivers/usb/host/ohci-hcd.c: In function '_ohci_create_int_queue': w+../drivers/usb/host/ohci-hcd.c:1637:2: warning: implicit declaration of function 'usb_get_bus' [-Wimplicit-function-declaration]
Actually, it found these also:
arm: + pm9g45 at91sam9g20ek_2mmc_nandflash m68k: + M5485BFE powerpc: + PLU405 MPC8641HPCN_36BIT digsy_mtc_rev5 PMC440 yosemite
Am I missing a patch perhaps?
No, this is my bad, I did not test building with any configs which have CONFIG_DM_USB=n
A v2 of this set with this fixed is coming up.
Regards,
Hans

Hi Hans,
On 13 May 2015 at 06:40, Hans de Goede hdegoede@redhat.com wrote:
Hi,
On 13-05-15 00:39, Simon Glass wrote:
Hi Hans,
On 12 May 2015 at 01:23, Hans de Goede hdegoede@redhat.com wrote:
Hi Simon,
On 12-05-15 00:37, Simon Glass wrote:
On 10 May 2015 at 06:10, Hans de Goede hdegoede@redhat.com wrote:
This commit adds support for the OHCI companion controller, which makes usb-1 devices directly plugged into to usb root port work.
Note for now this switches usb-keyboard support for sunxi back from int-queue support to the old interrupt polling method. Adding int-queue support to the ohci code and switching back to int-queue support is in the works.
Signed-off-by: Hans de Goede hdegoede@redhat.com Acked-by: Marek Vasut marex@denx.de Acked-by: Ian Campbell ijc@hellion.org.uk
arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sunxi.c | 104 ++++++++++++++++++++++++++ include/configs/sunxi-common.h | 5 +- 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/host/ohci-sunxi.c
Applied to u-boot-dm, thanks!
Thanks for merging this series!
Can you pick up these patches from yesterday too ? They have already been reviewed and acked by Marek, and they sit on to of this series :
http://patchwork.ozlabs.org/patch/471001/ http://patchwork.ozlabs.org/patch/471004/ http://patchwork.ozlabs.org/patch/471003/ http://patchwork.ozlabs.org/patch/471005/
Note the last one has queue misspelled (twice) in the commit msg you may want to amend that.
I get a build error with M5485BFE. I stopped the build after that so there may be others.
21: sunxi: Change usb-kbd interrupt polling to use an usb interrupt queue m68k: + M5485BFE -make[2]: *** [drivers/usb/musb-new/musb_host.o] Interrupt -make[1]: *** [drivers/usb/musb-new] Interrupt -make: *** wait: No child processes. Stop. -make[2]: *** Deleting file `drivers/mmc/mmc.o' -make[2]: *** [drivers/mmc/mmc.o] Interrupt -make[1]: *** [drivers/mmc] Interrupt +../drivers/usb/host/ohci-hcd.c:1637:46: error: 'struct usb_device' has no member named 'dev' +../drivers/usb/host/ohci-hcd.c: In function '_ohci_poll_int_queue': +../drivers/usb/host/ohci-hcd.c:1683:46: error: 'struct usb_device' has no member named 'dev' +make[2]: *** [drivers/usb/host/ohci-hcd.o] Error 1 +make[1]: *** [drivers/usb/host] Error 2 +make: *** [sub-make] Error 2 w+../drivers/usb/host/ohci-hcd.c: In function '_ohci_create_int_queue': w+../drivers/usb/host/ohci-hcd.c:1637:2: warning: implicit declaration of function 'usb_get_bus' [-Wimplicit-function-declaration]
Actually, it found these also:
arm: + pm9g45 at91sam9g20ek_2mmc_nandflash m68k: + M5485BFE powerpc: + PLU405 MPC8641HPCN_36BIT digsy_mtc_rev5 PMC440 yosemite
Am I missing a patch perhaps?
No, this is my bad, I did not test building with any configs which have CONFIG_DM_USB=n
A v2 of this set with this fixed is coming up.
OK, that did it. Thanks.
- Simon
participants (4)
-
Hans de Goede
-
Ian Campbell
-
Marek Vasut
-
Simon Glass