dm: disk: add read/write interfaces with udevice
authorAKASHI Takahiro <takahiro.akashi@linaro.org>
Tue, 19 Apr 2022 01:05:16 +0000 (10:05 +0900)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sat, 23 Apr 2022 20:05:41 +0000 (22:05 +0200)
In include/blk.h, Simon suggested:
===>
/*
 * These functions should take struct udevice instead of struct blk_desc,
 * but this is convenient for migration to driver model. Add a 'd' prefix
 * to the function operations, so that blk_read(), etc. can be reserved for
 * functions with the correct arguments.
 */
unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
                        lbaint_t blkcnt, void *buffer);
unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
                         lbaint_t blkcnt, const void *buffer);
unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
                         lbaint_t blkcnt);
<===

So new interfaces are provided with this patch.

They are expected to be used everywhere in U-Boot at the end.
The exceptions are block device drivers, partition drivers and efi_disk
which should know details of blk_desc structure.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
disk/disk-uclass.c
include/part.h

index 4918a2f..72ff62e 100644 (file)
@@ -146,6 +146,100 @@ U_BOOT_DRIVER(blk_partition) = {
        .ops            = &blk_part_ops,
 };
 
+/*
+ * BLOCK IO APIs
+ */
+static struct blk_desc *dev_get_blk(struct udevice *dev)
+{
+       struct blk_desc *block_dev;
+
+       switch (device_get_uclass_id(dev)) {
+       /*
+        * We won't support UCLASS_BLK with dev_* interfaces.
+        */
+       case UCLASS_PARTITION:
+               block_dev = dev_get_uclass_plat(dev_get_parent(dev));
+               break;
+       default:
+               block_dev = NULL;
+               break;
+       }
+
+       return block_dev;
+}
+
+unsigned long dev_read(struct udevice *dev, lbaint_t start,
+                      lbaint_t blkcnt, void *buffer)
+{
+       struct blk_desc *block_dev;
+       const struct blk_ops *ops;
+       struct disk_part *part;
+       lbaint_t start_in_disk;
+       ulong blks_read;
+
+       block_dev = dev_get_blk(dev);
+       if (!block_dev)
+               return -ENOSYS;
+
+       ops = blk_get_ops(dev);
+       if (!ops->read)
+               return -ENOSYS;
+
+       start_in_disk = start;
+       if (device_get_uclass_id(dev) == UCLASS_PARTITION) {
+               part = dev_get_uclass_plat(dev);
+               start_in_disk += part->gpt_part_info.start;
+       }
+
+       if (blkcache_read(block_dev->if_type, block_dev->devnum,
+                         start_in_disk, blkcnt, block_dev->blksz, buffer))
+               return blkcnt;
+       blks_read = ops->read(dev, start, blkcnt, buffer);
+       if (blks_read == blkcnt)
+               blkcache_fill(block_dev->if_type, block_dev->devnum,
+                             start_in_disk, blkcnt, block_dev->blksz, buffer);
+
+       return blks_read;
+}
+
+unsigned long dev_write(struct udevice *dev, lbaint_t start,
+                       lbaint_t blkcnt, const void *buffer)
+{
+       struct blk_desc *block_dev;
+       const struct blk_ops *ops;
+
+       block_dev = dev_get_blk(dev);
+       if (!block_dev)
+               return -ENOSYS;
+
+       ops = blk_get_ops(dev);
+       if (!ops->write)
+               return -ENOSYS;
+
+       blkcache_invalidate(block_dev->if_type, block_dev->devnum);
+
+       return ops->write(dev, start, blkcnt, buffer);
+}
+
+unsigned long dev_erase(struct udevice *dev, lbaint_t start,
+                       lbaint_t blkcnt)
+{
+       struct blk_desc *block_dev;
+       const struct blk_ops *ops;
+
+       block_dev = dev_get_blk(dev);
+       if (!block_dev)
+               return -ENOSYS;
+
+       ops = blk_get_ops(dev);
+       if (!ops->erase)
+               return -ENOSYS;
+
+       blkcache_invalidate(block_dev->if_type, block_dev->devnum);
+
+       return ops->erase(dev, start, blkcnt);
+}
+
 UCLASS_DRIVER(partition) = {
        .id             = UCLASS_PARTITION,
        .per_device_plat_auto   = sizeof(struct disk_part),
index a8db398..3a6958d 100644 (file)
@@ -313,6 +313,13 @@ struct udevice;
  */
 int part_create_block_devices(struct udevice *blk_dev);
 
+unsigned long dev_read(struct udevice *dev, lbaint_t start,
+                      lbaint_t blkcnt, void *buffer);
+unsigned long dev_write(struct udevice *dev, lbaint_t start,
+                       lbaint_t blkcnt, const void *buffer);
+unsigned long dev_erase(struct udevice *dev, lbaint_t start,
+                       lbaint_t blkcnt);
+
 /*
  * We don't support printing partition information in SPL and only support
  * getting partition information in a few cases.