drivers/mtd/nvmxip: introduce NVM XIP block storage emulation
add block storage emulation for NVM XIP flash devices
Some paltforms such as Corstone-1000 need to see NVM XIP raw flash
as a block storage device with read only capability.
Here NVM flash devices are devices with addressable
memory (e.g: QSPI NOR flash).
The implementation is generic and can be used by different platforms.
Two drivers are provided as follows.
nvmxip-blk :
a generic block driver allowing to read from the XIP flash
nvmxip Uclass driver :
When a device is described in the DT and associated with
UCLASS_NVMXIP, the Uclass creates a block device and binds it with
the nvmxip-blk.
Platforms can use multiple NVM XIP devices at the same time by defining a
DT node for each one of them.
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
diff --git a/drivers/mtd/nvmxip/nvmxip-uclass.c b/drivers/mtd/nvmxip/nvmxip-uclass.c
new file mode 100644
index 0000000..9f96041
--- /dev/null
+++ b/drivers/mtd/nvmxip/nvmxip-uclass.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <linux/bitops.h>
+#include "nvmxip.h"
+
+/* LBA Macros */
+
+#define DEFAULT_LBA_SHIFT 10 /* 1024 bytes per block */
+#define DEFAULT_LBA_COUNT 1024 /* block count */
+
+#define DEFAULT_LBA_SZ BIT(DEFAULT_LBA_SHIFT)
+
+/**
+ * nvmxip_post_bind() - post binding treatments
+ * @dev: the NVMXIP device
+ *
+ * Create and probe a child block device.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int nvmxip_post_bind(struct udevice *udev)
+{
+ int ret;
+ struct udevice *bdev = NULL;
+ char bdev_name[NVMXIP_BLKDEV_NAME_SZ + 1];
+ int devnum;
+
+ devnum = uclass_id_count(UCLASS_NVMXIP);
+ snprintf(bdev_name, NVMXIP_BLKDEV_NAME_SZ, "blk#%d", devnum);
+
+ ret = blk_create_devicef(udev, NVMXIP_BLKDRV_NAME, bdev_name, UCLASS_NVMXIP,
+ devnum, DEFAULT_LBA_SZ,
+ DEFAULT_LBA_COUNT, &bdev);
+ if (ret) {
+ log_err("[%s]: failure during creation of the block device %s, error %d\n",
+ udev->name, bdev_name, ret);
+ return ret;
+ }
+
+ ret = blk_probe_or_unbind(bdev);
+ if (ret) {
+ log_err("[%s]: failure during probing the block device %s, error %d\n",
+ udev->name, bdev_name, ret);
+ return ret;
+ }
+
+ log_info("[%s]: the block device %s ready for use\n", udev->name, bdev_name);
+
+ return 0;
+}
+
+UCLASS_DRIVER(nvmxip) = {
+ .name = "nvmxip",
+ .id = UCLASS_NVMXIP,
+ .post_bind = nvmxip_post_bind,
+};