[U-Boot] [PATCH RFC v2 0/6] usb: host: Add driver model support

Hi Marek, Simon,
This patch-series comes as a update for an earlier posted series[1] "[PATCH RFC 0/2] usb: host: Add a wrapper layer for mutiple host support" which was posted long back.
We had discussion to introduce the driver model instead of the approach used in [1]. The driver model seems pretty straight-forward and easier to implement besides giving a clean approach to use multiple host controller types, viz. EHCI, XHCI or OHCI simultaneously on a platform which has such provision.
It's rather bad on my side that it took so long to post the updated version. Got busy with the projects. :-(
So here's the RFC-v2 which implements the driver model approach. I have added support on OHCI, EHCI and XHCI and enabled EHCI and XHCI on Exynos5250 machines. Though not tested thoroughly, i can see EHCI and XHCI working together (enumerating the Root hubs).
Let me know you comments on what you think of current approach.
Thanks Vivek
[1] [PATCH RFC 0/2] usb: host: Add a wrapper layer for mutiple host support http://lists.denx.de/pipermail/u-boot/2014-June/182559.html
Vivek Gautam (6): usb: Rename usb_submit_int_msg() API to usb_int_msg() dm: usb: Make necessary changes in framework for driver model dm: usb-host: Add UCLASS driver for USB dm: usb-host: Add support for driver model in o/e/xhci. arm: exynos5: Enable EHCI and XHCI hcds through device tree. configs: smdk5250: Enable using XHCI and EHCI together
arch/arm/dts/exynos5.dtsi | 8 +++ common/usb.c | 101 ++++++++++++++++++++++++++++++--- common/usb_hub.c | 2 +- common/usb_kbd.c | 4 +- common/usb_storage.c | 2 +- drivers/usb/host/Kconfig | 9 +++ drivers/usb/host/Makefile | 3 + drivers/usb/host/ehci-hcd.c | 36 +++++++++--- drivers/usb/host/ohci-hcd.c | 35 +++++++++--- drivers/usb/host/usb-uclass.c | 107 +++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.c | 34 ++++++++--- include/configs/exynos5-common.h | 3 + include/configs/exynos5250-common.h | 3 + include/configs/smdk5250.h | 2 + include/dm/uclass-id.h | 1 + include/usb.h | 62 +++++++++++++++----- 16 files changed, 365 insertions(+), 47 deletions(-) create mode 100644 drivers/usb/host/usb-uclass.c

Until yet usb_**_msg() APIs don't contain the string 'submit'. Rename it to make things uniform. This is also helping while adding a host translational layer wherein we are using usb_submit_**_msg string to name APIs.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- common/usb.c | 4 ++-- common/usb_kbd.c | 4 ++-- common/usb_storage.c | 2 +- include/usb.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/common/usb.c b/common/usb.c index 32e15cd..849df27 100644 --- a/common/usb.c +++ b/common/usb.c @@ -162,10 +162,10 @@ int usb_disable_asynch(int disable) /* * submits an Interrupt Message */ -int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, +int usb_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval) { - return submit_int_msg(dev, pipe, buffer, transfer_len, interval); + return usb_submit_int_msg(dev, pipe, buffer, transfer_len, interval); }
/* diff --git a/common/usb_kbd.c b/common/usb_kbd.c index ecc3085..d5d33a5 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -313,7 +313,7 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) struct usb_kbd_pdata *data = dev->privptr;
/* Submit a interrupt transfer request */ - usb_submit_int_msg(dev, data->intpipe, &data->new[0], data->intpktsize, + usb_int_msg(dev, data->intpipe, &data->new[0], data->intpktsize, data->intinterval);
usb_kbd_irq_worker(dev); @@ -458,7 +458,7 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) data->intinterval); if (!data->intq) { #else - if (usb_submit_int_msg(dev, data->intpipe, data->new, data->intpktsize, + if (usb_int_msg(dev, data->intpipe, data->new, data->intpktsize, data->intinterval) < 0) { #endif printf("Failed to get keyboard state from device %04x:%04x\n", diff --git a/common/usb_storage.c b/common/usb_storage.c index 1411737..7094eea 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -599,7 +599,7 @@ static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us) int timeout;
us->ip_wanted = 1; - submit_int_msg(us->pusb_dev, us->irqpipe, + usb_int_msg(us->pusb_dev, us->irqpipe, (void *) &us->ip_data, us->irqmaxp, us->irqinterval); timeout = 1000; while (timeout--) { diff --git a/include/usb.h b/include/usb.h index a8fee0b..d1576b2 100644 --- a/include/usb.h +++ b/include/usb.h @@ -252,7 +252,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, void *data, unsigned short size, int timeout); int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout); -int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, +int usb_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval); int usb_disable_asynch(int disable); int usb_maxpacket(struct usb_device *dev, unsigned long pipe);

