
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);