summaryrefslogtreecommitdiff
path: root/disk
diff options
context:
space:
mode:
authorAKASHI Takahiro <takahiro.akashi@linaro.org>2022-04-19 10:05:09 +0900
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>2022-04-23 22:05:41 +0200
commit43855fdb2c99eae0cdc9b3c54c2d719262d3b3eb (patch)
tree02cc726f5c18ca426a77453e411660da5383e2eb /disk
parent8ff50227befdc778eb2cb239b778ed1ed843bf33 (diff)
dm: disk: add UCLASS_PARTITION
NOTE: probably we have to update config dependencies, in particular, SPL/TPL_PRINTF? With this new function, UCLASS_PARTITION devices will be created as child nodes of UCLASS_BLK device. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Diffstat (limited to 'disk')
-rw-r--r--disk/Makefile3
-rw-r--r--disk/disk-uclass.c153
2 files changed, 156 insertions, 0 deletions
diff --git a/disk/Makefile b/disk/Makefile
index 5ca10c5576..ec148832b3 100644
--- a/disk/Makefile
+++ b/disk/Makefile
@@ -6,6 +6,9 @@
#ccflags-y += -DET_DEBUG -DDEBUG
obj-$(CONFIG_$(SPL_TPL_)PARTITIONS) += part.o
+ifdef CONFIG_$(SPL_TPL_)BLK
+obj-$(CONFIG_$(SPL_TPL_)PARTITIONS) += disk-uclass.o
+endif
obj-$(CONFIG_$(SPL_TPL_)MAC_PARTITION) += part_mac.o
obj-$(CONFIG_$(SPL_TPL_)DOS_PARTITION) += part_dos.o
obj-$(CONFIG_$(SPL_TPL_)ISO_PARTITION) += part_iso.o
diff --git a/disk/disk-uclass.c b/disk/disk-uclass.c
new file mode 100644
index 0000000000..4918a2f72d
--- /dev/null
+++ b/disk/disk-uclass.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Software partition device (UCLASS_PARTITION)
+ *
+ * Copyright (c) 2021 Linaro Limited
+ * Author: AKASHI Takahiro
+ */
+
+#define LOG_CATEGORY UCLASS_PARTITION
+
+#include <blk.h>
+#include <dm.h>
+#include <log.h>
+#include <part.h>
+#include <vsprintf.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+int part_create_block_devices(struct udevice *blk_dev)
+{
+ int part, count;
+ struct blk_desc *desc = dev_get_uclass_plat(blk_dev);
+ struct disk_partition info;
+ struct disk_part *part_data;
+ char devname[32];
+ struct udevice *dev;
+ int ret;
+
+ if (!CONFIG_IS_ENABLED(PARTITIONS) ||
+ !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE))
+ return 0;
+
+ if (device_get_uclass_id(blk_dev) != UCLASS_BLK)
+ return 0;
+
+ /* Add devices for each partition */
+ for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
+ if (part_get_info(desc, part, &info))
+ continue;
+ snprintf(devname, sizeof(devname), "%s:%d", blk_dev->name,
+ part);
+
+ ret = device_bind_driver(blk_dev, "blk_partition",
+ strdup(devname), &dev);
+ if (ret)
+ return ret;
+
+ part_data = dev_get_uclass_plat(dev);
+ part_data->partnum = part;
+ part_data->gpt_part_info = info;
+ count++;
+
+ ret = device_probe(dev);
+ if (ret) {
+ debug("Can't probe\n");
+ count--;
+ device_unbind(dev);
+
+ continue;
+ }
+ }
+ debug("%s: %d partitions found in %s\n", __func__, count,
+ blk_dev->name);
+
+ return 0;
+}
+
+static ulong blk_part_read(struct udevice *dev, lbaint_t start,
+ lbaint_t blkcnt, void *buffer)
+{
+ struct udevice *parent;
+ struct disk_part *part;
+ const struct blk_ops *ops;
+
+ parent = dev_get_parent(dev);
+ ops = blk_get_ops(parent);
+ if (!ops->read)
+ return -ENOSYS;
+
+ part = dev_get_uclass_plat(dev);
+ if (start >= part->gpt_part_info.size)
+ return 0;
+
+ if ((start + blkcnt) > part->gpt_part_info.size)
+ blkcnt = part->gpt_part_info.size - start;
+ start += part->gpt_part_info.start;
+
+ return ops->read(parent, start, blkcnt, buffer);
+}
+
+static ulong blk_part_write(struct udevice *dev, lbaint_t start,
+ lbaint_t blkcnt, const void *buffer)
+{
+ struct udevice *parent;
+ struct disk_part *part;
+ const struct blk_ops *ops;
+
+ parent = dev_get_parent(dev);
+ ops = blk_get_ops(parent);
+ if (!ops->write)
+ return -ENOSYS;
+
+ part = dev_get_uclass_plat(dev);
+ if (start >= part->gpt_part_info.size)
+ return 0;
+
+ if ((start + blkcnt) > part->gpt_part_info.size)
+ blkcnt = part->gpt_part_info.size - start;
+ start += part->gpt_part_info.start;
+
+ return ops->write(parent, start, blkcnt, buffer);
+}
+
+static ulong blk_part_erase(struct udevice *dev, lbaint_t start,
+ lbaint_t blkcnt)
+{
+ struct udevice *parent;
+ struct disk_part *part;
+ const struct blk_ops *ops;
+
+ parent = dev_get_parent(dev);
+ ops = blk_get_ops(parent);
+ if (!ops->erase)
+ return -ENOSYS;
+
+ part = dev_get_uclass_plat(dev);
+ if (start >= part->gpt_part_info.size)
+ return 0;
+
+ if ((start + blkcnt) > part->gpt_part_info.size)
+ blkcnt = part->gpt_part_info.size - start;
+ start += part->gpt_part_info.start;
+
+ return ops->erase(parent, start, blkcnt);
+}
+
+static const struct blk_ops blk_part_ops = {
+ .read = blk_part_read,
+ .write = blk_part_write,
+ .erase = blk_part_erase,
+};
+
+U_BOOT_DRIVER(blk_partition) = {
+ .name = "blk_partition",
+ .id = UCLASS_PARTITION,
+ .ops = &blk_part_ops,
+};
+
+UCLASS_DRIVER(partition) = {
+ .id = UCLASS_PARTITION,
+ .per_device_plat_auto = sizeof(struct disk_part),
+ .name = "partition",
+};