From 07b2b78ce4bc8ae25e066c65245eaf58c0d9a67c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 29 Feb 2016 15:25:58 -0700 Subject: dm: usb: Convert USB storage to use driver-model for block devs Update this code to support CONFIG_BLK. Each USB storage device can have one or more block devices as children, each one representing a LUN (logical unit) of the USB device. Signed-off-by: Simon Glass Reviewed-by: Marek Vasut Tested-by: Stephen Warren --- common/usb_storage.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 6 deletions(-) (limited to 'common/usb_storage.c') diff --git a/common/usb_storage.c b/common/usb_storage.c index 0475123b18..14728242f0 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -67,7 +68,9 @@ static __u32 CBWTag; static int usb_max_devs; /* number of highest available usb device */ +#ifndef CONFIG_BLK static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV]; +#endif struct us_data; typedef int (*trans_cmnd)(ccb *cb, struct us_data *data); @@ -108,7 +111,9 @@ struct us_data { #define USB_MAX_XFER_BLK 20 #endif +#ifndef CONFIG_BLK static struct us_data usb_stor[USB_MAX_STOR_DEV]; +#endif #define USB_STOR_TRANSPORT_GOOD 0 #define USB_STOR_TRANSPORT_FAILED -1 @@ -118,16 +123,33 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *us, struct blk_desc *dev_desc); int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, struct us_data *ss); +#ifdef CONFIG_BLK +static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer); +static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer); +#else static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer); static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer); +#endif void uhci_show_temp_int_td(void); #ifdef CONFIG_PARTITIONS struct blk_desc *usb_stor_get_dev(int index) { +#ifdef CONFIG_BLK + struct udevice *dev; + int ret; + + ret = blk_get_device(IF_TYPE_USB, index, &dev); + if (ret) + return NULL; + return dev_get_uclass_platdata(dev); +#else return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL; +#endif } #endif @@ -143,6 +165,19 @@ static void usb_show_progress(void) int usb_stor_info(void) { int count = 0; +#ifdef CONFIG_BLK + struct udevice *dev; + + for (blk_first_device(IF_TYPE_USB, &dev); + dev; + blk_next_device(&dev)) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + printf(" Device %d: ", desc->devnum); + dev_print(desc); + count++; + } +#else int i; if (usb_max_devs > 0) { @@ -152,7 +187,7 @@ int usb_stor_info(void) } return 0; } - +#endif if (!count) { printf("No storage devices, perhaps not 'usb start'ed..?\n"); return 1; @@ -179,11 +214,63 @@ static unsigned int usb_get_max_lun(struct us_data *us) static int usb_stor_probe_device(struct usb_device *udev) { int lun, max_lun; + +#ifdef CONFIG_BLK + struct us_data *data; + char dev_name[30], *str; + int ret; +#else int start; if (udev == NULL) return -ENOENT; /* no more devices available */ +#endif + + debug("\n\nProbing for storage\n"); +#ifdef CONFIG_BLK + /* + * We store the us_data in the mass storage device's platdata. It + * is shared by all LUNs (block devices) attached to this mass storage + * device. + */ + data = dev_get_platdata(udev->dev); + if (!usb_storage_probe(udev, 0, data)) + return 0; + max_lun = usb_get_max_lun(data); + for (lun = 0; lun <= max_lun; lun++) { + struct blk_desc *blkdev; + struct udevice *dev; + + snprintf(dev_name, sizeof(dev_name), "%s.lun%d", + udev->dev->name, lun); + str = strdup(dev_name); + if (!str) + return -ENOMEM; + ret = blk_create_device(udev->dev, "usb_storage_blk", str, + IF_TYPE_USB, usb_max_devs, 512, 0, &dev); + if (ret) { + debug("Cannot bind driver\n"); + return ret; + } + + blkdev = dev_get_uclass_platdata(dev); + blkdev->target = 0xff; + blkdev->lun = lun; + ret = usb_stor_get_info(udev, data, blkdev); + if (ret == 1) + ret = blk_prepare_device(dev); + if (!ret) { + usb_max_devs++; + debug("%s: Found device %p\n", __func__, udev); + } else { + debug("usb_stor_get_info: Invalid device\n"); + ret = device_unbind(dev); + if (ret) + return ret; + } + } +#else /* We don't have space to even probe if we hit the maximum */ if (usb_max_devs == USB_MAX_STOR_DEV) { printf("max USB Storage Device reached: %d stopping\n", @@ -191,7 +278,6 @@ static int usb_stor_probe_device(struct usb_device *udev) return -ENOSPC; } - debug("\n\nProbing for storage\n"); if (!usb_storage_probe(udev, 0, &usb_stor[usb_max_devs])) return 0; @@ -220,10 +306,14 @@ static int usb_stor_probe_device(struct usb_device *udev) if (usb_stor_get_info(udev, &usb_stor[start], &usb_dev_desc[usb_max_devs]) == 1) { + debug("partype: %d\n", blkdev->part_type); + part_init(blkdev); + debug("partype: %d\n", blkdev->part_type); usb_max_devs++; debug("%s: Found device %p\n", __func__, udev); } } +#endif return 0; } @@ -1034,8 +1124,13 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor, } #endif /* CONFIG_USB_BIN_FIXUP */ +#ifdef CONFIG_BLK +static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +#else static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) +#endif { lbaint_t start, blks; uintptr_t buf_addr; @@ -1044,16 +1139,25 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, struct us_data *ss; int retry; ccb *srb = &usb_ccb; +#ifdef CONFIG_BLK + struct blk_desc *block_dev; +#endif if (blkcnt == 0) return 0; /* Setup device */ +#ifdef CONFIG_BLK + block_dev = dev_get_uclass_platdata(dev); + udev = dev_get_parent_priv(dev_get_parent(dev)); + debug("\nusb_read: udev %d\n", block_dev->devnum); +#else debug("\nusb_read: udev %d\n", block_dev->devnum); udev = usb_dev_desc[block_dev->devnum].priv; if (!udev) { debug("%s: No device\n", __func__); return 0; } +#endif ss = (struct us_data *)udev->privptr; usb_disable_asynch(1); /* asynch transfer not allowed */ @@ -1102,8 +1206,13 @@ retry_it: return blkcnt; } +#ifdef CONFIG_BLK +static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +#else static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) +#endif { lbaint_t start, blks; uintptr_t buf_addr; @@ -1112,17 +1221,26 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, struct us_data *ss; int retry; ccb *srb = &usb_ccb; +#ifdef CONFIG_BLK + struct blk_desc *block_dev; +#endif if (blkcnt == 0) return 0; /* Setup device */ +#ifdef CONFIG_BLK + block_dev = dev_get_uclass_platdata(dev); + udev = dev_get_parent_priv(dev_get_parent(dev)); + debug("\nusb_read: udev %d\n", block_dev->devnum); +#else debug("\nusb_read: udev %d\n", block_dev->devnum); udev = usb_dev_desc[block_dev->devnum].priv; if (!udev) { debug("%s: No device\n", __func__); return 0; } +#endif ss = (struct us_data *)udev->privptr; usb_disable_asynch(1); /* asynch transfer not allowed */ @@ -1377,11 +1495,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, dev_desc->log2blksz = LOG2(dev_desc->blksz); dev_desc->type = perq; debug(" address %d\n", dev_desc->target); - debug("partype: %d\n", dev_desc->part_type); - - part_init(dev_desc); - debug("partype: %d\n", dev_desc->part_type); return 1; } @@ -1409,6 +1523,9 @@ U_BOOT_DRIVER(usb_mass_storage) = { .id = UCLASS_MASS_STORAGE, .of_match = usb_mass_storage_ids, .probe = usb_mass_storage_probe, +#ifdef CONFIG_BLK + .platdata_auto_alloc_size = sizeof(struct us_data), +#endif }; UCLASS_DRIVER(usb_mass_storage) = { @@ -1425,5 +1542,17 @@ static const struct usb_device_id mass_storage_id_table[] = { }; U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table); +#endif +#ifdef CONFIG_BLK +static const struct blk_ops usb_storage_ops = { + .read = usb_stor_read, + .write = usb_stor_write, +}; + +U_BOOT_DRIVER(usb_storage_blk) = { + .name = "usb_storage_blk", + .id = UCLASS_BLK, + .ops = &usb_storage_ops, +}; #endif -- cgit v1.2.3