Add wrapper functions for usb layer operations for control, bulk, interrupt transfers to accomodate support for driver model.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- common/usb.c | 99 ++++++++++++++++++++++++++++++++++++++++++++---- common/usb_hub.c | 2 +- include/dm/uclass-id.h | 1 + include/usb.h | 60 +++++++++++++++++++++++------ 4 files changed, 142 insertions(+), 20 deletions(-)
diff --git a/common/usb.c b/common/usb.c index 849df27..407cc30 100644 --- a/common/usb.c +++ b/common/usb.c @@ -29,6 +29,7 @@ #include <common.h> #include <command.h> #include <asm/processor.h> +#include <dm/uclass.h> #include <linux/compiler.h> #include <linux/ctype.h> #include <asm/byteorder.h> @@ -45,12 +46,83 @@ static struct usb_device usb_dev[USB_MAX_DEVICE]; static int dev_index; static int asynch_allowed;
+static struct udevice *udev_usb; + char usb_started; /* flag for the started/stopped USB status */
#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif
+#ifdef CONFIG_DM_USB +/* Wrappers for Driver model */ +static inline int _usb_lowlevel_init(int index, enum usb_init_type init, + void **ctrl) +{ + return usb_lowlevel_init(index, USB_INIT_HOST, ctrl, udev_usb); +} + +static inline int _usb_lowlevel_stop(int index) +{ + return usb_lowlevel_stop(index, udev_usb); +} + +static inline int _usb_submit_control_msg(struct usb_device *dev, + unsigned long pipe, void *data, + int transfer_len, struct devrequest *setup) +{ + return usb_submit_control_msg(dev, pipe, data, transfer_len, + setup, dev->udev_usb); +} + +static inline int _usb_submit_bulk_msg(struct usb_device *dev, + unsigned int pipe, void *data, int transfer_len) +{ + return usb_submit_bulk_msg(dev, pipe, data, transfer_len, + dev->udev_usb); +} + +static inline int _usb_submit_int_msg(struct usb_device *dev, + unsigned long pipe, void *data, + int transfer_len, int interval) +{ + return usb_submit_int_msg(dev, pipe, data, transfer_len, + interval, dev->udev_usb); +} +#else +static inline int _usb_lowlevel_init(int index, enum usb_init_type init, + void **ctrl) +{ + return usb_lowlevel_init(index, USB_INIT_HOST, ctrl); +} + +static inline int _usb_lowlevel_stop(int index) +{ + return usb_lowlevel_stop(index); +} + +static inline int _usb_submit_control_msg(struct usb_device *dev, + unsigned long pipe, void *data, + int transfer_len, struct devrequest *setup) +{ + return usb_submit_control_msg(dev, pipe, data, transfer_len, setup); +} + +static inline int _usb_submit_bulk_msg(struct usb_device *dev, + unsigned int pipe, void *data, int transfer_len) +{ + return usb_submit_bulk_msg(dev, pipe, data, transfer_len); +} + +static inline int _usb_submit_int_msg(struct usb_device *dev, + unsigned long pipe, void *data, + int transfer_len, int interval) +{ + return usb_submit_int_msg(dev, pipe, data, transfer_len, interval); +} +#endif + + /*************************************************************************** * Init USB Device */ @@ -74,9 +146,20 @@ int usb_init(void)
/* init low_level USB */ for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) { +#ifdef CONFIG_DM_USB + /* Get the udevice here for given index */ + uclass_get_device(UCLASS_USB, i, &udev_usb); +#else + udev_usb = -ERR_PTR(ENOSYS); +#endif + + /* Now this udev is a pointer to the particular controller + * driver, which we can use now. + */ + /* init low_level USB */ printf("USB%d: ", i); - ret = usb_lowlevel_init(i, USB_INIT_HOST, &ctrl); + ret = _usb_lowlevel_init(i, USB_INIT_HOST, &ctrl); if (ret == -ENODEV) { /* No such device. */ puts("Port not available.\n"); controllers_initialized++; @@ -94,7 +177,7 @@ int usb_init(void) controllers_initialized++; start_index = dev_index; printf("scanning bus %d for devices... ", i); - dev = usb_alloc_new_device(ctrl); + dev = usb_alloc_new_device(ctrl, udev_usb); /* * device 0 is always present * (root hub, so let it analyze) @@ -132,7 +215,7 @@ int usb_stop(void) usb_hub_reset();
for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) { - if (usb_lowlevel_stop(i)) + if (_usb_lowlevel_stop(i)) printf("failed to stop USB controller %d\n", i); } } @@ -165,7 +248,7 @@ int usb_disable_asynch(int disable) int usb_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval) { - return usb_submit_int_msg(dev, pipe, buffer, transfer_len, interval); + return _usb_submit_int_msg(dev, pipe, buffer, transfer_len, interval); }
/* @@ -200,7 +283,7 @@ 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) + if (_usb_submit_control_msg(dev, pipe, data, size, setup_packet) < 0) return -1; if (timeout == 0) return (int)size; @@ -233,7 +316,7 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, if (len < 0) return -1; dev->status = USB_ST_NOT_PROC; /*not yet processed */ - if (submit_bulk_msg(dev, pipe, data, len) < 0) + if (_usb_submit_bulk_msg(dev, pipe, data, len) < 0) return -1; while (timeout--) { if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) @@ -830,7 +913,8 @@ struct usb_device *usb_get_dev_index(int index) /* returns a pointer of a new device structure or NULL, if * no device struct is available */ -struct usb_device *usb_alloc_new_device(void *controller) +struct usb_device *usb_alloc_new_device(void *controller, + struct udevice *udev_usb) { int i; debug("New Device %d\n", dev_index); @@ -845,6 +929,7 @@ struct usb_device *usb_alloc_new_device(void *controller) usb_dev[dev_index].children[i] = NULL; usb_dev[dev_index].parent = NULL; usb_dev[dev_index].controller = controller; + usb_dev[dev_index].udev_usb = udev_usb; dev_index++; return &usb_dev[dev_index - 1]; } diff --git a/common/usb_hub.c b/common/usb_hub.c index 66b4a72..0afe6ac 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -246,7 +246,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) mdelay(200);
/* Allocate a new device struct for it */ - usb = usb_alloc_new_device(dev->controller); + usb = usb_alloc_new_device(dev->controller, dev->udev_usb);
switch (portstatus & USB_PORT_STAT_SPEED_MASK) { case USB_PORT_STAT_SUPER_SPEED: diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 91bb90d..4f91e87 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -34,6 +34,7 @@ enum uclass_id { UCLASS_I2C_GENERIC, /* Generic I2C device */ UCLASS_I2C_EEPROM, /* I2C EEPROM device */ UCLASS_MOD_EXP, /* RSA Mod Exp device */ + UCLASS_USB, /* USB host class */
UCLASS_COUNT, UCLASS_INVALID = -1, diff --git a/include/usb.h b/include/usb.h index d1576b2..861f2fa 100644 --- a/include/usb.h +++ b/include/usb.h @@ -13,6 +13,7 @@ #include <linux/usb/ch9.h> #include <asm/cache.h> #include <part.h> +#include <dm.h>
/* * The EHCI spec says that we must align to at least 32 bytes. However, @@ -130,6 +131,9 @@ struct usb_device { void *controller; /* hardware controller private data */ /* slot_id - for xHCI enabled devices */ unsigned int slot_id; + + /* UClass device */ + struct udevice *udev_usb; };
struct int_queue; @@ -158,20 +162,45 @@ enum usb_init_type { defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_MUSB_SUNXI) || \ defined(CONFIG_USB_XHCI) || defined(CONFIG_USB_DWC2)
+#ifdef CONFIG_DM_USB +int usb_lowlevel_init(int index, enum usb_init_type init, + void **controller, struct udevice *udev_usb); +int usb_lowlevel_stop(int index, struct udevice *udev_usb); + +int usb_submit_bulk_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct udevice *udev_usb); +int usb_submit_control_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup, struct udevice *udev_usb); +int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + int interval, struct udevice *udev_usb); + +struct usb_ops { + int (*lowlevel_init)(int index, enum usb_init_type init, + void **controller); + int (*lowlevel_stop)(int index); + int (*submit_bulk_msg)(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len); + int (*submit_ctrl_msg)(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup); + int (*submit_int_msg)(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + int interval); +}; +#else int usb_lowlevel_init(int index, enum usb_init_type init, void **controller); int usb_lowlevel_stop(int index); -#ifdef CONFIG_MUSB_HOST -void usb_reset_root_port(void); -#else -#define usb_reset_root_port() -#endif - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, +int usb_submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len); -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup); -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, int interval); +int usb_submit_control_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup); +int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, int interval); +#endif
#if defined CONFIG_USB_EHCI || defined CONFIG_MUSB_HOST struct int_queue *create_int_queue(struct usb_device *dev, unsigned long pipe, @@ -180,6 +209,12 @@ int destroy_int_queue(struct usb_device *dev, struct int_queue *queue); void *poll_int_queue(struct usb_device *dev, struct int_queue *queue); #endif
+#ifdef CONFIG_MUSB_HOST +void usb_reset_root_port(void); +#else +#define usb_reset_root_port() +#endif + /* Defines */ #define USB_UHCI_VEND_ID 0x8086 #define USB_UHCI_DEV_ID 0x7112 @@ -428,7 +463,8 @@ void usb_hub_reset(void); int hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat);
-struct usb_device *usb_alloc_new_device(void *controller); +struct usb_device *usb_alloc_new_device(void *controller, + struct udevice *udev_usb);
int usb_new_device(struct usb_device *dev); void usb_free_device(void);

Adding a UCLASS driver for USB based on driver-model, to facilitate binding mutiple host-controllers to their respective drivers, and thereby enable using mutiple controllers simultaneously on a platform.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- drivers/usb/host/Kconfig | 9 ++++ drivers/usb/host/Makefile | 3 ++ drivers/usb/host/usb-uclass.c | 107 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 drivers/usb/host/usb-uclass.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 30d1457..fceacbb 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -3,6 +3,15 @@ # comment "USB Host Controller Drivers"
+config DM_USB + bool "USB Driver model support" + ---help--- + Driver model support for USB host controller drivers. + This will allow use of mutiple kinds of host controllers viz. OHCI, + EHCI, XHCI, etc simultaneously which was not possible till now. + Say 'y' if you have mutiple types of controllers on your boards + and would like to enable support for all of them. + config USB_XHCI_HCD bool "xHCI HCD (USB 3.0) support" ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 66d6e9a..d54e2a7 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -5,6 +5,9 @@ # SPDX-License-Identifier: GPL-2.0+ #
+# usb driver-model +obj-$(CONFIG_DM_USB) += usb-uclass.o + # ohci obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o obj-$(CONFIG_USB_ATMEL) += ohci-at91.o diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c new file mode 100644 index 0000000..e7a97ec --- /dev/null +++ b/drivers/usb/host/usb-uclass.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * + * Provides a smooth translation from usb_*() APIs from + * core usb drivers to controller drivers, enabling simultaneous + * use of different types of controller at once. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <linux/err.h> +#include <asm/io.h> +#include <usb.h> +//#include <linux/list.h> + +//DECLARE_GLOBAL_DATA_PTR; + +UCLASS_DRIVER(usb) = { + .name = "usb", + .id = UCLASS_USB, +}; + +int usb_lowlevel_init(int index, enum usb_init_type init, + void **controller, struct udevice *udev_usb) +{ + const struct usb_ops *ops; + + if (IS_ERR(udev_usb)) + return -EINVAL; + + ops = device_get_ops(udev_usb); + + if (!ops->lowlevel_init) + return -ENOSYS; + + return ops->lowlevel_init(index, init, controller); +} + +int usb_lowlevel_stop(int index, struct udevice *udev_usb) +{ + const struct usb_ops *ops; + + if (IS_ERR(udev_usb)) + return -EINVAL; + + ops = device_get_ops(udev_usb); + + if (!ops->lowlevel_stop) + return -ENOSYS; + + return ops->lowlevel_stop(index); +} + +int usb_submit_bulk_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct udevice *udev_usb) +{ + const struct usb_ops *ops; + + if (IS_ERR(udev_usb)) + return -EINVAL; + + ops = device_get_ops(udev_usb); + + if (!ops->submit_bulk_msg) + return -ENOSYS; + + return ops->submit_bulk_msg(dev, pipe, buffer, transfer_len); +} + +int usb_submit_control_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup, struct udevice *udev_usb) +{ + const struct usb_ops *ops; + + if (IS_ERR(udev_usb)) + return -EINVAL; + + ops = device_get_ops(udev_usb); + + if (!ops->submit_ctrl_msg) + return -ENOSYS; + + return ops->submit_ctrl_msg(dev,pipe, buffer, transfer_len, setup); +} + +int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + int interval, struct udevice *udev_usb) +{ + const struct usb_ops *ops; + + if (IS_ERR(udev_usb)) + return -EINVAL; + + ops = device_get_ops(udev_usb); + + if (!ops->submit_int_msg) + return -ENOSYS; + + return ops->submit_int_msg(dev, pipe, buffer, transfer_len, interval); +}

Adding support for driver model and necessary callbacks in ohci/ehci/xhci.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- drivers/usb/host/ehci-hcd.c | 36 ++++++++++++++++++++++++++++-------- drivers/usb/host/ohci-hcd.c | 35 ++++++++++++++++++++++++++++------- drivers/usb/host/xhci.c | 34 +++++++++++++++++++++++++++------- 3 files changed, 83 insertions(+), 22 deletions(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f1fb190..6320b98 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -930,13 +930,13 @@ unknown: return -1; }
-int usb_lowlevel_stop(int index) +int ehci_lowlevel_stop(int index) { ehci_shutdown(&ehcic[index]); return ehci_hcd_stop(index); }
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) +int ehci_lowlevel_init(int index, enum usb_init_type init, void **controller) { uint32_t reg; uint32_t cmd; @@ -1065,8 +1065,8 @@ done: }
int -submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length) +ehci_submit_bulk_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int length) {
if (usb_pipetype(pipe) != PIPE_BULK) { @@ -1077,8 +1077,8 @@ submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, }
int -submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *setup) +ehci_submit_control_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int length, struct devrequest *setup) { struct ehci_ctrl *ctrl = dev->controller;
@@ -1387,8 +1387,8 @@ out: }
int -submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, int interval) +ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int length, int interval) { void *backbuffer; struct int_queue *queue; @@ -1423,3 +1423,23 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, /* everything worked out fine */ return result; } + +static const struct udevice_id ehci_hcd_id[] = { + { "ehci-hcd", 0 }, + { }, +}; + +static const struct usb_ops ehci_ops = { + .lowlevel_init = ehci_lowlevel_init, + .lowlevel_stop = ehci_lowlevel_stop, + .submit_ctrl_msg = ehci_submit_control_msg, + .submit_bulk_msg = ehci_submit_bulk_msg, + .submit_int_msg = ehci_submit_int_msg, +}; + +U_BOOT_DRIVER(ehci_hcd_drv) = { + .name = "ehci_hcd_drv", + .of_match = ehci_hcd_id, + .id = UCLASS_USB, + .ops = &ehci_ops, +}; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 97a7ede..3bfc295 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1465,15 +1465,15 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, }
/* submit routines called from usb.c */ -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len) +int ohci_submit_bulk_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len) { info("submit_bulk_msg"); return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); }
-int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup) +int ohci_submit_control_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, struct devrequest *setup) { int maxsize = usb_maxpacket(dev, pipe);
@@ -1499,7 +1499,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); }
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +int ohci_submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval) { info("submit_int_msg"); @@ -1748,7 +1748,8 @@ static void hc_release_ohci(ohci_t *ohci) */ static char ohci_inited = 0;
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) +int ohci_lowlevel_init(int index, enum usb_init_type init, + void **controller) { #ifdef CONFIG_PCI_OHCI pci_dev_t pdev; @@ -1854,7 +1855,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) return 0; }
-int usb_lowlevel_stop(int index) +int ohci_lowlevel_stop(int index) { /* this gets called really early - before the controller has */ /* even been initialized! */ @@ -1880,3 +1881,23 @@ int usb_lowlevel_stop(int index) ohci_inited = 0; return 0; } + +static const struct udevice_id ohci_hcd_id[] = { + { "ohci-hcd", 0 }, + { }, +}; + +static const struct usb_ops ohci_ops = { + .lowlevel_init = ohci_lowlevel_init + .lowlevel_stop = ohci_lowlevel_stop + .submit_ctrl_msg = ohci_submit_control_msg + .submit_bulk_msg = ohci_submit_bulk_msg + .submit_int_msg = ohci_submit_int_msg +}; + +U_BOOT_DRIVER(ohci_hcd_drv) = { + .name = "ohci_hcd_drv", + .of_match = ohci_hcd_id, + .id = UCLASS_USB, + .ops = &ohci_ops, +}; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 87f2972..b3c3aab 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -859,7 +859,7 @@ unknown: * @return 0 */ int -submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, +xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, int interval) { /* @@ -879,8 +879,8 @@ submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, * @return returns 0 if successful else -1 on failure */ int -submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length) +xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, + void *buffer, int length) { if (usb_pipetype(pipe) != PIPE_BULK) { printf("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); @@ -901,8 +901,8 @@ submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, * @return returns 0 if successful else -1 on failure */ int -submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, - int length, struct devrequest *setup) +xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, + void *buffer, int length, struct devrequest *setup) { struct xhci_ctrl *ctrl = udev->controller; int ret = 0; @@ -936,7 +936,7 @@ submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, * @param index index to the host controller data structure * @return pointer to the intialised controller */ -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) +int xhci_lowlevel_init(int index, enum usb_init_type init, void **controller) { uint32_t val; uint32_t val2; @@ -1009,7 +1009,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) * @param index index to the host controller data structure * @return none */ -int usb_lowlevel_stop(int index) +int xhci_lowlevel_stop(int index) { struct xhci_ctrl *ctrl = (xhcic + index); u32 temp; @@ -1028,3 +1028,23 @@ int usb_lowlevel_stop(int index)
return 0; } + +static const struct udevice_id xhci_hcd_id[] = { + { "xhci-hcd", 0 }, + { }, +}; + +static const struct usb_ops xhci_ops = { + .lowlevel_init = xhci_lowlevel_init, + .lowlevel_stop = xhci_lowlevel_stop, + .submit_ctrl_msg = xhci_submit_control_msg, + .submit_bulk_msg = xhci_submit_bulk_msg, + .submit_int_msg = xhci_submit_int_msg, +}; + +U_BOOT_DRIVER(xhci_hcd_drv) = { + .name = "xhci_hcd_drv", + .of_match = xhci_hcd_id, + .id = UCLASS_USB, + .ops = &xhci_ops, +};

Add devices for XHCI-HCD and EHCI-HCD in exynos5 family.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- arch/arm/dts/exynos5.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/arch/arm/dts/exynos5.dtsi b/arch/arm/dts/exynos5.dtsi index 238acb8..5cdf406 100644 --- a/arch/arm/dts/exynos5.dtsi +++ b/arch/arm/dts/exynos5.dtsi @@ -157,6 +157,14 @@ }; };
+ ehcihcd { + compatible = "ehci-hcd"; + }; + + xhcihcd { + compatible = "xhci-hcd"; + }; + tmu@10060000 { compatible = "samsung,exynos-tmu"; reg = <0x10060000 0x10000>;

With driver model now we can enable both EHCI and XHCI on Exynos5250.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- include/configs/exynos5-common.h | 3 +++ include/configs/exynos5250-common.h | 3 +++ include/configs/smdk5250.h | 2 ++ 3 files changed, 8 insertions(+)
diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index 0ba39a2..6f0e7f8 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -173,8 +173,11 @@
#define CONFIG_CMD_GPIO
+#define CONFIG_DM + /* USB */ #define CONFIG_CMD_USB +#define CONFIG_DM_USB #define CONFIG_USB_STORAGE #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 diff --git a/include/configs/exynos5250-common.h b/include/configs/exynos5250-common.h index ae0e5ff..1843e25 100644 --- a/include/configs/exynos5250-common.h +++ b/include/configs/exynos5250-common.h @@ -41,6 +41,9 @@ /* I2C */ #define CONFIG_MAX_I2C_NUM 8
+/* USB */ +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 + /* Display */ #define CONFIG_LCD #ifdef CONFIG_LCD diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h index 3b06d30..27ba454 100644 --- a/include/configs/smdk5250.h +++ b/include/configs/smdk5250.h @@ -24,6 +24,8 @@ #define CONFIG_BOARD_COMMON #define CONFIG_ARCH_EARLY_INIT_R
+#define CONFIG_USB_EHCI +#define CONFIG_USB_EHCI_EXYNOS #define CONFIG_USB_XHCI #define CONFIG_USB_XHCI_EXYNOS
participants (1)
-
Vivek Gautam