dm: usb: Convert USB storage to use driver-model for block devs
authorSimon Glass <sjg@chromium.org>
Mon, 29 Feb 2016 22:25:58 +0000 (15:25 -0700)
committerSimon Glass <sjg@chromium.org>
Mon, 14 Mar 2016 21:34:50 +0000 (15:34 -0600)
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 <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
Tested-by: Stephen Warren <swarren@nvidia.com>
common/usb_storage.c

index 0475123..1472824 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/byteorder.h>
 #include <asm/processor.h>
 #include <dm/device-internal.h>
+#include <dm/lists.h>
 
 #include <part.h>
 #include <usb.h>
@@ -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