diff options
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | doc/develop/driver-model/nvmxip.rst | 45 | ||||
-rw-r--r-- | doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt | 56 | ||||
-rw-r--r-- | drivers/mtd/nvmxip/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mtd/nvmxip/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nvmxip/nvmxip_qspi.c | 70 |
6 files changed, 178 insertions, 1 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index fe87b39939f..fd155ca8788 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1208,6 +1208,7 @@ NVMXIP M: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> S: Maintained F: doc/develop/driver-model/nvmxip.rst +F: doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt F: drivers/mtd/nvmxip/ NVMEM diff --git a/doc/develop/driver-model/nvmxip.rst b/doc/develop/driver-model/nvmxip.rst index fe087b13d22..09afdbcccf5 100644 --- a/doc/develop/driver-model/nvmxip.rst +++ b/doc/develop/driver-model/nvmxip.rst @@ -25,7 +25,33 @@ The NVMXIP Uclass provides the following drivers: the Uclass creates a block device and binds it with the nvmxip-blk. The Uclass driver implemented by drivers/mtd/nvmxip/nvmxip-uclass.c - The implementation is generic and can be used by different platforms. + nvmxip_qspi driver : + + The driver probed with the DT and is the parent of the blk#<id> device. + nvmxip_qspi can be reused by other platforms. If the platform + has custom settings to apply before using the flash, then the platform + can provide its own parent driver belonging to UCLASS_NVMXIP and reuse + nvmxip-blk. The custom driver can be implemented like nvmxip_qspi in + addition to the platform custom settings. + The nvmxip_qspi driver belongs to UCLASS_NVMXIP. + The driver implemented by drivers/mtd/nvmxip/nvmxip_qspi.c + + For example, if we have two NVMXIP devices described in the DT + The devices hierarchy is as follows: + +:: + + => dm tree + + Class Index Probed Driver Name + ----------------------------------------------------------- + ... + nvmxip 0 [ + ] nvmxip_qspi |-- nvmxip-qspi1@08000000 + blk 3 [ + ] nvmxip-blk | `-- nvmxip-qspi1@08000000.blk#1 + nvmxip 1 [ + ] nvmxip_qspi |-- nvmxip-qspi2@08200000 + blk 4 [ + ] nvmxip-blk | `-- nvmxip-qspi2@08200000.blk#2 + +The implementation is generic and can be used by different platforms. Supported hardware -------------------------------- @@ -43,6 +69,23 @@ config NVMXIP handles the read operation. This driver is HW agnostic and can support multiple flash devices at the same time. +config NVMXIP_QSPI + This option allows the emulation of a block storage device on top of a QSPI XIP flash. + Any platform that needs to emulate one or multiple QSPI XIP flash devices can turn this + option on to enable the functionality. NVMXIP config is selected automatically. + Platforms that need to add custom treatments before accessing to the flash, can + write their own driver (same as nvmxip_qspi in addition to the custom settings). + +Device Tree nodes +-------------------- + +Multiple QSPI XIP flash devices can be used at the same time by describing them through DT +nodes. + +Please refer to the documentation of the DT binding at: + +doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt + Contributors ------------ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> diff --git a/doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt b/doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt new file mode 100644 index 00000000000..cc60e9efdcd --- /dev/null +++ b/doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt @@ -0,0 +1,56 @@ +Specifying NVMXIP information for devices +====================================== + +QSPI XIP flash device nodes +--------------------------- + +Each flash device should have its own node. + +Each node must specify the following fields: + +1) + compatible = "nvmxip,qspi"; + +This allows to bind the flash device with the nvmxip_qspi driver +If a platform has its own driver, please provide your own compatible +string. + +2) + reg = <0x0 0x08000000 0x0 0x00200000>; + +The start address and size of the flash device. The values give here are an +example (when the cell size is 2). + +When cell size is 1, the reg field looks like this: + + reg = <0x08000000 0x00200000>; + +3) + + lba_shift = <9>; + +The number of bit shifts used to calculate the size in bytes of one block. +In this example the block size is 1 << 9 = 2 ^ 9 = 512 bytes + +4) + + lba = <4096>; + +The number of blocks. + +Example of multiple flash devices +---------------------------------------------------- + + nvmxip-qspi1@08000000 { + compatible = "nvmxip,qspi"; + reg = <0x0 0x08000000 0x0 0x00200000>; + lba_shift = <9>; + lba = <4096>; + }; + + nvmxip-qspi2@08200000 { + compatible = "nvmxip,qspi"; + reg = <0x0 0x08200000 0x0 0x00100000>; + lba_shift = <9>; + lba = <2048>; + }; diff --git a/drivers/mtd/nvmxip/Kconfig b/drivers/mtd/nvmxip/Kconfig index ef53fc3c790..3ef71050264 100644 --- a/drivers/mtd/nvmxip/Kconfig +++ b/drivers/mtd/nvmxip/Kconfig @@ -11,3 +11,9 @@ config NVMXIP This option allows the emulation of a block storage device on top of a direct access non volatile memory XIP flash devices. This support provides the read operation. + +config NVMXIP_QSPI + bool "QSPI XIP support" + select NVMXIP + help + This option allows the emulation of a block storage device on top of a QSPI XIP flash diff --git a/drivers/mtd/nvmxip/Makefile b/drivers/mtd/nvmxip/Makefile index 07890982c7e..54eacc102e6 100644 --- a/drivers/mtd/nvmxip/Makefile +++ b/drivers/mtd/nvmxip/Makefile @@ -5,3 +5,4 @@ # Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> obj-y += nvmxip-uclass.o nvmxip.o +obj-$(CONFIG_NVMXIP_QSPI) += nvmxip_qspi.o diff --git a/drivers/mtd/nvmxip/nvmxip_qspi.c b/drivers/mtd/nvmxip/nvmxip_qspi.c new file mode 100644 index 00000000000..7221fd1cb46 --- /dev/null +++ b/drivers/mtd/nvmxip/nvmxip_qspi.c @@ -0,0 +1,70 @@ +// 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 <fdt_support.h> +#include <linux/errno.h> +#include "nvmxip.h" + +#include <asm/global_data.h> +DECLARE_GLOBAL_DATA_PTR; + +#define NVMXIP_QSPI_DRV_NAME "nvmxip_qspi" + +/** + * nvmxip_qspi_of_to_plat() -read from DT + * @dev: the NVMXIP device + * + * Read from the DT the NVMXIP information. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int nvmxip_qspi_of_to_plat(struct udevice *dev) +{ + struct nvmxip_plat *plat = dev_get_plat(dev); + int ret; + + plat->phys_base = (phys_addr_t)dev_read_addr(dev); + if (plat->phys_base == FDT_ADDR_T_NONE) { + log_err("[%s]: can not get base address from device tree\n", dev->name); + return -EINVAL; + } + + ret = dev_read_u32(dev, "lba_shift", &plat->lba_shift); + if (ret) { + log_err("[%s]: can not get lba_shift from device tree\n", dev->name); + return -EINVAL; + } + + ret = dev_read_u32(dev, "lba", (u32 *)&plat->lba); + if (ret) { + log_err("[%s]: can not get lba from device tree\n", dev->name); + return -EINVAL; + } + + log_debug("[%s]: XIP device base addr: 0x%llx , lba_shift: %d , lbas: %lu\n", + dev->name, plat->phys_base, plat->lba_shift, plat->lba); + + return 0; +} + +static const struct udevice_id nvmxip_qspi_ids[] = { + { .compatible = "nvmxip,qspi" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(nvmxip_qspi) = { + .name = NVMXIP_QSPI_DRV_NAME, + .id = UCLASS_NVMXIP, + .of_match = nvmxip_qspi_ids, + .of_to_plat = nvmxip_qspi_of_to_plat, + .plat_auto = sizeof(struct nvmxip_plat), +}; |