Message ID | 1422644697-3735-4-git-send-email-sjg@chromium.org |
---|---|
State | RFC |
Delegated to: | Marek Vasut |
Headers | show |
On Sat, Jan 31, 2015 at 12:34 AM, Simon Glass <sjg@chromium.org> wrote: > While we currently don't have driver model support for block devices and > Ethernet, we can still allow this to work when driver model is used for > USB. > > Signed-off-by: Simon Glass <sjg@chromium.org> > --- > > common/cmd_usb.c | 74 ++++++++++++++++------ > common/usb.c | 28 +++++---- > common/usb_hub.c | 13 +++- > common/usb_storage.c | 148 ++++++++++++++++++++++++++++---------------- > drivers/usb/eth/usb_ether.c | 46 +++++++++++--- > include/usb.h | 76 +++++++++++++++++++++-- > 6 files changed, 286 insertions(+), 99 deletions(-) > > diff --git a/common/cmd_usb.c b/common/cmd_usb.c > index 27813f0..b824634 100644 > --- a/common/cmd_usb.c > +++ b/common/cmd_usb.c > @@ -10,6 +10,7 @@ > > #include <common.h> > #include <command.h> > +#include <dm.h> > #include <asm/byteorder.h> > #include <asm/unaligned.h> > #include <part.h> > @@ -254,16 +255,24 @@ static void usb_display_config(struct usb_device *dev) > > static struct usb_device *usb_find_device(int devnum) > { > - struct usb_device *dev; > +#ifdef CONFIG_DM_USB > + struct udevice *dev; > + > + if (uclass_get_device_by_seq(UCLASS_USB, devnum, &dev)) > + return NULL; > + return dev_get_uclass_priv(dev); > +#else > + struct usb_device *udev; > int d; > > for (d = 0; d < USB_MAX_DEVICE; d++) { > - dev = usb_get_dev_index(d); > - if (dev == NULL) > + udev = usb_get_dev_index(d); > + if (udev == NULL) > return NULL; > - if (dev->devnum == devnum) > - return dev; > + if (udev->devnum == devnum) > + return udev; > } > +#endif > > return NULL; > } > @@ -466,9 +475,8 @@ static void do_usb_start(void) > */ > static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > { > - > + struct usb_device *udev = NULL; > int i; > - struct usb_device *dev = NULL; > extern char usb_started; > #ifdef CONFIG_USB_STORAGE > block_dev_desc_t *stor_dev; > @@ -508,36 +516,64 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > } > if (strncmp(argv[1], "tree", 4) == 0) { > puts("USB device tree:\n"); > +#ifdef CONFIG_DM_USB > + struct udevice *dev; > + > + for (uclass_first_device(UCLASS_USB, &dev); > + dev; > + uclass_next_device(&dev)) { > + struct usb_device *udev = dev_get_uclass_priv(dev); > + > + usb_show_tree(udev); > + } > +#else > for (i = 0; i < USB_MAX_DEVICE; i++) { > + struct usb_device *dev; > + > dev = usb_get_dev_index(i); > if (dev == NULL) > break; > if (dev->parent == NULL) > usb_show_tree(dev); > } > +#endif > return 0; > } > if (strncmp(argv[1], "inf", 3) == 0) { > - int d; > if (argc == 2) { > +#ifdef CONFIG_DM_USB > + struct udevice *dev; > + > + for (uclass_first_device(UCLASS_USB, &dev); > + dev; > + uclass_next_device(&dev)) { > + struct usb_device *udev; > + > + udev = dev_get_uclass_priv(dev); > + usb_display_desc(udev); > + usb_display_config(udev); > + } > +#else > + int d; > for (d = 0; d < USB_MAX_DEVICE; d++) { > - dev = usb_get_dev_index(d); > - if (dev == NULL) > + udev = usb_get_dev_index(d); > + if (udev == NULL) > break; > - usb_display_desc(dev); > - usb_display_config(dev); > + usb_display_desc(udev); > + usb_display_config(udev); > } > +#endif > return 0; > } else { > i = simple_strtoul(argv[2], NULL, 10); > printf("config for device %d\n", i); > - dev = usb_find_device(i); > - if (dev == NULL) { > + udev = usb_find_device(i); > + if (udev == NULL) { > printf("*** No device available ***\n"); > return 0; > } else { > - usb_display_desc(dev); > - usb_display_config(dev); > + usb_display_desc(udev); > + usb_display_config(udev); > } > } > return 0; > @@ -546,13 +582,13 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > if (argc < 5) > return CMD_RET_USAGE; > i = simple_strtoul(argv[2], NULL, 10); > - dev = usb_find_device(i); > - if (dev == NULL) { > + udev = usb_find_device(i); > + if (udev == NULL) { > printf("Device %d does not exist.\n", i); > return 1; > } > i = simple_strtoul(argv[3], NULL, 10); > - return usb_test(dev, i, argv[4]); > + return usb_test(udev, i, argv[4]); > } > #ifdef CONFIG_USB_STORAGE > if (strncmp(argv[1], "stor", 4) == 0) > diff --git a/common/usb.c b/common/usb.c > index 32e15cd..3ccf8a7 100644 > --- a/common/usb.c > +++ b/common/usb.c > @@ -41,12 +41,13 @@ > > #define USB_BUFSIZ 512 > > -static struct usb_device usb_dev[USB_MAX_DEVICE]; > -static int dev_index; > static int asynch_allowed; > - > char usb_started; /* flag for the started/stopped USB status */ > > +#ifndef CONFIG_DM_USB > +static struct usb_device usb_dev[USB_MAX_DEVICE]; > +static int dev_index; > + > #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT > #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 > #endif > @@ -94,12 +95,12 @@ int usb_init(void) > controllers_initialized++; > start_index = dev_index; > printf("scanning bus %d for devices... ", i); > - dev = usb_alloc_new_device(ctrl); > + ret = usb_alloc_new_device(ctrl, &dev); > /* > * device 0 is always present > * (root hub, so let it analyze) > */ > - if (dev) > + if (!ret) > usb_new_device(dev); > > if (start_index == dev_index) > @@ -152,6 +153,7 @@ int usb_disable_asynch(int disable) > asynch_allowed = !disable; > return old_value; > } > +#endif /* !CONFIG_DM_USB */ > > > /*------------------------------------------------------------------- > @@ -815,6 +817,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) > * the USB device are static allocated [USB_MAX_DEVICE]. > */ > > +#ifndef CONFIG_DM_USB > > /* returns a pointer to the device with the index [index]. > * if the device is not assigned (dev->devnum==-1) returns NULL > @@ -827,16 +830,13 @@ struct usb_device *usb_get_dev_index(int index) > return &usb_dev[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) > +int usb_alloc_new_device(void *controller, struct usb_device **devp) > { > int i; > debug("New Device %d\n", dev_index); > if (dev_index == USB_MAX_DEVICE) { > printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE); > - return NULL; > + return -ENOSPC; > } > /* default Address is 0, real addresses start with 1 */ > usb_dev[dev_index].devnum = dev_index + 1; > @@ -846,7 +846,9 @@ struct usb_device *usb_alloc_new_device(void *controller) > usb_dev[dev_index].parent = NULL; > usb_dev[dev_index].controller = controller; > dev_index++; > - return &usb_dev[dev_index - 1]; > + *devp = &usb_dev[dev_index - 1]; > + > + return 0; > } > > /* > @@ -854,7 +856,7 @@ struct usb_device *usb_alloc_new_device(void *controller) > * Called in error cases where configuring a newly attached > * device fails for some reason. > */ > -void usb_free_device(void) > +void usb_free_device(void *controller) > { > dev_index--; > debug("Freeing device node: %d\n", dev_index); > @@ -872,6 +874,8 @@ __weak int usb_alloc_device(struct usb_device *udev) > { > return 0; > } > +#endif /* !CONFIG_DM_USB */ > + > /* > * By the time we get here, the device has gotten a new device ID > * and is in the default state. We need to identify the thing and > diff --git a/common/usb_hub.c b/common/usb_hub.c > index 66b4a72..ccdf755 100644 > --- a/common/usb_hub.c > +++ b/common/usb_hub.c > @@ -211,6 +211,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) > struct usb_device *usb; > ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); > unsigned short portstatus; > + int ret; > > /* Check status */ > if (usb_get_port_status(dev, port + 1, portsts) < 0) { > @@ -246,7 +247,15 @@ 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); > +#ifdef CONFIG_DM_USB > + ret = usb_alloc_new_device(dev->controller_dev, &usb); > +#else > + ret = usb_alloc_new_device(dev->controller, &usb); > +#endif > + if (ret) { > + printf("cannot create new device: reg=%d", ret); > + return; > + } > > switch (portstatus & USB_PORT_STAT_SPEED_MASK) { > case USB_PORT_STAT_SUPER_SPEED: > @@ -269,7 +278,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) > /* Run it through the hoops (find a driver, etc) */ > if (usb_new_device(usb)) { > /* Woops, disable the port */ > - usb_free_device(); > + usb_free_device(dev->controller); > dev->children[port] = NULL; > debug("hub: disabling port %d\n", port + 1); > usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE); > diff --git a/common/usb_storage.c b/common/usb_storage.c > index 1411737..8fb2c18 100644 > --- a/common/usb_storage.c > +++ b/common/usb_storage.c > @@ -33,9 +33,12 @@ > > #include <common.h> > #include <command.h> > +#include <dm.h> > +#include <errno.h> > #include <inttypes.h> > #include <asm/byteorder.h> > #include <asm/processor.h> > +#include <dm/device-internal.h> > > #include <part.h> > #include <usb.h> > @@ -158,7 +161,6 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, > lbaint_t blkcnt, void *buffer); > unsigned long usb_stor_write(int device, lbaint_t blknr, > lbaint_t blkcnt, const void *buffer); > -struct usb_device * usb_get_dev_index(int index); > void uhci_show_temp_int_td(void); > > #ifdef CONFIG_PARTITIONS > @@ -208,6 +210,44 @@ static unsigned int usb_get_max_lun(struct us_data *us) > return (len > 0) ? *result : 0; > } > > +static int usb_stor_probe_device(struct usb_device *dev) > +{ > + if (dev == NULL) > + return -ENOENT; /* no more devices available */ > + > + if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) { > + /* OK, it's a storage device. Iterate over its LUNs > + * and populate `usb_dev_desc'. > + */ > + int lun, max_lun, start = usb_max_devs; > + > + max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]); > + for (lun = 0; > + lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; > + lun++) { > + struct block_dev_desc *blkdev; > + > + blkdev = &usb_dev_desc[usb_max_devs]; > + > + if (usb_stor_get_info(dev, &usb_stor[start], > + &usb_dev_desc[usb_max_devs]) == > + 1) { > + blkdev->lun = lun; > + blkdev->priv = dev; > + usb_max_devs++; > + } > + } > + } > + > + /* if storage device */ > + if (usb_max_devs == USB_MAX_STOR_DEV) { > + printf("max USB Storage Device reached: %d stopping\n", > + usb_max_devs); > + return -ENOSPC; > + } > + > + return 0; > +} > /******************************************************************************* > * scan the usb and reports device info > * to the user if mode = 1 > @@ -215,8 +255,8 @@ static unsigned int usb_get_max_lun(struct us_data *us) > */ > int usb_stor_scan(int mode) > { > + struct block_dev_desc *blkdev; > unsigned char i; > - struct usb_device *dev; > > if (mode == 1) > printf(" scanning usb for storage devices... "); > @@ -224,47 +264,55 @@ int usb_stor_scan(int mode) > usb_disable_asynch(1); /* asynch transfer not allowed */ > > for (i = 0; i < USB_MAX_STOR_DEV; i++) { > - memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t)); > - usb_dev_desc[i].if_type = IF_TYPE_USB; > - usb_dev_desc[i].dev = i; > - usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN; > - usb_dev_desc[i].target = 0xff; > - usb_dev_desc[i].type = DEV_TYPE_UNKNOWN; > - usb_dev_desc[i].block_read = usb_stor_read; > - usb_dev_desc[i].block_write = usb_stor_write; > + blkdev = &usb_dev_desc[i]; > + memset(&blkdev, 0, sizeof(block_dev_desc_t)); > + blkdev->if_type = IF_TYPE_USB; > + blkdev->dev = i; > + blkdev->part_type = PART_TYPE_UNKNOWN; > + blkdev->target = 0xff; > + blkdev->type = DEV_TYPE_UNKNOWN; > + blkdev->block_read = usb_stor_read; > + blkdev->block_write = usb_stor_write; > } > > usb_max_devs = 0; > +#ifdef CONFIG_DM_USB > + struct udevice *bus; > + struct uclass *uc; > + int ret; > + > + ret = uclass_get(UCLASS_USB, &uc); > + if (ret) > + return ret; > + uclass_foreach_dev(bus, uc) { > + struct udevice *dev; > + > + for (device_find_first_child(bus, &dev); > + dev; > + device_find_next_child(&dev)) { > + ret = device_probe(dev); > + if (!ret) { > + struct usb_device *udev; > + > + udev = dev_get_parentdata(dev); > + ret = usb_stor_probe_device(udev); > + } > + if (ret) { > + printf("Device '%s' probe failed: %d\n", > + dev->name, ret); > + } > + } > + } > +#else > for (i = 0; i < USB_MAX_DEVICE; i++) { > + struct usb_device *dev; > + > dev = usb_get_dev_index(i); /* get device */ > debug("i=%d\n", i); > - if (dev == NULL) > - break; /* no more devices available */ > - > - if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) { > - /* OK, it's a storage device. Iterate over its LUNs > - * and populate `usb_dev_desc'. > - */ > - int lun, max_lun, start = usb_max_devs; > - > - max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]); > - for (lun = 0; > - lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; > - lun++) { > - usb_dev_desc[usb_max_devs].lun = lun; > - if (usb_stor_get_info(dev, &usb_stor[start], > - &usb_dev_desc[usb_max_devs]) == 1) { > - usb_max_devs++; > - } > - } > - } > - /* if storage device */ > - if (usb_max_devs == USB_MAX_STOR_DEV) { > - printf("max USB Storage Device reached: %d stopping\n", > - usb_max_devs); > + if (usb_stor_probe_device(dev)) > break; > - } > } /* for */ > +#endif > > usb_disable_asynch(0); /* asynch transfer allowed */ > printf("%d Storage Device(s) found\n", usb_max_devs); > @@ -1046,7 +1094,7 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, > unsigned short smallblks; > struct usb_device *dev; > struct us_data *ss; > - int retry, i; > + int retry; > ccb *srb = &usb_ccb; > > if (blkcnt == 0) > @@ -1054,15 +1102,10 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, > > device &= 0xff; > /* Setup device */ > - debug("\nusb_read: dev %d \n", device); > - dev = NULL; > - for (i = 0; i < USB_MAX_DEVICE; i++) { > - dev = usb_get_dev_index(i); > - if (dev == NULL) > - return 0; > - if (dev->devnum == usb_dev_desc[device].target) > - break; > - } > + debug("\nusb_read: dev %d\n", device); > + dev = usb_dev_desc[device].priv; > + if (!dev) > + return 0; > ss = (struct us_data *)dev->privptr; > > usb_disable_asynch(1); /* asynch transfer not allowed */ > @@ -1119,7 +1162,7 @@ unsigned long usb_stor_write(int device, lbaint_t blknr, > unsigned short smallblks; > struct usb_device *dev; > struct us_data *ss; > - int retry, i; > + int retry; > ccb *srb = &usb_ccb; > > if (blkcnt == 0) > @@ -1127,15 +1170,10 @@ unsigned long usb_stor_write(int device, lbaint_t blknr, > > device &= 0xff; > /* Setup device */ > - debug("\nusb_write: dev %d \n", device); > - dev = NULL; > - for (i = 0; i < USB_MAX_DEVICE; i++) { > - dev = usb_get_dev_index(i); > - if (dev == NULL) > - return 0; > - if (dev->devnum == usb_dev_desc[device].target) > - break; > - } > + debug("\nusb_write: dev %d\n", device); > + dev = usb_dev_desc[device].priv; > + if (!dev) > + return 0; > ss = (struct us_data *)dev->privptr; > > usb_disable_asynch(1); /* asynch transfer not allowed */ > diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c > index 7cb96e3..4334d16 100644 > --- a/drivers/usb/eth/usb_ether.c > +++ b/drivers/usb/eth/usb_ether.c > @@ -5,7 +5,9 @@ > */ > > #include <common.h> > +#include <dm.h> > #include <usb.h> > +#include <dm/device-internal.h> > > #include "usb_ether.h" > > @@ -118,8 +120,6 @@ static void probe_valid_drivers(struct usb_device *dev) > int usb_host_eth_scan(int mode) > { > int i, old_async; > - struct usb_device *dev; > - > > if (mode == 1) > printf(" scanning usb for ethernet devices... "); > @@ -138,7 +138,38 @@ int usb_host_eth_scan(int mode) > } > > usb_max_eth_dev = 0; > +#ifdef CONFIG_DM_USB > + struct udevice *bus; > + struct uclass *uc; > + int ret; > + > + ret = uclass_get(UCLASS_USB, &uc); > + if (ret) > + return ret; > + uclass_foreach_dev(bus, uc) { > + for (i = 0; i < USB_MAX_DEVICE; i++) { > + struct usb_device *dev; > + > + dev = usb_get_dev_index(bus, i); /* get device */ > + debug("i=%d\n", i); > + if (dev == NULL) > + break; /* no more devices available */ > + > + /* > + * find valid usb_ether driver for this device, > + * if any > + */ > + probe_valid_drivers(dev); > + > + /* check limit */ > + if (usb_max_eth_dev == USB_MAX_ETH_DEV) > + break; > + } /* for */ > + } > +#else > for (i = 0; i < USB_MAX_DEVICE; i++) { > + struct usb_device *dev; > + > dev = usb_get_dev_index(i); /* get device */ > debug("i=%d\n", i); > if (dev == NULL) > @@ -148,13 +179,14 @@ int usb_host_eth_scan(int mode) > probe_valid_drivers(dev); > > /* check limit */ > - if (usb_max_eth_dev == USB_MAX_ETH_DEV) { > - printf("max USB Ethernet Device reached: %d stopping\n", > - usb_max_eth_dev); > + if (usb_max_eth_dev == USB_MAX_ETH_DEV) > break; > - } > } /* for */ > - > +#endif > + if (usb_max_eth_dev == USB_MAX_ETH_DEV) { > + printf("max USB Ethernet Device reached: %d stopping\n", > + usb_max_eth_dev); > + } > usb_disable_asynch(old_async); /* restore asynch value */ > printf("%d Ethernet Device(s) found\n", usb_max_eth_dev); > if (usb_max_eth_dev > 0) > diff --git a/include/usb.h b/include/usb.h > index a8fee0b..ba80eb8 100644 > --- a/include/usb.h > +++ b/include/usb.h > @@ -9,6 +9,7 @@ > #ifndef _USB_H_ > #define _USB_H_ > > +#include <fdtdec.h> > #include <usb_defs.h> > #include <linux/usb/ch9.h> > #include <asm/cache.h> > @@ -130,6 +131,10 @@ struct usb_device { > void *controller; /* hardware controller private data */ > /* slot_id - for xHCI enabled devices */ > unsigned int slot_id; > +#ifdef CONFIG_DM_USB > + char **strings; > + struct udevice *controller_dev; > +#endif > }; > > struct int_queue; > @@ -245,7 +250,6 @@ int usb_stop(void); /* stop the USB Controller */ > int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); > int usb_set_idle(struct usb_device *dev, int ifnum, int duration, > int report_id); > -struct usb_device *usb_get_dev_index(int index); > int usb_control_msg(struct usb_device *dev, unsigned int pipe, > unsigned char request, unsigned char requesttype, > unsigned short value, unsigned short index, > @@ -423,15 +427,79 @@ struct usb_hub_device { > struct usb_hub_descriptor desc; > }; > > +#ifdef CONFIG_DM_USB > + > +/* This is attached to each controller */ > +struct dm_usb_info { > + struct usb_device usb_dev[USB_MAX_DEVICE]; > + int dev_index; > + struct udevice *dev; > + void *controller; /* struct xhci_ctrl, etc. */ > +}; > + > +struct dm_usb_ops { > + int (*hcd_init)(struct udevice *dev, fdt_addr_t *hccrp, > + fdt_addr_t *hcorp); > + int (*control)(struct udevice *dev, struct usb_device *udev, > + unsigned long pipe, void *buffer, int length, > + struct devrequest *setup); > + int (*bulk)(struct udevice *dev, struct usb_device *udev, > + unsigned long pipe, void *buffer, int length); > + int (*interrupt)(struct udevice *dev, struct usb_device *udev, > + unsigned long pipe, void *buffer, int length, > + interval); data type required for "interval". It gives build error. > + int (*alloc_device)(struct udevice *dev, struct usb_device *udev); > +}; > + > +#define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops) > +#define usb_get_emul_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops) > + > +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, > + int length, int interval); > + > +int submit_control_msg(struct usb_device *dev, unsigned long pipe, > + void *buffer, int length, struct devrequest *setup); > + > +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, > + int length); > + > +#ifdef CONFIG_MUSB_HOST > +int usb_reset_root_port(void); > +#endif > + > +void usb_free_device(struct udevice *controller); > +/** > + * usb_alloc_new_device() - Allocate a new device > + * > + * @devp: returns a pointer of a new device structure > + * @return 0 if OK, -ENOSPC if we have found out of room for new devices > + */ > +int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp); > + > +struct usb_device *usb_get_dev_index(struct udevice *controller, int index); > + > +#else > + > +void usb_free_device(void *controller); > +/** > + * usb_alloc_new_device() - Allocate a new device > + * > + * @devp: returns a pointer of a new device structure > + * @return 0 if OK, -ENOSPC if we have found out of room for new devices > + */ > +int usb_alloc_new_device(void *controller, struct usb_device **devp); > + > +struct usb_device *usb_get_dev_index(int index); > + > +#endif > + > int usb_hub_probe(struct usb_device *dev, int ifnum); > 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); > - > int usb_new_device(struct usb_device *dev); > -void usb_free_device(void); > + > int usb_alloc_device(struct usb_device *dev); > > #endif /*_USB_H_ */ > -- > 2.2.0.rc0.207.ga3a616c > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot
diff --git a/common/cmd_usb.c b/common/cmd_usb.c index 27813f0..b824634 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -10,6 +10,7 @@ #include <common.h> #include <command.h> +#include <dm.h> #include <asm/byteorder.h> #include <asm/unaligned.h> #include <part.h> @@ -254,16 +255,24 @@ static void usb_display_config(struct usb_device *dev) static struct usb_device *usb_find_device(int devnum) { - struct usb_device *dev; +#ifdef CONFIG_DM_USB + struct udevice *dev; + + if (uclass_get_device_by_seq(UCLASS_USB, devnum, &dev)) + return NULL; + return dev_get_uclass_priv(dev); +#else + struct usb_device *udev; int d; for (d = 0; d < USB_MAX_DEVICE; d++) { - dev = usb_get_dev_index(d); - if (dev == NULL) + udev = usb_get_dev_index(d); + if (udev == NULL) return NULL; - if (dev->devnum == devnum) - return dev; + if (udev->devnum == devnum) + return udev; } +#endif return NULL; } @@ -466,9 +475,8 @@ static void do_usb_start(void) */ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - + struct usb_device *udev = NULL; int i; - struct usb_device *dev = NULL; extern char usb_started; #ifdef CONFIG_USB_STORAGE block_dev_desc_t *stor_dev; @@ -508,36 +516,64 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } if (strncmp(argv[1], "tree", 4) == 0) { puts("USB device tree:\n"); +#ifdef CONFIG_DM_USB + struct udevice *dev; + + for (uclass_first_device(UCLASS_USB, &dev); + dev; + uclass_next_device(&dev)) { + struct usb_device *udev = dev_get_uclass_priv(dev); + + usb_show_tree(udev); + } +#else for (i = 0; i < USB_MAX_DEVICE; i++) { + struct usb_device *dev; + dev = usb_get_dev_index(i); if (dev == NULL) break; if (dev->parent == NULL) usb_show_tree(dev); } +#endif return 0; } if (strncmp(argv[1], "inf", 3) == 0) { - int d; if (argc == 2) { +#ifdef CONFIG_DM_USB + struct udevice *dev; + + for (uclass_first_device(UCLASS_USB, &dev); + dev; + uclass_next_device(&dev)) { + struct usb_device *udev; + + udev = dev_get_uclass_priv(dev); + usb_display_desc(udev); + usb_display_config(udev); + } +#else + int d; for (d = 0; d < USB_MAX_DEVICE; d++) { - dev = usb_get_dev_index(d); - if (dev == NULL) + udev = usb_get_dev_index(d); + if (udev == NULL) break; - usb_display_desc(dev); - usb_display_config(dev); + usb_display_desc(udev); + usb_display_config(udev); } +#endif return 0; } else { i = simple_strtoul(argv[2], NULL, 10); printf("config for device %d\n", i); - dev = usb_find_device(i); - if (dev == NULL) { + udev = usb_find_device(i); + if (udev == NULL) { printf("*** No device available ***\n"); return 0; } else { - usb_display_desc(dev); - usb_display_config(dev); + usb_display_desc(udev); + usb_display_config(udev); } } return 0; @@ -546,13 +582,13 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc < 5) return CMD_RET_USAGE; i = simple_strtoul(argv[2], NULL, 10); - dev = usb_find_device(i); - if (dev == NULL) { + udev = usb_find_device(i); + if (udev == NULL) { printf("Device %d does not exist.\n", i); return 1; } i = simple_strtoul(argv[3], NULL, 10); - return usb_test(dev, i, argv[4]); + return usb_test(udev, i, argv[4]); } #ifdef CONFIG_USB_STORAGE if (strncmp(argv[1], "stor", 4) == 0) diff --git a/common/usb.c b/common/usb.c index 32e15cd..3ccf8a7 100644 --- a/common/usb.c +++ b/common/usb.c @@ -41,12 +41,13 @@ #define USB_BUFSIZ 512 -static struct usb_device usb_dev[USB_MAX_DEVICE]; -static int dev_index; static int asynch_allowed; - char usb_started; /* flag for the started/stopped USB status */ +#ifndef CONFIG_DM_USB +static struct usb_device usb_dev[USB_MAX_DEVICE]; +static int dev_index; + #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif @@ -94,12 +95,12 @@ int usb_init(void) controllers_initialized++; start_index = dev_index; printf("scanning bus %d for devices... ", i); - dev = usb_alloc_new_device(ctrl); + ret = usb_alloc_new_device(ctrl, &dev); /* * device 0 is always present * (root hub, so let it analyze) */ - if (dev) + if (!ret) usb_new_device(dev); if (start_index == dev_index) @@ -152,6 +153,7 @@ int usb_disable_asynch(int disable) asynch_allowed = !disable; return old_value; } +#endif /* !CONFIG_DM_USB */ /*------------------------------------------------------------------- @@ -815,6 +817,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) * the USB device are static allocated [USB_MAX_DEVICE]. */ +#ifndef CONFIG_DM_USB /* returns a pointer to the device with the index [index]. * if the device is not assigned (dev->devnum==-1) returns NULL @@ -827,16 +830,13 @@ struct usb_device *usb_get_dev_index(int index) return &usb_dev[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) +int usb_alloc_new_device(void *controller, struct usb_device **devp) { int i; debug("New Device %d\n", dev_index); if (dev_index == USB_MAX_DEVICE) { printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE); - return NULL; + return -ENOSPC; } /* default Address is 0, real addresses start with 1 */ usb_dev[dev_index].devnum = dev_index + 1; @@ -846,7 +846,9 @@ struct usb_device *usb_alloc_new_device(void *controller) usb_dev[dev_index].parent = NULL; usb_dev[dev_index].controller = controller; dev_index++; - return &usb_dev[dev_index - 1]; + *devp = &usb_dev[dev_index - 1]; + + return 0; } /* @@ -854,7 +856,7 @@ struct usb_device *usb_alloc_new_device(void *controller) * Called in error cases where configuring a newly attached * device fails for some reason. */ -void usb_free_device(void) +void usb_free_device(void *controller) { dev_index--; debug("Freeing device node: %d\n", dev_index); @@ -872,6 +874,8 @@ __weak int usb_alloc_device(struct usb_device *udev) { return 0; } +#endif /* !CONFIG_DM_USB */ + /* * By the time we get here, the device has gotten a new device ID * and is in the default state. We need to identify the thing and diff --git a/common/usb_hub.c b/common/usb_hub.c index 66b4a72..ccdf755 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -211,6 +211,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) struct usb_device *usb; ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); unsigned short portstatus; + int ret; /* Check status */ if (usb_get_port_status(dev, port + 1, portsts) < 0) { @@ -246,7 +247,15 @@ 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); +#ifdef CONFIG_DM_USB + ret = usb_alloc_new_device(dev->controller_dev, &usb); +#else + ret = usb_alloc_new_device(dev->controller, &usb); +#endif + if (ret) { + printf("cannot create new device: reg=%d", ret); + return; + } switch (portstatus & USB_PORT_STAT_SPEED_MASK) { case USB_PORT_STAT_SUPER_SPEED: @@ -269,7 +278,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) /* Run it through the hoops (find a driver, etc) */ if (usb_new_device(usb)) { /* Woops, disable the port */ - usb_free_device(); + usb_free_device(dev->controller); dev->children[port] = NULL; debug("hub: disabling port %d\n", port + 1); usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE); diff --git a/common/usb_storage.c b/common/usb_storage.c index 1411737..8fb2c18 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -33,9 +33,12 @@ #include <common.h> #include <command.h> +#include <dm.h> +#include <errno.h> #include <inttypes.h> #include <asm/byteorder.h> #include <asm/processor.h> +#include <dm/device-internal.h> #include <part.h> #include <usb.h> @@ -158,7 +161,6 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer); unsigned long usb_stor_write(int device, lbaint_t blknr, lbaint_t blkcnt, const void *buffer); -struct usb_device * usb_get_dev_index(int index); void uhci_show_temp_int_td(void); #ifdef CONFIG_PARTITIONS @@ -208,6 +210,44 @@ static unsigned int usb_get_max_lun(struct us_data *us) return (len > 0) ? *result : 0; } +static int usb_stor_probe_device(struct usb_device *dev) +{ + if (dev == NULL) + return -ENOENT; /* no more devices available */ + + if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) { + /* OK, it's a storage device. Iterate over its LUNs + * and populate `usb_dev_desc'. + */ + int lun, max_lun, start = usb_max_devs; + + max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]); + for (lun = 0; + lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; + lun++) { + struct block_dev_desc *blkdev; + + blkdev = &usb_dev_desc[usb_max_devs]; + + if (usb_stor_get_info(dev, &usb_stor[start], + &usb_dev_desc[usb_max_devs]) == + 1) { + blkdev->lun = lun; + blkdev->priv = dev; + usb_max_devs++; + } + } + } + + /* if storage device */ + if (usb_max_devs == USB_MAX_STOR_DEV) { + printf("max USB Storage Device reached: %d stopping\n", + usb_max_devs); + return -ENOSPC; + } + + return 0; +} /******************************************************************************* * scan the usb and reports device info * to the user if mode = 1 @@ -215,8 +255,8 @@ static unsigned int usb_get_max_lun(struct us_data *us) */ int usb_stor_scan(int mode) { + struct block_dev_desc *blkdev; unsigned char i; - struct usb_device *dev; if (mode == 1) printf(" scanning usb for storage devices... "); @@ -224,47 +264,55 @@ int usb_stor_scan(int mode) usb_disable_asynch(1); /* asynch transfer not allowed */ for (i = 0; i < USB_MAX_STOR_DEV; i++) { - memset(&usb_dev_desc[i], 0, sizeof(block_dev_desc_t)); - usb_dev_desc[i].if_type = IF_TYPE_USB; - usb_dev_desc[i].dev = i; - usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - usb_dev_desc[i].target = 0xff; - usb_dev_desc[i].type = DEV_TYPE_UNKNOWN; - usb_dev_desc[i].block_read = usb_stor_read; - usb_dev_desc[i].block_write = usb_stor_write; + blkdev = &usb_dev_desc[i]; + memset(&blkdev, 0, sizeof(block_dev_desc_t)); + blkdev->if_type = IF_TYPE_USB; + blkdev->dev = i; + blkdev->part_type = PART_TYPE_UNKNOWN; + blkdev->target = 0xff; + blkdev->type = DEV_TYPE_UNKNOWN; + blkdev->block_read = usb_stor_read; + blkdev->block_write = usb_stor_write; } usb_max_devs = 0; +#ifdef CONFIG_DM_USB + struct udevice *bus; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_USB, &uc); + if (ret) + return ret; + uclass_foreach_dev(bus, uc) { + struct udevice *dev; + + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + ret = device_probe(dev); + if (!ret) { + struct usb_device *udev; + + udev = dev_get_parentdata(dev); + ret = usb_stor_probe_device(udev); + } + if (ret) { + printf("Device '%s' probe failed: %d\n", + dev->name, ret); + } + } + } +#else for (i = 0; i < USB_MAX_DEVICE; i++) { + struct usb_device *dev; + dev = usb_get_dev_index(i); /* get device */ debug("i=%d\n", i); - if (dev == NULL) - break; /* no more devices available */ - - if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) { - /* OK, it's a storage device. Iterate over its LUNs - * and populate `usb_dev_desc'. - */ - int lun, max_lun, start = usb_max_devs; - - max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]); - for (lun = 0; - lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV; - lun++) { - usb_dev_desc[usb_max_devs].lun = lun; - if (usb_stor_get_info(dev, &usb_stor[start], - &usb_dev_desc[usb_max_devs]) == 1) { - usb_max_devs++; - } - } - } - /* if storage device */ - if (usb_max_devs == USB_MAX_STOR_DEV) { - printf("max USB Storage Device reached: %d stopping\n", - usb_max_devs); + if (usb_stor_probe_device(dev)) break; - } } /* for */ +#endif usb_disable_asynch(0); /* asynch transfer allowed */ printf("%d Storage Device(s) found\n", usb_max_devs); @@ -1046,7 +1094,7 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, unsigned short smallblks; struct usb_device *dev; struct us_data *ss; - int retry, i; + int retry; ccb *srb = &usb_ccb; if (blkcnt == 0) @@ -1054,15 +1102,10 @@ unsigned long usb_stor_read(int device, lbaint_t blknr, device &= 0xff; /* Setup device */ - debug("\nusb_read: dev %d \n", device); - dev = NULL; - for (i = 0; i < USB_MAX_DEVICE; i++) { - dev = usb_get_dev_index(i); - if (dev == NULL) - return 0; - if (dev->devnum == usb_dev_desc[device].target) - break; - } + debug("\nusb_read: dev %d\n", device); + dev = usb_dev_desc[device].priv; + if (!dev) + return 0; ss = (struct us_data *)dev->privptr; usb_disable_asynch(1); /* asynch transfer not allowed */ @@ -1119,7 +1162,7 @@ unsigned long usb_stor_write(int device, lbaint_t blknr, unsigned short smallblks; struct usb_device *dev; struct us_data *ss; - int retry, i; + int retry; ccb *srb = &usb_ccb; if (blkcnt == 0) @@ -1127,15 +1170,10 @@ unsigned long usb_stor_write(int device, lbaint_t blknr, device &= 0xff; /* Setup device */ - debug("\nusb_write: dev %d \n", device); - dev = NULL; - for (i = 0; i < USB_MAX_DEVICE; i++) { - dev = usb_get_dev_index(i); - if (dev == NULL) - return 0; - if (dev->devnum == usb_dev_desc[device].target) - break; - } + debug("\nusb_write: dev %d\n", device); + dev = usb_dev_desc[device].priv; + if (!dev) + return 0; ss = (struct us_data *)dev->privptr; usb_disable_asynch(1); /* asynch transfer not allowed */ diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c index 7cb96e3..4334d16 100644 --- a/drivers/usb/eth/usb_ether.c +++ b/drivers/usb/eth/usb_ether.c @@ -5,7 +5,9 @@ */ #include <common.h> +#include <dm.h> #include <usb.h> +#include <dm/device-internal.h> #include "usb_ether.h" @@ -118,8 +120,6 @@ static void probe_valid_drivers(struct usb_device *dev) int usb_host_eth_scan(int mode) { int i, old_async; - struct usb_device *dev; - if (mode == 1) printf(" scanning usb for ethernet devices... "); @@ -138,7 +138,38 @@ int usb_host_eth_scan(int mode) } usb_max_eth_dev = 0; +#ifdef CONFIG_DM_USB + struct udevice *bus; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_USB, &uc); + if (ret) + return ret; + uclass_foreach_dev(bus, uc) { + for (i = 0; i < USB_MAX_DEVICE; i++) { + struct usb_device *dev; + + dev = usb_get_dev_index(bus, i); /* get device */ + debug("i=%d\n", i); + if (dev == NULL) + break; /* no more devices available */ + + /* + * find valid usb_ether driver for this device, + * if any + */ + probe_valid_drivers(dev); + + /* check limit */ + if (usb_max_eth_dev == USB_MAX_ETH_DEV) + break; + } /* for */ + } +#else for (i = 0; i < USB_MAX_DEVICE; i++) { + struct usb_device *dev; + dev = usb_get_dev_index(i); /* get device */ debug("i=%d\n", i); if (dev == NULL) @@ -148,13 +179,14 @@ int usb_host_eth_scan(int mode) probe_valid_drivers(dev); /* check limit */ - if (usb_max_eth_dev == USB_MAX_ETH_DEV) { - printf("max USB Ethernet Device reached: %d stopping\n", - usb_max_eth_dev); + if (usb_max_eth_dev == USB_MAX_ETH_DEV) break; - } } /* for */ - +#endif + if (usb_max_eth_dev == USB_MAX_ETH_DEV) { + printf("max USB Ethernet Device reached: %d stopping\n", + usb_max_eth_dev); + } usb_disable_asynch(old_async); /* restore asynch value */ printf("%d Ethernet Device(s) found\n", usb_max_eth_dev); if (usb_max_eth_dev > 0) diff --git a/include/usb.h b/include/usb.h index a8fee0b..ba80eb8 100644 --- a/include/usb.h +++ b/include/usb.h @@ -9,6 +9,7 @@ #ifndef _USB_H_ #define _USB_H_ +#include <fdtdec.h> #include <usb_defs.h> #include <linux/usb/ch9.h> #include <asm/cache.h> @@ -130,6 +131,10 @@ struct usb_device { void *controller; /* hardware controller private data */ /* slot_id - for xHCI enabled devices */ unsigned int slot_id; +#ifdef CONFIG_DM_USB + char **strings; + struct udevice *controller_dev; +#endif }; struct int_queue; @@ -245,7 +250,6 @@ int usb_stop(void); /* stop the USB Controller */ int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id); -struct usb_device *usb_get_dev_index(int index); int usb_control_msg(struct usb_device *dev, unsigned int pipe, unsigned char request, unsigned char requesttype, unsigned short value, unsigned short index, @@ -423,15 +427,79 @@ struct usb_hub_device { struct usb_hub_descriptor desc; }; +#ifdef CONFIG_DM_USB + +/* This is attached to each controller */ +struct dm_usb_info { + struct usb_device usb_dev[USB_MAX_DEVICE]; + int dev_index; + struct udevice *dev; + void *controller; /* struct xhci_ctrl, etc. */ +}; + +struct dm_usb_ops { + int (*hcd_init)(struct udevice *dev, fdt_addr_t *hccrp, + fdt_addr_t *hcorp); + int (*control)(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length, + struct devrequest *setup); + int (*bulk)(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length); + int (*interrupt)(struct udevice *dev, struct usb_device *udev, + unsigned long pipe, void *buffer, int length, + interval); + int (*alloc_device)(struct udevice *dev, struct usb_device *udev); +}; + +#define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops) +#define usb_get_emul_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops) + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int length, int interval); + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int length, struct devrequest *setup); + +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int length); + +#ifdef CONFIG_MUSB_HOST +int usb_reset_root_port(void); +#endif + +void usb_free_device(struct udevice *controller); +/** + * usb_alloc_new_device() - Allocate a new device + * + * @devp: returns a pointer of a new device structure + * @return 0 if OK, -ENOSPC if we have found out of room for new devices + */ +int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp); + +struct usb_device *usb_get_dev_index(struct udevice *controller, int index); + +#else + +void usb_free_device(void *controller); +/** + * usb_alloc_new_device() - Allocate a new device + * + * @devp: returns a pointer of a new device structure + * @return 0 if OK, -ENOSPC if we have found out of room for new devices + */ +int usb_alloc_new_device(void *controller, struct usb_device **devp); + +struct usb_device *usb_get_dev_index(int index); + +#endif + int usb_hub_probe(struct usb_device *dev, int ifnum); 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); - int usb_new_device(struct usb_device *dev); -void usb_free_device(void); + int usb_alloc_device(struct usb_device *dev); #endif /*_USB_H_ */
While we currently don't have driver model support for block devices and Ethernet, we can still allow this to work when driver model is used for USB. Signed-off-by: Simon Glass <sjg@chromium.org> --- common/cmd_usb.c | 74 ++++++++++++++++------ common/usb.c | 28 +++++---- common/usb_hub.c | 13 +++- common/usb_storage.c | 148 ++++++++++++++++++++++++++++---------------- drivers/usb/eth/usb_ether.c | 46 +++++++++++--- include/usb.h | 76 +++++++++++++++++++++-- 6 files changed, 286 insertions(+), 99 deletions(-)