From patchwork Thu Jul 9 11:17:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 241119 List-Id: U-Boot discussion From: jagan at amarulasolutions.com (Jagan Teki) Date: Thu, 9 Jul 2020 16:47:05 +0530 Subject: [PATCH 1/5] mtd: spi: Drop redundent SPI flash driver In-Reply-To: <20200709111709.68904-1-jagan@amarulasolutions.com> References: <20200709111709.68904-1-jagan@amarulasolutions.com> Message-ID: <20200709111709.68904-2-jagan@amarulasolutions.com> UCLASS_SPI_FLASH driver at driver/mtd/spi is a generic spi flash driver to probe jedec,spi-nor flash chips. Technically a probe call in U_BOOT_DRIVER is local to that driver and not applicable to use it another driver or in another code. The apollolake SPL code using the generic probe by adding extra SPI flash driver, which make more confusion in terms of code readability and driver model structure. The fact that apollolake SPL requires a separate SPI flash driver to handle of-platdata via bind call, so move the bind call in the generic flash driver and drop the driver from apollolake code. I hope this wouldn't break generic code usage flash chips otherwise, we can handle this via driver data or a separate spi driver in drivers/mtd/spi. Cc: Bin Meng Cc: Simon Glass Cc: Vignesh R Signed-off-by: Jagan Teki --- arch/x86/cpu/apollolake/spl.c | 60 ----------------------------------- drivers/mtd/spi/sf-uclass.c | 29 ++++++++++++++++- include/spi_flash.h | 12 ------- 3 files changed, 28 insertions(+), 73 deletions(-) diff --git a/arch/x86/cpu/apollolake/spl.c b/arch/x86/cpu/apollolake/spl.c index 5a53831dc6..e1ee1e0624 100644 --- a/arch/x86/cpu/apollolake/spl.c +++ b/arch/x86/cpu/apollolake/spl.c @@ -68,66 +68,6 @@ SPL_LOAD_IMAGE_METHOD("Mapped SPI", 2, BOOT_DEVICE_SPI_MMAP, rom_load_image); #if CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT) -static int apl_flash_std_read(struct udevice *dev, u32 offset, size_t len, - void *buf) -{ - struct spi_flash *flash = dev_get_uclass_priv(dev); - struct mtd_info *mtd = &flash->mtd; - size_t retlen; - - return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); -} - -static int apl_flash_probe(struct udevice *dev) -{ - return spi_flash_std_probe(dev); -} - -/* - * Manually set the parent of the SPI flash to SPI, since dtoc doesn't. We also - * need to allocate the parent_platdata since by the time this function is - * called device_bind() has already gone past that step. - */ -static int apl_flash_bind(struct udevice *dev) -{ - if (CONFIG_IS_ENABLED(OF_PLATDATA)) { - struct dm_spi_slave_platdata *plat; - struct udevice *spi; - int ret; - - ret = uclass_first_device_err(UCLASS_SPI, &spi); - if (ret) - return ret; - dev->parent = spi; - - plat = calloc(sizeof(*plat), 1); - if (!plat) - return -ENOMEM; - dev->parent_platdata = plat; - } - - return 0; -} - -static const struct dm_spi_flash_ops apl_flash_ops = { - .read = apl_flash_std_read, -}; - -static const struct udevice_id apl_flash_ids[] = { - { .compatible = "jedec,spi-nor" }, - { } -}; - -U_BOOT_DRIVER(winbond_w25q128fw) = { - .name = "winbond_w25q128fw", - .id = UCLASS_SPI_FLASH, - .of_match = apl_flash_ids, - .bind = apl_flash_bind, - .probe = apl_flash_probe, - .priv_auto_alloc_size = sizeof(struct spi_flash), - .ops = &apl_flash_ops, -}; - /* This uses a SPI flash device to read the next phase */ static int spl_fast_spi_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index b09046fec3..44cdb3151d 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -122,7 +122,7 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) return mtd->_erase(mtd, &instr); } -int spi_flash_std_probe(struct udevice *dev) +static int spi_flash_std_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); struct spi_flash *flash; @@ -164,6 +164,32 @@ static int spi_flash_std_remove(struct udevice *dev) return 0; } +/* + * Manually set the parent of the SPI flash to SPI, since dtoc doesn't. We also + * need to allocate the parent_platdata since by the time this function is + * called device_bind() has already gone past that step. + */ +static int spi_flash_std_bind(struct udevice *dev) +{ + if (CONFIG_IS_ENABLED(OF_PLATDATA)) { + struct dm_spi_slave_platdata *plat; + struct udevice *spi; + int ret; + + ret = uclass_first_device_err(UCLASS_SPI, &spi); + if (ret) + return ret; + dev->parent = spi; + + plat = calloc(sizeof(*plat), 1); + if (!plat) + return -ENOMEM; + dev->parent_platdata = plat; + } + + return 0; +} + static const struct dm_spi_flash_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, @@ -180,6 +206,7 @@ U_BOOT_DRIVER(spi_flash_std) = { .id = UCLASS_SPI_FLASH, .of_match = spi_flash_std_ids, .probe = spi_flash_std_probe, + .bind = spi_flash_std_bind, .remove = spi_flash_std_remove, .priv_auto_alloc_size = sizeof(struct spi_flash), .ops = &spi_flash_std_ops, diff --git a/include/spi_flash.h b/include/spi_flash.h index 41cf4b0670..24759944eb 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -75,18 +75,6 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, */ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len); -/** - * spi_flash_std_probe() - Probe a SPI flash device - * - * This is the standard internal method for probing a SPI flash device to - * determine its type. It can be used in chip-specific drivers which need to - * do this, typically with of-platdata - * - * @dev: SPI-flash device to probe - * @return 0 if OK, -ve on error - */ -int spi_flash_std_probe(struct udevice *dev); - static inline int spi_flash_read(struct spi_flash *flash, u32 offset, size_t len, void *buf) { From patchwork Thu Jul 9 11:17:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 241120 List-Id: U-Boot discussion From: jagan at amarulasolutions.com (Jagan Teki) Date: Thu, 9 Jul 2020 16:47:06 +0530 Subject: [PATCH 2/5] mtd: Add dm-mtd core ops In-Reply-To: <20200709111709.68904-1-jagan@amarulasolutions.com> References: <20200709111709.68904-1-jagan@amarulasolutions.com> Message-ID: <20200709111709.68904-3-jagan@amarulasolutions.com> - Add generic mtd operations for UCLASS_MTD - Add mtd_dread|derase|dwrite The respetive MTD_UCLASS drivers must install the hooks to these mtd_ops and other core ops are act as a interface b/w drivers vs command code. Cc: Simon Glass Cc: Vignesh R Signed-off-by: Jagan Teki --- drivers/mtd/mtd-uclass.c | 38 +++++++++++++++++++++++++++++++++++++ include/mtd.h | 41 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/drivers/mtd/mtd-uclass.c b/drivers/mtd/mtd-uclass.c index 5418217431..bb00336a60 100644 --- a/drivers/mtd/mtd-uclass.c +++ b/drivers/mtd/mtd-uclass.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* + * Copyright (c) 2020 Amarula Solutions(India) + * Copyright (c) 2020 Jagan Teki * Copyright (C) 2015 Thomas Chou */ @@ -8,6 +10,42 @@ #include #include #include +#include + +int mtd_dread(struct udevice *dev, loff_t from, size_t len, u_char *buf) +{ + const struct mtd_ops *ops = mtd_get_ops(dev); + + if (!ops->read) + return -EOPNOTSUPP; + + return ops->read(dev, from, len, buf); +} + +int mtd_derase(struct udevice *dev, loff_t off, size_t len) +{ + const struct mtd_ops *ops = mtd_get_ops(dev); + struct erase_info instr; + + if (!ops->erase) + return -EOPNOTSUPP; + + memset(&instr, 0, sizeof(instr)); + instr.addr = off; + instr.len = len; + + return ops->erase(dev, &instr); +} + +int mtd_dwrite(struct udevice *dev, loff_t to, size_t len, const u_char *buf) +{ + const struct mtd_ops *ops = mtd_get_ops(dev); + + if (!ops->write) + return -EOPNOTSUPP; + + return ops->write(dev, to, len, buf); +} /** * mtd_probe - Probe the device @dev if not already done diff --git a/include/mtd.h b/include/mtd.h index b0f8693386..b94afe8945 100644 --- a/include/mtd.h +++ b/include/mtd.h @@ -8,6 +8,47 @@ #include +struct mtd_ops { + int (*erase)(struct udevice *dev, struct erase_info *instr); + int (*read)(struct udevice *dev, loff_t from, size_t len, + u_char *buf); + int (*write)(struct udevice *dev, loff_t to, size_t len, + const u_char *buf); +}; + +#define mtd_get_ops(dev) ((struct mtd_ops *)(dev)->driver->ops) + +/** + * mtd_dread() - Read data from mtd device + * + * @dev: mtd udevice + * @from: Offset into device in bytes to read from + * @len: Length of bytes to read + * @buf: Buffer to put the data that is read + * @return 0 if OK, -ve on error + */ +int mtd_dread(struct udevice *dev, loff_t from, size_t len, u_char *buf); + +/** + * mtd_dwrite() - Write data to mtd device + * + * @dev: mtd udevice + * @to: Offset into device in bytes to write to + * @len: Length of bytes to write + * @buf: Buffer containing bytes to write + * @return 0 if OK, -ve on error + */ +int mtd_dwrite(struct udevice *dev, loff_t to, size_t len, const u_char *buf); + +/** + * mtd_derase() - Erase blocks of the mtd device + * + * @dev: mtd udevice + * @instr: Erase info details of mtd device + * @return 0 if OK, -ve on error + */ +int mtd_derase(struct udevice *dev, loff_t off, size_t len); + int mtd_probe(struct udevice *dev); int mtd_probe_devices(void); From patchwork Thu Jul 9 11:17:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 241121 List-Id: U-Boot discussion From: jagan at amarulasolutions.com (Jagan Teki) Date: Thu, 9 Jul 2020 16:47:07 +0530 Subject: [PATCH 3/5] mtd: Add SPL_DM_MTD option In-Reply-To: <20200709111709.68904-1-jagan@amarulasolutions.com> References: <20200709111709.68904-1-jagan@amarulasolutions.com> Message-ID: <20200709111709.68904-4-jagan@amarulasolutions.com> Add SPL option for DM_MTD. Cc: Simon Glass Cc: Vignesh R Signed-off-by: Jagan Teki --- drivers/mtd/Kconfig | 8 ++++++++ drivers/mtd/Makefile | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 348b43e653..3feedf311f 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -17,6 +17,14 @@ config DM_MTD flash, RAM and similar chips, often used for solid state file systems on embedded devices. +config SPL_DM_MTD + bool "Enable Driver Model for MTD drivers in SPL" + depends on SPL_DM + help + Enable driver model for Memory Technology Devices (MTD), such as + flash, RAM and similar chips, often used for solid state file + systems on embedded devices. + config MTD_NOR_FLASH bool "Enable parallel NOR flash support" help diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 318788c5e2..f6b0719746 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -4,7 +4,7 @@ # Wolfgang Denk, DENX Software Engineering, wd at denx.de. mtd-$(CONFIG_MTD) += mtdcore.o mtd_uboot.o -mtd-$(CONFIG_DM_MTD) += mtd-uclass.o +mtd-$(CONFIG_$(SPL_)DM_MTD) += mtd-uclass.o mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o mtd-$(CONFIG_MTD_CONCAT) += mtdconcat.o mtd-$(CONFIG_ALTERA_QSPI) += altera_qspi.o From patchwork Thu Jul 9 11:17:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 241122 List-Id: U-Boot discussion From: jagan at amarulasolutions.com (Jagan Teki) Date: Thu, 9 Jul 2020 16:47:08 +0530 Subject: [PATCH 4/5] mtd: Build mtd-uclass as obj In-Reply-To: <20200709111709.68904-1-jagan@amarulasolutions.com> References: <20200709111709.68904-1-jagan@amarulasolutions.com> Message-ID: <20200709111709.68904-5-jagan@amarulasolutions.com> Technically dm and nodm codebases have to build separately since the SPL and U-Boot proper will enable based on the requirements and foot-print sizes. Till now there is no usage of SPL DM_MTD, but if we enable it can't build since the mtd-uclass is linked with nodm MTD code. So move the build link from mtd to obj so-that it can make compatible with all build types. Cc: Simon Glass Cc: Vignesh R Signed-off-by: Jagan Teki --- drivers/mtd/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index f6b0719746..baab7b8657 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -4,7 +4,6 @@ # Wolfgang Denk, DENX Software Engineering, wd at denx.de. mtd-$(CONFIG_MTD) += mtdcore.o mtd_uboot.o -mtd-$(CONFIG_$(SPL_)DM_MTD) += mtd-uclass.o mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o mtd-$(CONFIG_MTD_CONCAT) += mtdconcat.o mtd-$(CONFIG_ALTERA_QSPI) += altera_qspi.o @@ -18,6 +17,9 @@ mtd-$(CONFIG_STM32_FLASH) += stm32_flash.o mtd-$(CONFIG_RENESAS_RPC_HF) += renesas_rpc_hf.o mtd-$(CONFIG_HBMC_AM654) += hbmc-am654.o +# dm-mtd +obj-$(CONFIG_$(SPL_)DM_MTD) += mtd-uclass.o + # U-Boot build ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) From patchwork Thu Jul 9 11:17:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 241123 List-Id: U-Boot discussion From: jagan at amarulasolutions.com (Jagan Teki) Date: Thu, 9 Jul 2020 16:47:09 +0530 Subject: [PATCH 5/5] mtd: spi: Switch to MTD uclass (absolute UCLASS_SPI_FLASH) In-Reply-To: <20200709111709.68904-1-jagan@amarulasolutions.com> References: <20200709111709.68904-1-jagan@amarulasolutions.com> Message-ID: <20200709111709.68904-6-jagan@amarulasolutions.com> Why MTD UCLASS switch? >From a nutshell, all the memory-related flash devices like Parallel NOR, Raw NAND, SPI NOR/NAND stacks should be part of the MTD layer. The same theory applies to incase of MTD UCLASS in U-Boot. Unfortunately, no flash drivers are using the MTD UCLASS in the fully functional driver model. There are several reasons behind it like - MTD code always copies/sync from Linux to support the latest ? flash features. - So no special interest to touch since flash code is much bigger ? than usual and a lot of features are tested with existing code. - No real taker to implement it. So, this patch is trying to move further to use a common flash interface layer called MTD in the driver model way. As initial support it supporting spinor flash device drivers would be written as UCLASS_MTD. What happened to UCLASS_SPI_FLASH, why it is absolute now? Due to the effect of Linux MTD/SPI_NOR sync the existing spi_flash the structure has been affected such a way that it was dead and typedefs to spi_nor. What happened with this patch then? With this patch, the UCLASS_SPI_FLASH will be replaced with UCLASS_MTD by using dm-driven mtd_ops. absolute link: sf.c => sf uclass => sf driver => spi-nor-core - flash operations via dm_spi_flash_ops updated link: sf.c => mtd uclass => mtd driver => spi-nor-core - flash operations via mtd_ops (dm variant) Future work? - cleanup of spi_flash with spinor - renaming of CONFIG option changes - implement common mtd probe - implement mtd flash interface types so that the respective ? commands like sf, mtd can make use of dm-mtd in the proper way. Signed-off-by: Jagan Teki --- arch/arm/mach-rockchip/spl-boot-order.c | 4 +- arch/x86/cpu/apollolake/spl.c | 8 +- arch/x86/lib/fsp2/fsp_init.c | 2 +- arch/x86/lib/fsp2/fsp_support.c | 7 +- arch/x86/lib/mrccache.c | 8 +- board/atmel/common/mac-spi-nor.c | 4 +- drivers/mtd/spi/Kconfig | 2 + drivers/mtd/spi/sandbox.c | 2 +- drivers/mtd/spi/sf-uclass.c | 106 ++++++------------------ drivers/mtd/spi/sf_dataflash.c | 25 +++--- include/dm/uclass-id.h | 1 - include/spi_flash.h | 53 +----------- test/dm/sf.c | 12 +-- 13 files changed, 71 insertions(+), 163 deletions(-) diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c index 94673f34c9..64a745d189 100644 --- a/arch/arm/mach-rockchip/spl-boot-order.c +++ b/arch/arm/mach-rockchip/spl-boot-order.c @@ -62,7 +62,7 @@ static int spl_node_to_boot_device(int node) default: return -ENOSYS; } - } else if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, + } else if (!uclass_get_device_by_of_offset(UCLASS_MTD, node, &parent)) { return BOOT_DEVICE_SPI; } @@ -73,7 +73,7 @@ static int spl_node_to_boot_device(int node) * extended with awareness of the BLK layer (and matching OF_CONTROL) * soon. */ - if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent)) + if (!uclass_get_device_by_of_offset(UCLASS_MTD, node, &parent)) return BOOT_DEVICE_SPI; return -1; diff --git a/arch/x86/cpu/apollolake/spl.c b/arch/x86/cpu/apollolake/spl.c index e1ee1e0624..9c80440bbb 100644 --- a/arch/x86/cpu/apollolake/spl.c +++ b/arch/x86/cpu/apollolake/spl.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ static int rom_load_image(struct spl_image_info *spl_image, debug("Reading from mapped SPI %lx, size %lx", spl_pos, spl_size); if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) { - ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev); + ret = uclass_find_first_device(UCLASS_MTD, &dev); if (ret) return log_msg_ret("spi_flash", ret); if (!dev) @@ -77,7 +78,7 @@ static int spl_fast_spi_load_image(struct spl_image_info *spl_image, struct udevice *dev; int ret; - ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev); + ret = uclass_first_device_err(UCLASS_MTD, &dev); if (ret) return ret; @@ -89,8 +90,7 @@ static int spl_fast_spi_load_image(struct spl_image_info *spl_image, spl_image->name = "U-Boot"; spl_pos &= ~0xff000000; debug("Reading from flash %lx, size %lx\n", spl_pos, spl_size); - ret = spi_flash_read_dm(dev, spl_pos, spl_size, - (void *)spl_image->load_addr); + ret = mtd_dread(dev, spl_pos, spl_size, (void *)spl_image->load_addr); cpu_flush_l1d_to_l2(); if (ret) return ret; diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c index 85cae54a0c..61af45d239 100644 --- a/arch/x86/lib/fsp2/fsp_init.c +++ b/arch/x86/lib/fsp2/fsp_init.c @@ -124,7 +124,7 @@ int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry, struct udevice *sf; /* Just use the SPI driver to get the memory map */ - ret = uclass_find_first_device(UCLASS_SPI_FLASH, &sf); + ret = uclass_find_first_device(UCLASS_MTD, &sf); if (ret) return log_msg_ret("Cannot get SPI flash", ret); ret = dm_spi_get_mmap(sf, &map_base, &map_size, &offset); diff --git a/arch/x86/lib/fsp2/fsp_support.c b/arch/x86/lib/fsp2/fsp_support.c index 3f2ca840dc..434bfdbc0e 100644 --- a/arch/x86/lib/fsp2/fsp_support.c +++ b/arch/x86/lib/fsp2/fsp_support.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -37,10 +38,10 @@ int fsp_get_header(ulong offset, ulong size, bool use_spi_flash, */ debug("offset=%x buf=%x\n", (uint)offset, (uint)buf); if (use_spi_flash) { - ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev); + ret = uclass_first_device_err(UCLASS_MTD, &dev); if (ret) return log_msg_ret("Cannot find flash device", ret); - ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf); + ret = mtd_dread(dev, offset, PROBE_BUF_SIZE, buf); if (ret) return log_msg_ret("Cannot read flash", ret); } else { @@ -88,7 +89,7 @@ int fsp_get_header(ulong offset, ulong size, bool use_spi_flash, debug("Image base %x\n", (uint)base); debug("Image addr %x\n", (uint)fsp->fsp_mem_init); if (use_spi_flash) { - ret = spi_flash_read_dm(dev, offset, size, base); + ret = mtd_dread(dev, offset, size, base); if (ret) return log_msg_ret("Could not read FPS-M", ret); } else { diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index f181e8100c..30eb5cf669 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -167,7 +168,7 @@ static int mrccache_update(struct udevice *sf, struct mrc_region *entry, debug("Erasing the MRC cache region of %x bytes at %x\n", entry->length, entry->offset); - ret = spi_flash_erase_dm(sf, entry->offset, entry->length); + ret = mtd_derase(sf, entry->offset, entry->length); if (ret) { debug("Failed to erase flash region\n"); return ret; @@ -178,8 +179,7 @@ static int mrccache_update(struct udevice *sf, struct mrc_region *entry, /* Write the data out */ offset = (ulong)cache - base_addr + entry->offset; debug("Write MRC cache update to flash at %lx\n", offset); - ret = spi_flash_write_dm(sf, offset, cur->data_size + sizeof(*cur), - cur); + ret = mtd_dwrite(sf, offset, cur->data_size + sizeof(*cur), cur); if (ret) { debug("Failed to write to SPI flash\n"); return log_msg_ret("Cannot update mrccache", ret); @@ -242,7 +242,7 @@ int mrccache_get_region(enum mrc_type_t type, struct udevice **devp, * the device here since it may put it into a strange state where the * memory map cannot be read. */ - ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev); + ret = uclass_find_first_device(UCLASS_MTD, &dev); if (ret || !dev) { /* * Fall back to searching the device tree since driver model diff --git a/board/atmel/common/mac-spi-nor.c b/board/atmel/common/mac-spi-nor.c index ced27b65e6..0b3f1b1340 100644 --- a/board/atmel/common/mac-spi-nor.c +++ b/board/atmel/common/mac-spi-nor.c @@ -107,10 +107,10 @@ void at91_spi_nor_set_ethaddr(void) if (env_get(ethaddr_name)) return; - if (uclass_first_device_err(UCLASS_SPI_FLASH, &dev)) + if (uclass_first_device_err(UCLASS_MTD, &dev)) return; - nor = dev_get_uclass_priv(dev); + nor = dev_get_priv(dev); if (!nor) return; diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 018e8c597e..9de0484b29 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -3,6 +3,8 @@ menu "SPI Flash Support" config DM_SPI_FLASH bool "Enable Driver Model for SPI flash" depends on DM && DM_SPI + select DM_MTD + imply SPL_DM_MTD imply SPI_FLASH help Enable driver model for SPI flash. This SPI flash interface diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index 8cbe97ee20..0b04f14b16 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -8,7 +8,7 @@ * Licensed under the GPL-2 or later. */ -#define LOG_CATEGORY UCLASS_SPI_FLASH +#define LOG_CATEGORY UCLASS_MTD #include #include diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 44cdb3151d..9cab08f49b 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,22 +15,6 @@ DECLARE_GLOBAL_DATA_PTR; -int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf) -{ - return log_ret(sf_get_ops(dev)->read(dev, offset, len, buf)); -} - -int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, - const void *buf) -{ - return log_ret(sf_get_ops(dev)->write(dev, offset, len, buf)); -} - -int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) -{ - return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); -} - void spi_flash_free(struct spi_flash *flash) { device_remove(flash->spi->dev, DM_REMOVE_NORMAL); @@ -57,108 +42,78 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, str = strdup(name); #endif ret = spi_get_bus_and_cs(bus, cs, max_hz, spi_mode, - "spi_flash_std", str, &bus_dev, &slave); + "spi_flash_std", str, &bus_dev, &slave); if (ret) return NULL; - return dev_get_uclass_priv(slave->dev); + return dev_get_priv(slave->dev); } -static int spi_flash_post_bind(struct udevice *dev) +static int spi_flash_std_read(struct udevice *dev, loff_t from, size_t len, + u_char *buf) { -#if defined(CONFIG_NEEDS_MANUAL_RELOC) - struct dm_spi_flash_ops *ops = sf_get_ops(dev); - static int reloc_done; - - if (!reloc_done) { - if (ops->read) - ops->read += gd->reloc_off; - if (ops->write) - ops->write += gd->reloc_off; - if (ops->erase) - ops->erase += gd->reloc_off; - - reloc_done++; - } -#endif - return 0; -} - -static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, - void *buf) -{ - struct spi_flash *flash = dev_get_uclass_priv(dev); + struct spi_flash *flash = dev_get_priv(dev); struct mtd_info *mtd = &flash->mtd; size_t retlen; - return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); + return log_ret(mtd->_read(mtd, from, len, &retlen, buf)); } -static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) +static int spi_flash_std_write(struct udevice *dev, loff_t to, size_t len, + const u_char *buf) { - struct spi_flash *flash = dev_get_uclass_priv(dev); + struct spi_flash *flash = dev_get_priv(dev); struct mtd_info *mtd = &flash->mtd; size_t retlen; - return mtd->_write(mtd, offset, len, &retlen, buf); + return mtd->_write(mtd, to, len, &retlen, buf); } -static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) +static int spi_flash_std_erase(struct udevice *dev, struct erase_info *instr) { - struct spi_flash *flash = dev_get_uclass_priv(dev); + struct spi_flash *flash = dev_get_priv(dev); struct mtd_info *mtd = &flash->mtd; - struct erase_info instr; - if (offset % mtd->erasesize || len % mtd->erasesize) { - printf("SF: Erase offset/length not multiple of erase size\n"); + if (instr->addr % mtd->erasesize || instr->len % mtd->erasesize) { + dev_err(dev, "Erase offset/length not multiple of erasesize\n"); return -EINVAL; } - memset(&instr, 0, sizeof(instr)); - instr.addr = offset; - instr.len = len; - - return mtd->_erase(mtd, &instr); + return mtd->_erase(mtd, instr); } static int spi_flash_std_probe(struct udevice *dev) { + struct spi_flash *flash = dev_get_priv(dev); struct spi_slave *slave = dev_get_parent_priv(dev); - struct spi_flash *flash; int ret; - if (!slave) { - printf("SF: Failed to set up slave\n"); - return -ENODEV; - } - - flash = dev_get_uclass_priv(dev); flash->dev = dev; flash->spi = slave; - /* Claim spi bus */ ret = spi_claim_bus(slave); if (ret) { - debug("SF: Failed to claim SPI bus: %d\n", ret); + dev_err(dev, "failed to claim bus (ret=%d)\n", ret); return ret; } ret = spi_nor_scan(flash); - if (ret) - goto err_read_id; + if (ret) { + dev_err(dev, "failed to scan spinor (ret=%d)\n", ret); + goto err_claim_bus; + } - if (CONFIG_IS_ENABLED(SPI_FLASH_MTD)) + if (IS_ENABLED(CONFIG_SPI_FLASH_MTD)) ret = spi_flash_mtd_register(flash); -err_read_id: +err_claim_bus: spi_release_bus(slave); return ret; } static int spi_flash_std_remove(struct udevice *dev) { - if (CONFIG_IS_ENABLED(SPI_FLASH_MTD)) + if (IS_ENABLED(CONFIG_SPI_FLASH_MTD)) spi_flash_mtd_unregister(); return 0; @@ -190,7 +145,7 @@ static int spi_flash_std_bind(struct udevice *dev) return 0; } -static const struct dm_spi_flash_ops spi_flash_std_ops = { +static const struct mtd_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase, @@ -203,7 +158,7 @@ static const struct udevice_id spi_flash_std_ids[] = { U_BOOT_DRIVER(spi_flash_std) = { .name = "spi_flash_std", - .id = UCLASS_SPI_FLASH, + .id = UCLASS_MTD, .of_match = spi_flash_std_ids, .probe = spi_flash_std_probe, .bind = spi_flash_std_bind, @@ -211,10 +166,3 @@ U_BOOT_DRIVER(spi_flash_std) = { .priv_auto_alloc_size = sizeof(struct spi_flash), .ops = &spi_flash_std_ops, }; - -UCLASS_DRIVER(spi_flash) = { - .id = UCLASS_SPI_FLASH, - .name = "spi_flash", - .post_bind = spi_flash_post_bind, - .per_device_auto_alloc_size = sizeof(struct spi_flash), -}; diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 27d847d421..5c73b54cbc 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -117,7 +118,7 @@ static int dataflash_waitready(struct spi_slave *spi) } /* Erase pages of flash */ -static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) +static int spi_dataflash_erase(struct udevice *dev, struct erase_info *instr) { struct dataflash *dataflash; struct spi_flash *spi_flash; @@ -125,6 +126,8 @@ static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) unsigned blocksize; uint8_t *command; uint32_t rem; + loff_t offset = instr->addr; + size_t len = instr->len; int status; dataflash = dev_get_priv(dev); @@ -136,7 +139,7 @@ static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) memset(dataflash->command, 0 , sizeof(dataflash->command)); command = dataflash->command; - debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); + debug("%s: erase addr=0x%llx len 0x%x\n", dev->name, offset, len); div_u64_rem(len, spi_flash->page_size, &rem); if (rem) { @@ -146,7 +149,7 @@ static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) } div_u64_rem(offset, spi_flash->page_size, &rem); if (rem) { - printf("%s: offset(0x%x) isn't the multiple of page size(0x%x)\n", + printf("%s: offset(0x%llx) isn't the multiple of page size(0x%x)\n", dev->name, offset, spi_flash->page_size); return -EINVAL; } @@ -210,8 +213,8 @@ static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) * len : Amount to read * buf : Buffer containing the data */ -static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, - void *buf) +static int spi_dataflash_read(struct udevice *dev, loff_t offset, size_t len, + u_char *buf) { struct dataflash *dataflash; struct spi_flash *spi_flash; @@ -227,7 +230,7 @@ static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, memset(dataflash->command, 0 , sizeof(dataflash->command)); command = dataflash->command; - debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); + debug("%s: erase addr=0x%llx len 0x%x\n", dev->name, offset, len); debug("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]); @@ -266,8 +269,8 @@ static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, * len : Amount to write * buf : Buffer containing the data */ -int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) +int spi_dataflash_write(struct udevice *dev, loff_t offset, size_t len, + const u_char *buf) { struct dataflash *dataflash; struct spi_flash *spi_flash; @@ -285,7 +288,7 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, memset(dataflash->command, 0 , sizeof(dataflash->command)); command = dataflash->command; - debug("%s: write 0x%x..0x%x\n", dev->name, offset, (offset + len)); + debug("%s: write 0x%llx..0x%llx\n", dev->name, offset, (offset + len)); pageaddr = ((unsigned)offset / spi_flash->page_size); to = ((unsigned)offset % spi_flash->page_size); @@ -676,7 +679,7 @@ err_jedec_probe: return status; } -static const struct dm_spi_flash_ops spi_dataflash_ops = { +static const struct mtd_ops spi_dataflash_ops = { .read = spi_dataflash_read, .write = spi_dataflash_write, .erase = spi_dataflash_erase, @@ -690,7 +693,7 @@ static const struct udevice_id spi_dataflash_ids[] = { U_BOOT_DRIVER(spi_dataflash) = { .name = "spi_dataflash", - .id = UCLASS_SPI_FLASH, + .id = UCLASS_MTD, .of_match = spi_dataflash_ids, .probe = spi_dataflash_probe, .priv_auto_alloc_size = sizeof(struct dataflash), diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 7837d459f1..1f56f7f48a 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -99,7 +99,6 @@ enum uclass_id { UCLASS_SMEM, /* Shared memory interface */ UCLASS_SOUND, /* Playing simple sounds */ UCLASS_SPI, /* SPI bus */ - UCLASS_SPI_FLASH, /* SPI flash */ UCLASS_SPI_GENERIC, /* Generic SPI flash target */ UCLASS_SPMI, /* System Power Management Interface bus */ UCLASS_SYSCON, /* System configuration device */ diff --git a/include/spi_flash.h b/include/spi_flash.h index 24759944eb..f4852fc5c1 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -10,6 +10,7 @@ #define _SPI_FLASH_H_ #include /* Because we dereference struct udevice here */ +#include #include #include @@ -27,70 +28,24 @@ # define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE #endif -struct spi_slave; - -struct dm_spi_flash_ops { - int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf); - int (*write)(struct udevice *dev, u32 offset, size_t len, - const void *buf); - int (*erase)(struct udevice *dev, u32 offset, size_t len); -}; - -/* Access the serial operations for a device */ -#define sf_get_ops(dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops) - #if CONFIG_IS_ENABLED(DM_SPI_FLASH) -/** - * spi_flash_read_dm() - Read data from SPI flash - * - * @dev: SPI flash device - * @offset: Offset into device in bytes to read from - * @len: Number of bytes to read - * @buf: Buffer to put the data that is read - * @return 0 if OK, -ve on error - */ -int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf); - -/** - * spi_flash_write_dm() - Write data to SPI flash - * - * @dev: SPI flash device - * @offset: Offset into device in bytes to write to - * @len: Number of bytes to write - * @buf: Buffer containing bytes to write - * @return 0 if OK, -ve on error - */ -int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, - const void *buf); - -/** - * spi_flash_erase_dm() - Erase blocks of the SPI flash - * - * Note that @len must be a muiltiple of the flash sector size. - * - * @dev: SPI flash device - * @offset: Offset into device in bytes to start erasing - * @len: Number of bytes to erase - * @return 0 if OK, -ve on error - */ -int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len); static inline int spi_flash_read(struct spi_flash *flash, u32 offset, size_t len, void *buf) { - return spi_flash_read_dm(flash->dev, offset, len, buf); + return mtd_dread(flash->dev, offset, len, buf); } static inline int spi_flash_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { - return spi_flash_write_dm(flash->dev, offset, len, buf); + return mtd_dwrite(flash->dev, offset, len, buf); } static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, size_t len) { - return spi_flash_erase_dm(flash->dev, offset, len); + return mtd_derase(flash->dev, offset, len); } struct sandbox_state; diff --git a/test/dm/sf.c b/test/dm/sf.c index 9e7dead684..a675923dc5 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -31,23 +31,23 @@ static int dm_test_spi_flash(struct unit_test_state *uts) src = map_sysmem(0x20000, full_size); ut_assertok(os_write_file("spi.bin", src, full_size)); - ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev)); + ut_assertok(uclass_first_device_err(UCLASS_MTD, &dev)); dst = map_sysmem(0x20000 + full_size, full_size); - ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + ut_assertok(mtd_dread(dev, 0, size, dst)); ut_asserteq_mem(src, dst, size); /* Erase */ - ut_assertok(spi_flash_erase_dm(dev, 0, size)); - ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + ut_assertok(mtd_derase(dev, 0, size)); + ut_assertok(mtd_dread(dev, 0, size, dst)); for (i = 0; i < size; i++) ut_asserteq(dst[i], 0xff); /* Write some new data */ for (i = 0; i < size; i++) src[i] = i; - ut_assertok(spi_flash_write_dm(dev, 0, size, src)); - ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); + ut_assertok(mtd_dwrite(dev, 0, size, src)); + ut_assertok(mtd_dread(dev, 0, size, dst)); ut_asserteq_mem(src, dst, size); /* Check mapping */