| From 4b71ade0e8e5ad3692b1decb5c1d0c9472827535 Mon Sep 17 00:00:00 2001 |
| From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> |
| Date: Fri, 14 Apr 2023 13:44:25 +0100 |
| Subject: [PATCH 28/42] drivers/mtd/nvmxip: introduce QSPI XIP driver |
| |
| add nvmxip_qspi driver under UCLASS_NVMXIP |
| |
| The device associated with this driver 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 driver. The custom driver can be implemented like nvmxip_qspi in |
| addition to the platform custom settings. |
| |
| Platforms can use multiple NVM XIP devices at the same time by defining a |
| DT node for each one of them. |
| |
| For more details please refer to doc/develop/driver-model/nvmxip_qspi.rst |
| |
| Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> |
| Upstream-Status: Backport [https://github.com/u-boot/u-boot/commit/c9c2c95d4cd27fe0cd41fe13a863899d268f973c] |
| --- |
| MAINTAINERS | 1 + |
| doc/develop/driver-model/nvmxip.rst | 45 +++++++++++- |
| .../nvmxip/nvmxip_qspi.txt | 56 +++++++++++++++ |
| drivers/mtd/nvmxip/Kconfig | 6 ++ |
| drivers/mtd/nvmxip/Makefile | 1 + |
| drivers/mtd/nvmxip/nvmxip_qspi.c | 70 +++++++++++++++++++ |
| 6 files changed, 178 insertions(+), 1 deletion(-) |
| create mode 100644 doc/device-tree-bindings/nvmxip/nvmxip_qspi.txt |
| create mode 100644 drivers/mtd/nvmxip/nvmxip_qspi.c |
| |
| diff --git a/MAINTAINERS b/MAINTAINERS |
| index 1dbfab5f43..f81654346e 100644 |
| --- a/MAINTAINERS |
| +++ b/MAINTAINERS |
| @@ -1206,6 +1206,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 fe087b13d2..09afdbcccf 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 0000000000..cc60e9efdc |
| --- /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 ef53fc3c79..3ef7105026 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 07890982c7..54eacc102e 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 0000000000..7221fd1cb4 |
| --- /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), |
| +}; |
| -- |
| 2.25.1 |
| |