[U-Boot] [PATCH v7 00/34] sf: MTD support

This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes: - drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm) - drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities. - spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7: - Rebase to master - Added MTD core support to dataflash - Few patch bisectable separations
Changes in v6, v5, v4, v3, v2: - One patch bisectable separation - Rebase to master - added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
common/cmd_sf.c | 16 +- drivers/mtd/spi/Kconfig | 14 +- drivers/mtd/spi/Makefile | 9 +- .../mtd/spi/{sf_dataflash.c => mtd_dataflash.c} | 402 ++++++----- drivers/mtd/spi/sf-uclass.c | 39 -- drivers/mtd/spi/sf_internal.h | 74 +- drivers/mtd/spi/sf_mtd.c | 104 --- drivers/mtd/spi/sf_ops.c | 769 ++++++++++++++++----- drivers/mtd/spi/sf_probe.c | 508 ++------------ include/configs/aristainetos-common.h | 1 - include/configs/gw_ventana.h | 1 - include/configs/ls1021aqds.h | 2 +- include/configs/socfpga_common.h | 1 - include/configs/zynq-common.h | 1 + include/spi_flash.h | 163 ++--- 15 files changed, 926 insertions(+), 1178 deletions(-) rename drivers/mtd/spi/{sf_dataflash.c => mtd_dataflash.c} (64%) delete mode 100644 drivers/mtd/spi/sf_mtd.c

Rename spi_flash_validate_params to spi_flash_scan as this code not only deals with params setup but also configure all spi_flash attributes.
And also moved all flash related code into spi_flash_scan for future functionality addition.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_probe.c | 145 +++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 70 deletions(-)
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index a619182..0e20088 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -130,13 +130,42 @@ bank_end: } #endif
-static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, +#if CONFIG_IS_ENABLED(OF_CONTROL) +int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) +{ + fdt_addr_t addr; + fdt_size_t size; + int node; + + /* If there is no node, do nothing */ + node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); + if (node < 0) + return 0; + + addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("%s: Cannot decode address\n", __func__); + return 0; + } + + if (flash->size != size) { + debug("%s: Memory map must cover entire device\n", __func__); + return -1; + } + flash->memory_map = map_sysmem(addr, size); + + return 0; +} +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + +static int spi_flash_scan(struct spi_slave *spi, u8 *idcode, struct spi_flash *flash) { const struct spi_flash_params *params; u8 cmd; u16 jedec = idcode[1] << 8 | idcode[2]; u16 ext_jedec = idcode[3] << 8 | idcode[4]; + int ret;
/* Validate params from spi_flash_params table */ params = spi_flash_params_table; @@ -158,6 +187,13 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, return -EPROTONOSUPPORT; }
+ /* Flash powers up read-only, so clear BP# bits */ +#if defined(CONFIG_SPI_FLASH_ATMEL) || \ + defined(CONFIG_SPI_FLASH_MACRONIX) || \ + defined(CONFIG_SPI_FLASH_SST) + spi_flash_cmd_write_status(flash, 0); +#endif + /* Assign spi data */ flash->spi = spi; flash->name = params->name; @@ -253,6 +289,17 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, /* Go for default supported write cmd */ flash->write_cmd = CMD_PAGE_PROGRAM;
+ /* Set the quad enable bit - only for quad commands */ + if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || + (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || + (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { + ret = spi_flash_set_qeb(flash, idcode[0]); + if (ret) { + debug("SF: Fail to set QEB for %02x\n", idcode[0]); + return -EINVAL; + } + } + /* Read dummy_byte: dummy byte is determined based on the * dummy cycles of a particular command. * Fast commands - dummy_byte = dummy_cycles/8 @@ -279,48 +326,41 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
/* Configure the BAR - discover bank cmds and read current bank */ #ifdef CONFIG_SPI_FLASH_BAR - int ret = spi_flash_read_bank(flash, idcode[0]); + ret = spi_flash_read_bank(flash, idcode[0]); if (ret < 0) return ret; #endif
- /* Flash powers up read-only, so clear BP# bits */ -#if defined(CONFIG_SPI_FLASH_ATMEL) || \ - defined(CONFIG_SPI_FLASH_MACRONIX) || \ - defined(CONFIG_SPI_FLASH_SST) - spi_flash_cmd_write_status(flash, 0); -#endif - - return 0; -} - #if CONFIG_IS_ENABLED(OF_CONTROL) -int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) -{ - fdt_addr_t addr; - fdt_size_t size; - int node; - - /* If there is no node, do nothing */ - node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); - if (node < 0) - return 0; - - addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); - if (addr == FDT_ADDR_T_NONE) { - debug("%s: Cannot decode address\n", __func__); - return 0; + ret = spi_flash_decode_fdt(gd->fdt_blob, flash); + if (ret) { + debug("SF: FDT decode error\n"); + return -EINVAL; } +#endif
- if (flash->size != size) { - debug("%s: Memory map must cover entire device\n", __func__); - return -1; +#ifndef CONFIG_SPL_BUILD + printf("SF: Detected %s with page size ", flash->name); + print_size(flash->page_size, ", erase size "); + print_size(flash->erase_size, ", total "); + print_size(flash->size, ""); + if (flash->memory_map) + printf(", mapped at %p", flash->memory_map); + puts("\n"); +#endif + +#ifndef CONFIG_SPI_FLASH_BAR + if (((flash->dual_flash == SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN)) || + ((flash->dual_flash > SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN << 1))) { + puts("SF: Warning - Only lower 16MiB accessible,"); + puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); } - flash->memory_map = map_sysmem(addr, size); +#endif
- return 0; + return ret; } -#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
/** * spi_flash_probe_slave() - Probe for a SPI flash device on a bus @@ -359,47 +399,12 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) print_buffer(0, idcode, 1, sizeof(idcode), 0); #endif
- if (spi_flash_validate_params(spi, idcode, flash)) { + ret = spi_flash_scan(spi, idcode, flash); + if (ret) { ret = -EINVAL; goto err_read_id; }
- /* Set the quad enable bit - only for quad commands */ - if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || - (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || - (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { - if (spi_flash_set_qeb(flash, idcode[0])) { - debug("SF: Fail to set QEB for %02x\n", idcode[0]); - ret = -EINVAL; - goto err_read_id; - } - } - -#if CONFIG_IS_ENABLED(OF_CONTROL) - if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { - debug("SF: FDT decode error\n"); - ret = -EINVAL; - goto err_read_id; - } -#endif -#ifndef CONFIG_SPL_BUILD - printf("SF: Detected %s with page size ", flash->name); - print_size(flash->page_size, ", erase size "); - print_size(flash->erase_size, ", total "); - print_size(flash->size, ""); - if (flash->memory_map) - printf(", mapped at %p", flash->memory_map); - puts("\n"); -#endif -#ifndef CONFIG_SPI_FLASH_BAR - if (((flash->dual_flash == SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN)) || - ((flash->dual_flash > SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN << 1))) { - puts("SF: Warning - Only lower 16MiB accessible,"); - puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); - } -#endif #ifdef CONFIG_SPI_FLASH_MTD ret = spi_flash_mtd_register(flash); #endif

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
Rename spi_flash_validate_params to spi_flash_scan as this code not only deals with params setup but also configure all spi_flash attributes.
And also moved all flash related code into spi_flash_scan for future functionality addition.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_probe.c | 145 +++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 70 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Intension is that sf_ops should deals all spi_flash related stuff and sf_probe (which should renamed future) should be an interface layer for spi_flash versus spi drivers.
sf_ops => spi_flash interface sf_probe => interface layer vs spi_flash(sf_probe) to spi drivers
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 14 ++ drivers/mtd/spi/sf_ops.c | 343 ++++++++++++++++++++++++++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 342 ----------------------------------------- 3 files changed, 357 insertions(+), 342 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 85c8a89..f3eb6f3 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -245,4 +245,18 @@ int spi_flash_mtd_register(struct spi_flash *flash); void spi_flash_mtd_unregister(void); #endif
+/** + * spi_flash_scan - scan the SPI FLASH + * @spi: the spi slave structure + * @idcode: idcode of spi flash + * @flash: the spi flash structure + * + * The drivers can use this fuction to scan the SPI FLASH. + * In the scanning, it will try to get all the necessary information to + * fill the spi_flash{}. + * + * Return: 0 for success, others for failure. + */ +int spi_flash_scan(struct spi_slave *spi, u8 *idcode, struct spi_flash *flash); + #endif /* _SF_INTERNAL_H_ */ diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 3a56d7f..306db8f 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -11,6 +11,7 @@ #include <common.h> #include <errno.h> #include <malloc.h> +#include <mapmem.h> #include <spi.h> #include <spi_flash.h> #include <watchdog.h> @@ -19,6 +20,8 @@
#include "sf_internal.h"
+DECLARE_GLOBAL_DATA_PTR; + static void spi_flash_addr(u32 addr, u8 *cmd) { /* cmd[0] is actual command */ @@ -757,3 +760,343 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) return 0; } #endif + + +/* Read commands array */ +static u8 spi_read_cmds_array[] = { + CMD_READ_ARRAY_SLOW, + CMD_READ_ARRAY_FAST, + CMD_READ_DUAL_OUTPUT_FAST, + CMD_READ_DUAL_IO_FAST, + CMD_READ_QUAD_OUTPUT_FAST, + CMD_READ_QUAD_IO_FAST, +}; + +#ifdef CONFIG_SPI_FLASH_MACRONIX +static int spi_flash_set_qeb_mxic(struct spi_flash *flash) +{ + u8 qeb_status; + int ret; + + ret = spi_flash_cmd_read_status(flash, &qeb_status); + if (ret < 0) + return ret; + + if (qeb_status & STATUS_QEB_MXIC) { + debug("SF: mxic: QEB is already set\n"); + } else { + ret = spi_flash_cmd_write_status(flash, STATUS_QEB_MXIC); + if (ret < 0) + return ret; + } + + return ret; +} +#endif + +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) +static int spi_flash_set_qeb_winspan(struct spi_flash *flash) +{ + u8 qeb_status; + int ret; + + ret = spi_flash_cmd_read_config(flash, &qeb_status); + if (ret < 0) + return ret; + + if (qeb_status & STATUS_QEB_WINSPAN) { + debug("SF: winspan: QEB is already set\n"); + } else { + ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN); + if (ret < 0) + return ret; + } + + return ret; +} +#endif + +static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0) +{ + switch (idcode0) { +#ifdef CONFIG_SPI_FLASH_MACRONIX + case SPI_FLASH_CFI_MFR_MACRONIX: + return spi_flash_set_qeb_mxic(flash); +#endif +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + case SPI_FLASH_CFI_MFR_SPANSION: + case SPI_FLASH_CFI_MFR_WINBOND: + return spi_flash_set_qeb_winspan(flash); +#endif +#ifdef CONFIG_SPI_FLASH_STMICRO + case SPI_FLASH_CFI_MFR_STMICRO: + debug("SF: QEB is volatile for %02x flash\n", idcode0); + return 0; +#endif + default: + printf("SF: Need set QEB func for %02x flash\n", idcode0); + return -1; + } +} + +#ifdef CONFIG_SPI_FLASH_BAR +static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0) +{ + u8 curr_bank = 0; + int ret; + + if (flash->size <= SPI_FLASH_16MB_BOUN) + goto bank_end; + + switch (idcode0) { + case SPI_FLASH_CFI_MFR_SPANSION: + flash->bank_read_cmd = CMD_BANKADDR_BRRD; + flash->bank_write_cmd = CMD_BANKADDR_BRWR; + default: + flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; + flash->bank_write_cmd = CMD_EXTNADDR_WREAR; + } + + ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1, + &curr_bank, 1); + if (ret) { + debug("SF: fail to read bank addr register\n"); + return ret; + } + +bank_end: + flash->bank_curr = curr_bank; + return 0; +} +#endif + +#if CONFIG_IS_ENABLED(OF_CONTROL) +int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) +{ + fdt_addr_t addr; + fdt_size_t size; + int node; + + /* If there is no node, do nothing */ + node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); + if (node < 0) + return 0; + + addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("%s: Cannot decode address\n", __func__); + return 0; + } + + if (flash->size != size) { + debug("%s: Memory map must cover entire device\n", __func__); + return -1; + } + flash->memory_map = map_sysmem(addr, size); + + return 0; +} +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + +int spi_flash_scan(struct spi_slave *spi, u8 *idcode, struct spi_flash *flash) +{ + const struct spi_flash_params *params; + u8 cmd; + u16 jedec = idcode[1] << 8 | idcode[2]; + u16 ext_jedec = idcode[3] << 8 | idcode[4]; + int ret; + + /* Validate params from spi_flash_params table */ + params = spi_flash_params_table; + for (; params->name != NULL; params++) { + if ((params->jedec >> 16) == idcode[0]) { + if ((params->jedec & 0xFFFF) == jedec) { + if (params->ext_jedec == 0) + break; + else if (params->ext_jedec == ext_jedec) + break; + } + } + } + + if (!params->name) { + printf("SF: Unsupported flash IDs: "); + printf("manuf %02x, jedec %04x, ext_jedec %04x\n", + idcode[0], jedec, ext_jedec); + return -EPROTONOSUPPORT; + } + + /* Flash powers up read-only, so clear BP# bits */ +#if defined(CONFIG_SPI_FLASH_ATMEL) || \ + defined(CONFIG_SPI_FLASH_MACRONIX) || \ + defined(CONFIG_SPI_FLASH_SST) + spi_flash_cmd_write_status(flash, 0); +#endif + + /* Assign spi data */ + flash->spi = spi; + flash->name = params->name; + flash->memory_map = spi->memory_map; + flash->dual_flash = flash->spi->option; + + /* Assign spi flash flags */ + if (params->flags & SST_WR) + flash->flags |= SNOR_F_SST_WR; + + /* Assign spi_flash ops */ +#ifndef CONFIG_DM_SPI_FLASH + flash->write = spi_flash_cmd_write_ops; +#if defined(CONFIG_SPI_FLASH_SST) + if (flash->flags & SNOR_F_SST_WR) { + if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) + flash->write = sst_write_bp; + else + flash->write = sst_write_wp; + } +#endif + flash->erase = spi_flash_cmd_erase_ops; + flash->read = spi_flash_cmd_read_ops; +#endif + + /* lock hooks are flash specific - assign them based on idcode0 */ + switch (idcode[0]) { +#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) + case SPI_FLASH_CFI_MFR_STMICRO: + case SPI_FLASH_CFI_MFR_SST: + flash->flash_lock = stm_lock; + flash->flash_unlock = stm_unlock; + flash->flash_is_locked = stm_is_locked; +#endif + break; + default: + debug("SF: Lock ops not supported for %02x flash\n", idcode[0]); + } + + /* Compute the flash size */ + flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; + /* + * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the + * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with + * the 0x4d00 Extended JEDEC code have 512b pages. All of the others + * have 256b pages. + */ + if (ext_jedec == 0x4d00) { + if ((jedec == 0x0215) || (jedec == 0x216)) + flash->page_size = 256; + else + flash->page_size = 512; + } else { + flash->page_size = 256; + } + flash->page_size <<= flash->shift; + flash->sector_size = params->sector_size << flash->shift; + flash->size = flash->sector_size * params->nr_sectors << flash->shift; +#ifdef CONFIG_SF_DUAL_FLASH + if (flash->dual_flash & SF_DUAL_STACKED_FLASH) + flash->size <<= 1; +#endif + + /* Compute erase sector and command */ + if (params->flags & SECT_4K) { + flash->erase_cmd = CMD_ERASE_4K; + flash->erase_size = 4096 << flash->shift; + } else if (params->flags & SECT_32K) { + flash->erase_cmd = CMD_ERASE_32K; + flash->erase_size = 32768 << flash->shift; + } else { + flash->erase_cmd = CMD_ERASE_64K; + flash->erase_size = flash->sector_size; + } + + /* Now erase size becomes valid sector size */ + flash->sector_size = flash->erase_size; + + /* Look for the fastest read cmd */ + cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); + if (cmd) { + cmd = spi_read_cmds_array[cmd - 1]; + flash->read_cmd = cmd; + } else { + /* Go for default supported read cmd */ + flash->read_cmd = CMD_READ_ARRAY_FAST; + } + + /* Not require to look for fastest only two write cmds yet */ + if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP) + flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; + else + /* Go for default supported write cmd */ + flash->write_cmd = CMD_PAGE_PROGRAM; + + /* Set the quad enable bit - only for quad commands */ + if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || + (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || + (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { + ret = spi_flash_set_qeb(flash, idcode[0]); + if (ret) { + debug("SF: Fail to set QEB for %02x\n", idcode[0]); + return -EINVAL; + } + } + + /* Read dummy_byte: dummy byte is determined based on the + * dummy cycles of a particular command. + * Fast commands - dummy_byte = dummy_cycles/8 + * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 + * For I/O commands except cmd[0] everything goes on no.of lines + * based on particular command but incase of fast commands except + * data all go on single line irrespective of command. + */ + switch (flash->read_cmd) { + case CMD_READ_QUAD_IO_FAST: + flash->dummy_byte = 2; + break; + case CMD_READ_ARRAY_SLOW: + flash->dummy_byte = 0; + break; + default: + flash->dummy_byte = 1; + } + +#ifdef CONFIG_SPI_FLASH_STMICRO + if (params->flags & E_FSR) + flash->flags |= SNOR_F_USE_FSR; +#endif + + /* Configure the BAR - discover bank cmds and read current bank */ +#ifdef CONFIG_SPI_FLASH_BAR + ret = spi_flash_read_bank(flash, idcode[0]); + if (ret < 0) + return ret; +#endif + +#if CONFIG_IS_ENABLED(OF_CONTROL) + ret = spi_flash_decode_fdt(gd->fdt_blob, flash); + if (ret) { + debug("SF: FDT decode error\n"); + return -EINVAL; + } +#endif + +#ifndef CONFIG_SPL_BUILD + printf("SF: Detected %s with page size ", flash->name); + print_size(flash->page_size, ", erase size "); + print_size(flash->erase_size, ", total "); + print_size(flash->size, ""); + if (flash->memory_map) + printf(", mapped at %p", flash->memory_map); + puts("\n"); +#endif + +#ifndef CONFIG_SPI_FLASH_BAR + if (((flash->dual_flash == SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN)) || + ((flash->dual_flash > SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN << 1))) { + puts("SF: Warning - Only lower 16MiB accessible,"); + puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); + } +#endif + + return ret; +} diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 0e20088..994559d 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -20,348 +20,6 @@
#include "sf_internal.h"
-DECLARE_GLOBAL_DATA_PTR; - -/* Read commands array */ -static u8 spi_read_cmds_array[] = { - CMD_READ_ARRAY_SLOW, - CMD_READ_ARRAY_FAST, - CMD_READ_DUAL_OUTPUT_FAST, - CMD_READ_DUAL_IO_FAST, - CMD_READ_QUAD_OUTPUT_FAST, - CMD_READ_QUAD_IO_FAST, -}; - -#ifdef CONFIG_SPI_FLASH_MACRONIX -static int spi_flash_set_qeb_mxic(struct spi_flash *flash) -{ - u8 qeb_status; - int ret; - - ret = spi_flash_cmd_read_status(flash, &qeb_status); - if (ret < 0) - return ret; - - if (qeb_status & STATUS_QEB_MXIC) { - debug("SF: mxic: QEB is already set\n"); - } else { - ret = spi_flash_cmd_write_status(flash, STATUS_QEB_MXIC); - if (ret < 0) - return ret; - } - - return ret; -} -#endif - -#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) -static int spi_flash_set_qeb_winspan(struct spi_flash *flash) -{ - u8 qeb_status; - int ret; - - ret = spi_flash_cmd_read_config(flash, &qeb_status); - if (ret < 0) - return ret; - - if (qeb_status & STATUS_QEB_WINSPAN) { - debug("SF: winspan: QEB is already set\n"); - } else { - ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN); - if (ret < 0) - return ret; - } - - return ret; -} -#endif - -static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0) -{ - switch (idcode0) { -#ifdef CONFIG_SPI_FLASH_MACRONIX - case SPI_FLASH_CFI_MFR_MACRONIX: - return spi_flash_set_qeb_mxic(flash); -#endif -#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) - case SPI_FLASH_CFI_MFR_SPANSION: - case SPI_FLASH_CFI_MFR_WINBOND: - return spi_flash_set_qeb_winspan(flash); -#endif -#ifdef CONFIG_SPI_FLASH_STMICRO - case SPI_FLASH_CFI_MFR_STMICRO: - debug("SF: QEB is volatile for %02x flash\n", idcode0); - return 0; -#endif - default: - printf("SF: Need set QEB func for %02x flash\n", idcode0); - return -1; - } -} - -#ifdef CONFIG_SPI_FLASH_BAR -static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0) -{ - u8 curr_bank = 0; - int ret; - - if (flash->size <= SPI_FLASH_16MB_BOUN) - goto bank_end; - - switch (idcode0) { - case SPI_FLASH_CFI_MFR_SPANSION: - flash->bank_read_cmd = CMD_BANKADDR_BRRD; - flash->bank_write_cmd = CMD_BANKADDR_BRWR; - default: - flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; - flash->bank_write_cmd = CMD_EXTNADDR_WREAR; - } - - ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1, - &curr_bank, 1); - if (ret) { - debug("SF: fail to read bank addr register\n"); - return ret; - } - -bank_end: - flash->bank_curr = curr_bank; - return 0; -} -#endif - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) -{ - fdt_addr_t addr; - fdt_size_t size; - int node; - - /* If there is no node, do nothing */ - node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); - if (node < 0) - return 0; - - addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); - if (addr == FDT_ADDR_T_NONE) { - debug("%s: Cannot decode address\n", __func__); - return 0; - } - - if (flash->size != size) { - debug("%s: Memory map must cover entire device\n", __func__); - return -1; - } - flash->memory_map = map_sysmem(addr, size); - - return 0; -} -#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ - -static int spi_flash_scan(struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_params *params; - u8 cmd; - u16 jedec = idcode[1] << 8 | idcode[2]; - u16 ext_jedec = idcode[3] << 8 | idcode[4]; - int ret; - - /* Validate params from spi_flash_params table */ - params = spi_flash_params_table; - for (; params->name != NULL; params++) { - if ((params->jedec >> 16) == idcode[0]) { - if ((params->jedec & 0xFFFF) == jedec) { - if (params->ext_jedec == 0) - break; - else if (params->ext_jedec == ext_jedec) - break; - } - } - } - - if (!params->name) { - printf("SF: Unsupported flash IDs: "); - printf("manuf %02x, jedec %04x, ext_jedec %04x\n", - idcode[0], jedec, ext_jedec); - return -EPROTONOSUPPORT; - } - - /* Flash powers up read-only, so clear BP# bits */ -#if defined(CONFIG_SPI_FLASH_ATMEL) || \ - defined(CONFIG_SPI_FLASH_MACRONIX) || \ - defined(CONFIG_SPI_FLASH_SST) - spi_flash_cmd_write_status(flash, 0); -#endif - - /* Assign spi data */ - flash->spi = spi; - flash->name = params->name; - flash->memory_map = spi->memory_map; - flash->dual_flash = flash->spi->option; - - /* Assign spi flash flags */ - if (params->flags & SST_WR) - flash->flags |= SNOR_F_SST_WR; - - /* Assign spi_flash ops */ -#ifndef CONFIG_DM_SPI_FLASH - flash->write = spi_flash_cmd_write_ops; -#if defined(CONFIG_SPI_FLASH_SST) - if (flash->flags & SNOR_F_SST_WR) { - if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) - flash->write = sst_write_bp; - else - flash->write = sst_write_wp; - } -#endif - flash->erase = spi_flash_cmd_erase_ops; - flash->read = spi_flash_cmd_read_ops; -#endif - - /* lock hooks are flash specific - assign them based on idcode0 */ - switch (idcode[0]) { -#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) - case SPI_FLASH_CFI_MFR_STMICRO: - case SPI_FLASH_CFI_MFR_SST: - flash->flash_lock = stm_lock; - flash->flash_unlock = stm_unlock; - flash->flash_is_locked = stm_is_locked; -#endif - break; - default: - debug("SF: Lock ops not supported for %02x flash\n", idcode[0]); - } - - /* Compute the flash size */ - flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; - /* - * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the - * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with - * the 0x4d00 Extended JEDEC code have 512b pages. All of the others - * have 256b pages. - */ - if (ext_jedec == 0x4d00) { - if ((jedec == 0x0215) || (jedec == 0x216)) - flash->page_size = 256; - else - flash->page_size = 512; - } else { - flash->page_size = 256; - } - flash->page_size <<= flash->shift; - flash->sector_size = params->sector_size << flash->shift; - flash->size = flash->sector_size * params->nr_sectors << flash->shift; -#ifdef CONFIG_SF_DUAL_FLASH - if (flash->dual_flash & SF_DUAL_STACKED_FLASH) - flash->size <<= 1; -#endif - - /* Compute erase sector and command */ - if (params->flags & SECT_4K) { - flash->erase_cmd = CMD_ERASE_4K; - flash->erase_size = 4096 << flash->shift; - } else if (params->flags & SECT_32K) { - flash->erase_cmd = CMD_ERASE_32K; - flash->erase_size = 32768 << flash->shift; - } else { - flash->erase_cmd = CMD_ERASE_64K; - flash->erase_size = flash->sector_size; - } - - /* Now erase size becomes valid sector size */ - flash->sector_size = flash->erase_size; - - /* Look for the fastest read cmd */ - cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); - if (cmd) { - cmd = spi_read_cmds_array[cmd - 1]; - flash->read_cmd = cmd; - } else { - /* Go for default supported read cmd */ - flash->read_cmd = CMD_READ_ARRAY_FAST; - } - - /* Not require to look for fastest only two write cmds yet */ - if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP) - flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; - else - /* Go for default supported write cmd */ - flash->write_cmd = CMD_PAGE_PROGRAM; - - /* Set the quad enable bit - only for quad commands */ - if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || - (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || - (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { - ret = spi_flash_set_qeb(flash, idcode[0]); - if (ret) { - debug("SF: Fail to set QEB for %02x\n", idcode[0]); - return -EINVAL; - } - } - - /* Read dummy_byte: dummy byte is determined based on the - * dummy cycles of a particular command. - * Fast commands - dummy_byte = dummy_cycles/8 - * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 - * For I/O commands except cmd[0] everything goes on no.of lines - * based on particular command but incase of fast commands except - * data all go on single line irrespective of command. - */ - switch (flash->read_cmd) { - case CMD_READ_QUAD_IO_FAST: - flash->dummy_byte = 2; - break; - case CMD_READ_ARRAY_SLOW: - flash->dummy_byte = 0; - break; - default: - flash->dummy_byte = 1; - } - -#ifdef CONFIG_SPI_FLASH_STMICRO - if (params->flags & E_FSR) - flash->flags |= SNOR_F_USE_FSR; -#endif - - /* Configure the BAR - discover bank cmds and read current bank */ -#ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_read_bank(flash, idcode[0]); - if (ret < 0) - return ret; -#endif - -#if CONFIG_IS_ENABLED(OF_CONTROL) - ret = spi_flash_decode_fdt(gd->fdt_blob, flash); - if (ret) { - debug("SF: FDT decode error\n"); - return -EINVAL; - } -#endif - -#ifndef CONFIG_SPL_BUILD - printf("SF: Detected %s with page size ", flash->name); - print_size(flash->page_size, ", erase size "); - print_size(flash->erase_size, ", total "); - print_size(flash->size, ""); - if (flash->memory_map) - printf(", mapped at %p", flash->memory_map); - puts("\n"); -#endif - -#ifndef CONFIG_SPI_FLASH_BAR - if (((flash->dual_flash == SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN)) || - ((flash->dual_flash > SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN << 1))) { - puts("SF: Warning - Only lower 16MiB accessible,"); - puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); - } -#endif - - return ret; -} - /** * spi_flash_probe_slave() - Probe for a SPI flash device on a bus *

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
Intension is that sf_ops should deals all spi_flash related stuff and sf_probe (which should renamed future) should be an interface layer for spi_flash versus spi drivers.
sf_ops => spi_flash interface sf_probe => interface layer vs spi_flash(sf_probe) to spi drivers
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_internal.h | 14 ++ drivers/mtd/spi/sf_ops.c | 343 ++++++++++++++++++++++++++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 342 ----------------------------------------- 3 files changed, 357 insertions(+), 342 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

read_id code is related to spi_flash stuff hence moved to sf_ops.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 3 +-- drivers/mtd/spi/sf_ops.c | 21 ++++++++++++++++++--- drivers/mtd/spi/sf_probe.c | 15 +-------------- 3 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index f3eb6f3..670429f 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -248,7 +248,6 @@ void spi_flash_mtd_unregister(void); /** * spi_flash_scan - scan the SPI FLASH * @spi: the spi slave structure - * @idcode: idcode of spi flash * @flash: the spi flash structure * * The drivers can use this fuction to scan the SPI FLASH. @@ -257,6 +256,6 @@ void spi_flash_mtd_unregister(void); * * Return: 0 for success, others for failure. */ -int spi_flash_scan(struct spi_slave *spi, u8 *idcode, struct spi_flash *flash); +int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash);
#endif /* _SF_INTERNAL_H_ */ diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 306db8f..54c6468 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -898,14 +898,29 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) } #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
-int spi_flash_scan(struct spi_slave *spi, u8 *idcode, struct spi_flash *flash) +int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) { const struct spi_flash_params *params; + u16 jedec, ext_jedec; + u8 idcode[5]; u8 cmd; - u16 jedec = idcode[1] << 8 | idcode[2]; - u16 ext_jedec = idcode[3] << 8 | idcode[4]; int ret;
+ /* Read the ID codes */ + ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); + if (ret) { + printf("SF: Failed to get idcodes\n"); + return -EINVAL; + } + +#ifdef DEBUG + printf("SF: Got idcodes\n"); + print_buffer(0, idcode, 1, sizeof(idcode), 0); +#endif + + jedec = idcode[1] << 8 | idcode[2]; + ext_jedec = idcode[3] << 8 | idcode[4]; + /* Validate params from spi_flash_params table */ params = spi_flash_params_table; for (; params->name != NULL; params++) { diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 994559d..e35b917 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -29,7 +29,6 @@ */ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) { - u8 idcode[5]; int ret;
/* Setup spi_slave */ @@ -45,19 +44,7 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) return ret; }
- /* Read the ID codes */ - ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); - if (ret) { - printf("SF: Failed to get idcodes\n"); - goto err_read_id; - } - -#ifdef DEBUG - printf("SF: Got idcodes\n"); - print_buffer(0, idcode, 1, sizeof(idcode), 0); -#endif - - ret = spi_flash_scan(spi, idcode, flash); + ret = spi_flash_scan(spi, flash); if (ret) { ret = -EINVAL; goto err_read_id;

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
read_id code is related to spi_flash stuff hence moved to sf_ops.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_internal.h | 3 +-- drivers/mtd/spi/sf_ops.c | 21 ++++++++++++++++++--- drivers/mtd/spi/sf_probe.c | 15 +-------------- 3 files changed, 20 insertions(+), 19 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

- Move bar read code below the bar write hance both at once place, hence it easy for #ifdef macro only once and readable. - Move read_cmd_array at top
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 80 +++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 41 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 54c6468..8d6040e 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -30,6 +30,16 @@ static void spi_flash_addr(u32 addr, u8 *cmd) cmd[3] = addr >> 0; }
+/* Read commands array */ +static u8 spi_read_cmds_array[] = { + CMD_READ_ARRAY_SLOW, + CMD_READ_ARRAY_FAST, + CMD_READ_DUAL_OUTPUT_FAST, + CMD_READ_DUAL_IO_FAST, + CMD_READ_QUAD_OUTPUT_FAST, + CMD_READ_QUAD_IO_FAST, +}; + int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs) { int ret; @@ -133,6 +143,35 @@ bar_end: flash->bank_curr = bank_sel; return flash->bank_curr; } + +static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0) +{ + u8 curr_bank = 0; + int ret; + + if (flash->size <= SPI_FLASH_16MB_BOUN) + goto bank_end; + + switch (idcode0) { + case SPI_FLASH_CFI_MFR_SPANSION: + flash->bank_read_cmd = CMD_BANKADDR_BRRD; + flash->bank_write_cmd = CMD_BANKADDR_BRWR; + default: + flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; + flash->bank_write_cmd = CMD_EXTNADDR_WREAR; + } + + ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1, + &curr_bank, 1); + if (ret) { + debug("SF: fail to read bank addr register\n"); + return ret; + } + +bank_end: + flash->bank_curr = curr_bank; + return 0; +} #endif
#ifdef CONFIG_SF_DUAL_FLASH @@ -762,16 +801,6 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) #endif
-/* Read commands array */ -static u8 spi_read_cmds_array[] = { - CMD_READ_ARRAY_SLOW, - CMD_READ_ARRAY_FAST, - CMD_READ_DUAL_OUTPUT_FAST, - CMD_READ_DUAL_IO_FAST, - CMD_READ_QUAD_OUTPUT_FAST, - CMD_READ_QUAD_IO_FAST, -}; - #ifdef CONFIG_SPI_FLASH_MACRONIX static int spi_flash_set_qeb_mxic(struct spi_flash *flash) { @@ -839,37 +868,6 @@ static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0) } }
-#ifdef CONFIG_SPI_FLASH_BAR -static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0) -{ - u8 curr_bank = 0; - int ret; - - if (flash->size <= SPI_FLASH_16MB_BOUN) - goto bank_end; - - switch (idcode0) { - case SPI_FLASH_CFI_MFR_SPANSION: - flash->bank_read_cmd = CMD_BANKADDR_BRRD; - flash->bank_write_cmd = CMD_BANKADDR_BRWR; - default: - flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; - flash->bank_write_cmd = CMD_EXTNADDR_WREAR; - } - - ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1, - &curr_bank, 1); - if (ret) { - debug("SF: fail to read bank addr register\n"); - return ret; - } - -bank_end: - flash->bank_curr = curr_bank; - return 0; -} -#endif - #if CONFIG_IS_ENABLED(OF_CONTROL) int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) {

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
- Move bar read code below the bar write hance both at once place, hence it easy for #ifdef macro only once and readable.
- Move read_cmd_array at top
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_ops.c | 80 +++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 41 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Use static for file-scope functions and removed them from header files.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 18 ------------------ drivers/mtd/spi/sf_ops.c | 11 ++++++----- 2 files changed, 6 insertions(+), 23 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 670429f..8f586ee 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -171,12 +171,6 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, /* Flash erase(sectors) operation, support all possible erase commands */ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
-/* Read the status register */ -int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs); - -/* Program the status register */ -int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws); - /* Lock stmicro spi flash region */ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len);
@@ -186,12 +180,6 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); /* Check if a stmicro spi flash region is completely locked */ int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len);
-/* Read the config register */ -int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc); - -/* Program the config register */ -int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc); - /* Enable writing on the SPI flash */ static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) { @@ -205,12 +193,6 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) }
/* - * Send the read status command to the device and wait for the wip - * (write-in-progress) bit to clear itself. - */ -int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); - -/* * Used for spi_flash write operation * - SPI claim * - spi_flash_cmd_write_enable diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 8d6040e..23a6adb 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -40,7 +40,7 @@ static u8 spi_read_cmds_array[] = { CMD_READ_QUAD_IO_FAST, };
-int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs) +static int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs) { int ret; u8 cmd; @@ -69,7 +69,7 @@ static int read_fsr(struct spi_flash *flash, u8 *fsr) return 0; }
-int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) +static int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) { u8 cmd; int ret; @@ -85,7 +85,7 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) }
#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) -int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc) +static int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc) { int ret; u8 cmd; @@ -100,7 +100,7 @@ int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc) return 0; }
-int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc) +static int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc) { u8 data[2]; u8 cmd; @@ -238,7 +238,8 @@ static int spi_flash_ready(struct spi_flash *flash) return sr && fsr; }
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) +static int spi_flash_cmd_wait_ready(struct spi_flash *flash, + unsigned long timeout) { int timebase, ret;

This patch removes unneeded ifdef and fixed accordingly.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index cf4e7e1..a24f761 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -12,11 +12,7 @@ obj-$(CONFIG_SPL_SPI_LOAD) += spi_spl_load.o obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o endif
-#ifndef CONFIG_DM_SPI -obj-$(CONFIG_SPI_FLASH) += sf_probe.o -#endif -obj-$(CONFIG_CMD_SF) += sf.o -obj-$(CONFIG_SPI_FLASH) += sf_ops.o sf_params.o +obj-$(CONFIG_SPI_FLASH) += sf_probe.o sf_ops.o sf_params.o sf.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
This patch removes unneeded ifdef and fixed accordingly.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Thu, Nov 26, 2015 at 8:03 PM, Jagan Teki jteki@openedev.com wrote:
This patch removes unneeded ifdef and fixed accordingly.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index cf4e7e1..a24f761 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -12,11 +12,7 @@ obj-$(CONFIG_SPL_SPI_LOAD) += spi_spl_load.o obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o endif
-#ifndef CONFIG_DM_SPI -obj-$(CONFIG_SPI_FLASH) += sf_probe.o -#endif -obj-$(CONFIG_CMD_SF) += sf.o -obj-$(CONFIG_SPI_FLASH) += sf_ops.o sf_params.o +obj-$(CONFIG_SPI_FLASH) += sf_probe.o sf_ops.o sf_params.o sf.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o --
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Most of the register access function are static, so used simple name to represent each.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 23a6adb..853759e 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -40,7 +40,7 @@ static u8 spi_read_cmds_array[] = { CMD_READ_QUAD_IO_FAST, };
-static int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs) +static int read_sr(struct spi_flash *flash, u8 *rs) { int ret; u8 cmd; @@ -69,7 +69,7 @@ static int read_fsr(struct spi_flash *flash, u8 *fsr) return 0; }
-static int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) +static int write_sr(struct spi_flash *flash, u8 ws) { u8 cmd; int ret; @@ -85,7 +85,7 @@ static int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) }
#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) -static int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc) +static int read_cr(struct spi_flash *flash, u8 *rc) { int ret; u8 cmd; @@ -100,13 +100,13 @@ static int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc) return 0; }
-static int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc) +static int write_cr(struct spi_flash *flash, u8 wc) { u8 data[2]; u8 cmd; int ret;
- ret = spi_flash_cmd_read_status(flash, &data[0]); + ret = read_sr(flash, &data[0]); if (ret < 0) return ret;
@@ -123,7 +123,7 @@ static int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc) #endif
#ifdef CONFIG_SPI_FLASH_BAR -static int spi_flash_write_bank(struct spi_flash *flash, u32 offset) +static int spi_flash_write_bar(struct spi_flash *flash, u32 offset) { u8 cmd, bank_sel; int ret; @@ -144,7 +144,7 @@ bar_end: return flash->bank_curr; }
-static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0) +static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0) { u8 curr_bank = 0; int ret; @@ -175,7 +175,7 @@ bank_end: #endif
#ifdef CONFIG_SF_DUAL_FLASH -static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr) +static void spi_flash_dual(struct spi_flash *flash, u32 *addr) { switch (flash->dual_flash) { case SF_DUAL_STACKED_FLASH: @@ -201,7 +201,7 @@ static int spi_flash_sr_ready(struct spi_flash *flash) u8 sr; int ret;
- ret = spi_flash_cmd_read_status(flash, &sr); + ret = read_sr(flash, &sr); if (ret < 0) return ret;
@@ -325,10 +325,10 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
#ifdef CONFIG_SF_DUAL_FLASH if (flash->dual_flash > SF_SINGLE_FLASH) - spi_flash_dual_flash(flash, &erase_addr); + spi_flash_dual(flash, &erase_addr); #endif #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bank(flash, erase_addr); + ret = spi_flash_write_bar(flash, erase_addr); if (ret < 0) return ret; #endif @@ -375,10 +375,10 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
#ifdef CONFIG_SF_DUAL_FLASH if (flash->dual_flash > SF_SINGLE_FLASH) - spi_flash_dual_flash(flash, &write_addr); + spi_flash_dual(flash, &write_addr); #endif #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bank(flash, write_addr); + ret = spi_flash_write_bar(flash, write_addr); if (ret < 0) return ret; #endif @@ -470,10 +470,10 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
#ifdef CONFIG_SF_DUAL_FLASH if (flash->dual_flash > SF_SINGLE_FLASH) - spi_flash_dual_flash(flash, &read_addr); + spi_flash_dual(flash, &read_addr); #endif #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bank(flash, read_addr); + ret = spi_flash_write_bar(flash, read_addr); if (ret < 0) return ret; bank_sel = flash->bank_curr; @@ -671,7 +671,7 @@ int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len) int status; u8 sr;
- status = spi_flash_cmd_read_status(flash, &sr); + status = read_sr(flash, &sr); if (status < 0) return status;
@@ -708,7 +708,7 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) u8 shift = ffs(mask) - 1, pow, val; int ret;
- ret = spi_flash_cmd_read_status(flash, &status_old); + ret = read_sr(flash, &status_old); if (ret < 0) return ret;
@@ -745,7 +745,7 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) if ((status_new & mask) <= (status_old & mask)) return -EINVAL;
- spi_flash_cmd_write_status(flash, status_new); + write_sr(flash, status_new);
return 0; } @@ -762,7 +762,7 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) u8 shift = ffs(mask) - 1, pow, val; int ret;
- ret = spi_flash_cmd_read_status(flash, &status_old); + ret = read_sr(flash, &status_old); if (ret < 0) return ret;
@@ -795,7 +795,7 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) if ((status_new & mask) >= (status_old & mask)) return -EINVAL;
- spi_flash_cmd_write_status(flash, status_new); + write_sr(flash, status_new);
return 0; } @@ -808,14 +808,14 @@ static int spi_flash_set_qeb_mxic(struct spi_flash *flash) u8 qeb_status; int ret;
- ret = spi_flash_cmd_read_status(flash, &qeb_status); + ret = read_sr(flash, &qeb_status); if (ret < 0) return ret;
if (qeb_status & STATUS_QEB_MXIC) { debug("SF: mxic: QEB is already set\n"); } else { - ret = spi_flash_cmd_write_status(flash, STATUS_QEB_MXIC); + ret = write_sr(flash, STATUS_QEB_MXIC); if (ret < 0) return ret; } @@ -830,14 +830,14 @@ static int spi_flash_set_qeb_winspan(struct spi_flash *flash) u8 qeb_status; int ret;
- ret = spi_flash_cmd_read_config(flash, &qeb_status); + ret = read_cr(flash, &qeb_status); if (ret < 0) return ret;
if (qeb_status & STATUS_QEB_WINSPAN) { debug("SF: winspan: QEB is already set\n"); } else { - ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN); + ret = write_cr(flash, STATUS_QEB_WINSPAN); if (ret < 0) return ret; } @@ -944,7 +944,7 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) #if defined(CONFIG_SPI_FLASH_ATMEL) || \ defined(CONFIG_SPI_FLASH_MACRONIX) || \ defined(CONFIG_SPI_FLASH_SST) - spi_flash_cmd_write_status(flash, 0); + write_sr(flash, 0); #endif
/* Assign spi data */ @@ -1079,7 +1079,7 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash)
/* Configure the BAR - discover bank cmds and read current bank */ #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_read_bank(flash, idcode[0]); + ret = spi_flash_read_bar(flash, idcode[0]); if (ret < 0) return ret; #endif

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
Most of the register access function are static, so used simple name to represent each.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_ops.c | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

flash operations are defined as static and reuse them with function-pointers so call them with generic function pounters instead of calling like normal functions.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 2 -- drivers/mtd/spi/sf_probe.c | 15 +++------------ include/spi_flash.h | 13 ------------- 3 files changed, 3 insertions(+), 27 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 853759e..ab21f02 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -958,7 +958,6 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) flash->flags |= SNOR_F_SST_WR;
/* Assign spi_flash ops */ -#ifndef CONFIG_DM_SPI_FLASH flash->write = spi_flash_cmd_write_ops; #if defined(CONFIG_SPI_FLASH_SST) if (flash->flags & SNOR_F_SST_WR) { @@ -970,7 +969,6 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) #endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops; -#endif
/* lock hooks are flash specific - assign them based on idcode0 */ switch (idcode[0]) { diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index e35b917..678b81c 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -120,7 +120,7 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev);
- return spi_flash_cmd_read_ops(flash, offset, len, buf); + return flash->read(flash, offset, len, buf); }
int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, @@ -128,23 +128,14 @@ int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev);
-#if defined(CONFIG_SPI_FLASH_SST) - if (flash->flags & SNOR_F_SST_WR) { - if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) - return sst_write_bp(flash, offset, len, buf); - else - return sst_write_wp(flash, offset, len, buf); - } -#endif - - return spi_flash_cmd_write_ops(flash, offset, len, buf); + return flash->write(flash, offset, len, buf); }
int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) { struct spi_flash *flash = dev_get_uclass_priv(dev);
- return spi_flash_cmd_erase_ops(flash, offset, len); + return flash->erase(flash, offset, len); }
int spi_flash_std_probe(struct udevice *dev) diff --git a/include/spi_flash.h b/include/spi_flash.h index f25b3e7..721b358 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -94,23 +94,10 @@ struct spi_flash { int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); -#ifndef CONFIG_DM_SPI_FLASH - /* - * These are not strictly needed for driver model, but keep them here - * while the transition is in progress. - * - * Normally each driver would provide its own operations, but for - * SPI flash most chips use the same algorithms. One approach is - * to create a 'common' SPI flash device which knows how to talk - * to most devices, and then allow other drivers to be used instead - * if required, perhaps with a way of scanning through the list to - * find the driver that matches the device. - */ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); int (*write)(struct spi_flash *flash, u32 offset, size_t len, const void *buf); int (*erase)(struct spi_flash *flash, u32 offset, size_t len); -#endif };
struct dm_spi_flash_ops {

Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
flash operations are defined as static and reuse them with function-pointers so call them with generic function pounters instead of calling like normal functions.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_ops.c | 2 -- drivers/mtd/spi/sf_probe.c | 15 +++------------ include/spi_flash.h | 13 ------------- 3 files changed, 3 insertions(+), 27 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 853759e..ab21f02 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -958,7 +958,6 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) flash->flags |= SNOR_F_SST_WR;
/* Assign spi_flash ops */
-#ifndef CONFIG_DM_SPI_FLASH flash->write = spi_flash_cmd_write_ops; #if defined(CONFIG_SPI_FLASH_SST) if (flash->flags & SNOR_F_SST_WR) { @@ -970,7 +969,6 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) #endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops; -#endif
/* lock hooks are flash specific - assign them based on idcode0 */ switch (idcode[0]) {
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index e35b917..678b81c 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -120,7 +120,7 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev);
return spi_flash_cmd_read_ops(flash, offset, len, buf);
return flash->read(flash, offset, len, buf);
}
int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, @@ -128,23 +128,14 @@ int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev);
-#if defined(CONFIG_SPI_FLASH_SST)
if (flash->flags & SNOR_F_SST_WR) {
if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
return sst_write_bp(flash, offset, len, buf);
else
return sst_write_wp(flash, offset, len, buf);
}
-#endif
return spi_flash_cmd_write_ops(flash, offset, len, buf);
return flash->write(flash, offset, len, buf);
}
int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) { struct spi_flash *flash = dev_get_uclass_priv(dev);
return spi_flash_cmd_erase_ops(flash, offset, len);
return flash->erase(flash, offset, len);
}
int spi_flash_std_probe(struct udevice *dev) diff --git a/include/spi_flash.h b/include/spi_flash.h index f25b3e7..721b358 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -94,23 +94,10 @@ struct spi_flash { int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); -#ifndef CONFIG_DM_SPI_FLASH
/*
* These are not strictly needed for driver model, but keep them here
* while the transition is in progress.
*
* Normally each driver would provide its own operations, but for
* SPI flash most chips use the same algorithms. One approach is
* to create a 'common' SPI flash device which knows how to talk
* to most devices, and then allow other drivers to be used instead
* if required, perhaps with a way of scanning through the list to
* find the driver that matches the device.
*/ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); int (*write)(struct spi_flash *flash, u32 offset, size_t len, const void *buf); int (*erase)(struct spi_flash *flash, u32 offset, size_t len);
-#endif
No this should go the other way. The flash_...() methods introduced above should be removed with driver model.
If we don't move things forward towards driver model for all platforms we are going to create a fork.
};
struct dm_spi_flash_ops {
1.9.1
Regards, Simon

Hi Simon,
On 26 November 2015 at 23:20, Simon Glass sjg@chromium.org wrote:
Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
flash operations are defined as static and reuse them with function-pointers so call them with generic function pounters instead of calling like normal functions.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_ops.c | 2 -- drivers/mtd/spi/sf_probe.c | 15 +++------------ include/spi_flash.h | 13 ------------- 3 files changed, 3 insertions(+), 27 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 853759e..ab21f02 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -958,7 +958,6 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) flash->flags |= SNOR_F_SST_WR;
/* Assign spi_flash ops */
-#ifndef CONFIG_DM_SPI_FLASH flash->write = spi_flash_cmd_write_ops; #if defined(CONFIG_SPI_FLASH_SST) if (flash->flags & SNOR_F_SST_WR) { @@ -970,7 +969,6 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) #endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops; -#endif
/* lock hooks are flash specific - assign them based on idcode0 */ switch (idcode[0]) {
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index e35b917..678b81c 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -120,7 +120,7 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev);
return spi_flash_cmd_read_ops(flash, offset, len, buf);
return flash->read(flash, offset, len, buf);
}
int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, @@ -128,23 +128,14 @@ int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev);
-#if defined(CONFIG_SPI_FLASH_SST)
if (flash->flags & SNOR_F_SST_WR) {
if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
return sst_write_bp(flash, offset, len, buf);
else
return sst_write_wp(flash, offset, len, buf);
}
-#endif
return spi_flash_cmd_write_ops(flash, offset, len, buf);
return flash->write(flash, offset, len, buf);
}
int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) { struct spi_flash *flash = dev_get_uclass_priv(dev);
return spi_flash_cmd_erase_ops(flash, offset, len);
return flash->erase(flash, offset, len);
}
int spi_flash_std_probe(struct udevice *dev) diff --git a/include/spi_flash.h b/include/spi_flash.h index f25b3e7..721b358 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -94,23 +94,10 @@ struct spi_flash { int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); -#ifndef CONFIG_DM_SPI_FLASH
/*
* These are not strictly needed for driver model, but keep them here
* while the transition is in progress.
*
* Normally each driver would provide its own operations, but for
* SPI flash most chips use the same algorithms. One approach is
* to create a 'common' SPI flash device which knows how to talk
* to most devices, and then allow other drivers to be used instead
* if required, perhaps with a way of scanning through the list to
* find the driver that matches the device.
*/ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); int (*write)(struct spi_flash *flash, u32 offset, size_t len, const void *buf); int (*erase)(struct spi_flash *flash, u32 offset, size_t len);
-#endif
No this should go the other way. The flash_...() methods introduced above should be removed with driver model.
The lock methods above flash_..() are common to both dm and non-dm there is no separate lock ops for dm now.
If we don't move things forward towards driver model for all platforms we are going to create a fork.
};
struct dm_spi_flash_ops {
thanks!

Using macro's for flash power up read-only access code leads wrong behaviour hence use idcode0 for runtime detection, hence the flash which require this functionality gets detected at runtime.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 1 + drivers/mtd/spi/sf_ops.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 8f586ee..b8692c6 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -66,6 +66,7 @@ enum spi_nor_option_flags { #define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 #define SPI_FLASH_CFI_MFR_SST 0xbf #define SPI_FLASH_CFI_MFR_WINBOND 0xef +#define SPI_FLASH_CFI_MFR_ATMEL 0x1f
/* Erase commands */ #define CMD_ERASE_4K 0x20 diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index ab21f02..80eac39 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -941,11 +941,10 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) }
/* Flash powers up read-only, so clear BP# bits */ -#if defined(CONFIG_SPI_FLASH_ATMEL) || \ - defined(CONFIG_SPI_FLASH_MACRONIX) || \ - defined(CONFIG_SPI_FLASH_SST) + if (idcode[0] == SPI_FLASH_CFI_MFR_ATMEL || + idcode[0] == SPI_FLASH_CFI_MFR_MACRONIX || + idcode[0] == SPI_FLASH_CFI_MFR_SST) write_sr(flash, 0); -#endif
/* Assign spi data */ flash->spi = spi;

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
Using macro's for flash power up read-only access code leads wrong behaviour hence use idcode0 for runtime detection, hence the flash which require this functionality gets detected at runtime.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_internal.h | 1 + drivers/mtd/spi/sf_ops.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Use static for file-scope functions and removed them from header files.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 21 --------------------- drivers/mtd/spi/sf_ops.c | 11 ++++++----- 2 files changed, 6 insertions(+), 26 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index b8692c6..acf76e1 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -120,11 +120,6 @@ enum spi_nor_option_flags { #ifdef CONFIG_SPI_FLASH_SST # define CMD_SST_BP 0x02 /* Byte Program */ # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ - -int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); -int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); #endif
/** @@ -168,10 +163,6 @@ int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const void *data, size_t data_len);
- -/* Flash erase(sectors) operation, support all possible erase commands */ -int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); - /* Lock stmicro spi flash region */ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len);
@@ -205,24 +196,12 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, const void *buf, size_t buf_len);
/* - * Flash write operation, support all possible write commands. - * Write the requested data out breaking it up into multiple write - * commands as needed per the write size. - */ -int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, - size_t len, const void *buf); - -/* * Same as spi_flash_cmd_read() except it also claims/releases the SPI * bus. Used as common part of the ->read() operation. */ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, void *data, size_t data_len);
-/* Flash read operation, support all possible read commands */ -int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, - size_t len, void *data); - #ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register(struct spi_flash *flash); void spi_flash_mtd_unregister(void); diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 80eac39..2e6b25e 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -299,7 +299,8 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, return ret; }
-int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) +static int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, + size_t len) { u32 erase_size, erase_addr; u8 cmd[SPI_FLASH_CMD_LEN]; @@ -350,7 +351,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) return ret; }
-int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, +static int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { unsigned long byte_addr, page_size; @@ -435,7 +436,7 @@ void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len) memcpy(data, offset, len); }
-int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, +static int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, size_t len, void *data) { u8 *cmd, cmdsz; @@ -527,7 +528,7 @@ static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); }
-int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, +static int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { size_t actual, cmd_len; @@ -594,7 +595,7 @@ int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, return ret; }
-int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, +static int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { size_t actual;

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
Use static for file-scope functions and removed them from header files.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_internal.h | 21 --------------------- drivers/mtd/spi/sf_ops.c | 11 ++++++----- 2 files changed, 6 insertions(+), 26 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Removed unneeded header includes in sf_ops and sf_probe
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 2 -- drivers/mtd/spi/sf_probe.c | 3 --- 2 files changed, 5 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 2e6b25e..1ee8a7c 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -14,8 +14,6 @@ #include <mapmem.h> #include <spi.h> #include <spi_flash.h> -#include <watchdog.h> -#include <linux/compiler.h> #include <linux/log2.h>
#include "sf_internal.h" diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 678b81c..f2e210d 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -11,12 +11,9 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <fdtdec.h> #include <malloc.h> -#include <mapmem.h> #include <spi.h> #include <spi_flash.h> -#include <asm/io.h>
#include "sf_internal.h"

On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
Removed unneeded header includes in sf_ops and sf_probe
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_ops.c | 2 -- drivers/mtd/spi/sf_probe.c | 3 --- 2 files changed, 5 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

This patch add support to use spi_flash_scan in dm-spi-flash probe, so-that it can access the spi_flash functionalities same as non-dm sf probe.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_probe.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index f2e210d..60856f9 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -137,14 +137,36 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
int spi_flash_std_probe(struct udevice *dev) { - struct spi_slave *slave = dev_get_parent_priv(dev); struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); struct spi_flash *flash; + int ret; + + debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
flash = dev_get_uclass_priv(dev); flash->dev = dev; - debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); - return spi_flash_probe_slave(slave, flash); + + /* Claim spi bus */ + ret = spi_claim_bus(slave); + if (ret) { + debug("SF: Failed to claim SPI bus: %d\n", ret); + return ret; + } + + ret = spi_flash_scan(slave, flash); + if (ret) { + ret = -EINVAL; + goto err_read_id; + } + +#ifdef CONFIG_SPI_FLASH_MTD + ret = spi_flash_mtd_register(flash); +#endif + +err_read_id: + spi_release_bus(slave); + return ret; }
static const struct dm_spi_flash_ops spi_flash_std_ops = {

Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
This patch add support to use spi_flash_scan in dm-spi-flash probe, so-that it can access the spi_flash functionalities same as non-dm sf probe.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_probe.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index f2e210d..60856f9 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -137,14 +137,36 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
int spi_flash_std_probe(struct udevice *dev) {
struct spi_slave *slave = dev_get_parent_priv(dev); struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
struct spi_slave *slave = dev_get_parent_priv(dev); struct spi_flash *flash;
int ret;
debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); flash = dev_get_uclass_priv(dev); flash->dev = dev;
debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
return spi_flash_probe_slave(slave, flash);
/* Claim spi bus */
ret = spi_claim_bus(slave);
if (ret) {
debug("SF: Failed to claim SPI bus: %d\n", ret);
return ret;
}
ret = spi_flash_scan(slave, flash);
if (ret) {
ret = -EINVAL;
goto err_read_id;
}
+#ifdef CONFIG_SPI_FLASH_MTD
ret = spi_flash_mtd_register(flash);
+#endif
But you can't call this from driver model code. As far as I can see the MTD layer does not support driver model. You are going to create a plate of spaghetti and it will be a big job to untangle it.
+err_read_id:
spi_release_bus(slave);
return ret;
}
static const struct dm_spi_flash_ops spi_flash_std_ops = {
1.9.1
Regards, Simon

Hi Simon,
On 26 November 2015 at 23:20, Simon Glass sjg@chromium.org wrote:
Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
This patch add support to use spi_flash_scan in dm-spi-flash probe, so-that it can access the spi_flash functionalities same as non-dm sf probe.
Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_probe.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index f2e210d..60856f9 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -137,14 +137,36 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
int spi_flash_std_probe(struct udevice *dev) {
struct spi_slave *slave = dev_get_parent_priv(dev); struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
struct spi_slave *slave = dev_get_parent_priv(dev); struct spi_flash *flash;
int ret;
debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); flash = dev_get_uclass_priv(dev); flash->dev = dev;
debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
return spi_flash_probe_slave(slave, flash);
/* Claim spi bus */
ret = spi_claim_bus(slave);
if (ret) {
debug("SF: Failed to claim SPI bus: %d\n", ret);
return ret;
}
ret = spi_flash_scan(slave, flash);
if (ret) {
ret = -EINVAL;
goto err_read_id;
}
+#ifdef CONFIG_SPI_FLASH_MTD
ret = spi_flash_mtd_register(flash);
+#endif
But you can't call this from driver model code. As far as I can see the MTD layer does not support driver model. You are going to create a plate of spaghetti and it will be a big job to untangle it.
This call is same as before, SPI_FLASH_MTD is not exactly a MTD core it's an internal mtd driver for sf that in turn call mtd core and anyway this will replaced with add_mtd_device coming patches.
And why can't we call mtd from here? because mtd core requires fill mtd structure form respective flash layers like sf, nand and cfi.
+err_read_id:
spi_release_bus(slave);
return ret;
}
static const struct dm_spi_flash_ops spi_flash_std_ops = {
1.9.1
thanks!

spi_flash_probe_tail code looks not in proper shape to add more functionalities. hence refactorized so-that it's more readable and hence we may extend more functionalies to it.
Cc: Bin Meng bmeng.cn@gmail.com Cc: Troy Kisky troy.kisky@boundarydevices.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 3 +- drivers/mtd/spi/sf_ops.c | 7 ++-- drivers/mtd/spi/sf_probe.c | 74 ++++++++++++++++++------------------------- 3 files changed, 34 insertions(+), 50 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index acf76e1..fda49e9 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -209,7 +209,6 @@ void spi_flash_mtd_unregister(void);
/** * spi_flash_scan - scan the SPI FLASH - * @spi: the spi slave structure * @flash: the spi flash structure * * The drivers can use this fuction to scan the SPI FLASH. @@ -218,6 +217,6 @@ void spi_flash_mtd_unregister(void); * * Return: 0 for success, others for failure. */ -int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash); +int spi_flash_scan(struct spi_flash *flash);
#endif /* _SF_INTERNAL_H_ */ diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 1ee8a7c..3705534 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -896,7 +896,7 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) } #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
-int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) +int spi_flash_scan(struct spi_flash *flash) { const struct spi_flash_params *params; u16 jedec, ext_jedec; @@ -905,7 +905,7 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) int ret;
/* Read the ID codes */ - ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); + ret = spi_flash_cmd(flash->spi, CMD_READ_ID, idcode, sizeof(idcode)); if (ret) { printf("SF: Failed to get idcodes\n"); return -EINVAL; @@ -946,9 +946,8 @@ int spi_flash_scan(struct spi_slave *spi, struct spi_flash *flash) write_sr(flash, 0);
/* Assign spi data */ - flash->spi = spi; flash->name = params->name; - flash->memory_map = spi->memory_map; + flash->memory_map = flash->spi->memory_map; flash->dual_flash = flash->spi->option;
/* Assign spi flash flags */ diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 60856f9..ea24fa0 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -17,49 +17,11 @@
#include "sf_internal.h"
-/** - * spi_flash_probe_slave() - Probe for a SPI flash device on a bus - * - * @spi: Bus to probe - * @flashp: Pointer to place to put flash info, which may be NULL if the - * space should be allocated - */ -int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) -{ - int ret; - - /* Setup spi_slave */ - if (!spi) { - printf("SF: Failed to set up slave\n"); - return -ENODEV; - } - - /* Claim spi bus */ - ret = spi_claim_bus(spi); - if (ret) { - debug("SF: Failed to claim SPI bus: %d\n", ret); - return ret; - } - - ret = spi_flash_scan(spi, flash); - if (ret) { - ret = -EINVAL; - goto err_read_id; - } - -#ifdef CONFIG_SPI_FLASH_MTD - ret = spi_flash_mtd_register(flash); -#endif - -err_read_id: - spi_release_bus(spi); - return ret; -} - #ifndef CONFIG_DM_SPI_FLASH struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) { struct spi_flash *flash; + int ret;
/* Allocate space if needed (not used by sf-uclass */ flash = calloc(1, sizeof(*flash)); @@ -68,13 +30,37 @@ struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) return NULL; }
- if (spi_flash_probe_slave(bus, flash)) { - spi_free_slave(bus); - free(flash); - return NULL; + flash->spi = bus; + + /* Claim spi bus */ + ret = spi_claim_bus(bus); + if (ret) { + debug("SF: Failed to claim SPI bus: %d\n", ret); + goto err_claim; }
+ ret = spi_flash_scan(flash); + if (ret) + goto err_scan; + +#ifdef CONFIG_SPI_FLASH_MTD + ret = spi_flash_mtd_register(flash); + if (ret) { + printf("SF: failed to register mtd device: %d\n", ret); + goto err_mtd; + } +#endif return flash; + +#ifdef CONFIG_SPI_FLASH_MTD +err_mtd: + spi_free_slave(bus); +#endif +err_scan: + spi_release_bus(bus); +err_claim: + free(flash); + return NULL; }
struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, @@ -154,7 +140,7 @@ int spi_flash_std_probe(struct udevice *dev) return ret; }
- ret = spi_flash_scan(slave, flash); + ret = spi_flash_scan(flash); if (ret) { ret = -EINVAL; goto err_read_id;

Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
spi_flash_probe_tail code looks not in proper shape to add more functionalities. hence refactorized so-that it's more readable and hence we may extend more functionalies to it.
Cc: Bin Meng bmeng.cn@gmail.com Cc: Troy Kisky troy.kisky@boundarydevices.com Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_internal.h | 3 +- drivers/mtd/spi/sf_ops.c | 7 ++-- drivers/mtd/spi/sf_probe.c | 74 ++++++++++++++++++------------------------- 3 files changed, 34 insertions(+), 50 deletions(-)
This relies on the early patch which I believe is not a good plan.
From what I can see the SPI MTD code does not support driver model, so
that should be sorted out first.
- Simon

spi_flash_probe_tail code looks not in proper shape to add more functionalities. hence refactorized so-that it's more readable and hence we may extend more functionalies to it.
Cc: Bin Meng bmeng.cn@gmail.com Cc: Troy Kisky troy.kisky@boundarydevices.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_probe.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index ea24fa0..603c6bc 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -123,15 +123,12 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
int spi_flash_std_probe(struct udevice *dev) { - struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); + struct spi_flash *flash = dev_get_uclass_priv(dev); struct spi_slave *slave = dev_get_parent_priv(dev); - struct spi_flash *flash; int ret;
- debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); - - flash = dev_get_uclass_priv(dev); flash->dev = dev; + flash->spi = slave;
/* Claim spi bus */ ret = spi_claim_bus(slave); @@ -143,14 +140,23 @@ int spi_flash_std_probe(struct udevice *dev) ret = spi_flash_scan(flash); if (ret) { ret = -EINVAL; - goto err_read_id; + goto err_scan; }
#ifdef CONFIG_SPI_FLASH_MTD ret = spi_flash_mtd_register(flash); + if (ret) { + printf("SF: failed to register mtd device: %d\n", ret); + goto err_mtd; + } #endif + return ret;
-err_read_id: +#ifdef CONFIG_SPI_FLASH_MTD +err_mtd: + spi_free_slave(slave); +#endif +err_scan: spi_release_bus(slave); return ret; }

Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
spi_flash_probe_tail code looks not in proper shape to add more functionalities. hence refactorized so-that it's more readable and hence we may extend more functionalies to it.
Cc: Bin Meng bmeng.cn@gmail.com Cc: Troy Kisky troy.kisky@boundarydevices.com Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_probe.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
This patch relies on early changes which I think are not good.
Regards, Simon

Add SPL_MTD_SUPPORT to ZYNQ_QSPI SPL.
Cc: Michal Simek michal.simek@xilinx.com Signed-off-by: Jagan Teki jteki@openedev.com --- include/configs/zynq-common.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h index fa83ac7..a54fa26 100644 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -354,6 +354,7 @@
/* qspi mode is working fine */ #ifdef CONFIG_ZYNQ_QSPI +#define CONFIG_SPL_MTD_SUPPORT #define CONFIG_SPL_SPI_SUPPORT #define CONFIG_SPL_SPI_LOAD #define CONFIG_SPL_SPI_FLASH_SUPPORT

Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
Add SPL_MTD_SUPPORT to ZYNQ_QSPI SPL.
Cc: Michal Simek michal.simek@xilinx.com Signed-off-by: Jagan Teki jteki@openedev.com
include/configs/zynq-common.h | 1 + 1 file changed, 1 insertion(+)
This should be done with Kconfig.
Regards, Simon

This patch adds mtd_info support to spi_flash layer, MTD has proven core for flash operations so adding MTD to spi_flash will extends more functionality.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 40 +++++++++++++++++++++++----------------- drivers/mtd/spi/sf_probe.c | 28 ++++++++++++++++++++-------- include/spi_flash.h | 4 ++++ 3 files changed, 47 insertions(+), 25 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 3705534..c9f0bbd 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -15,6 +15,7 @@ #include <spi.h> #include <spi_flash.h> #include <linux/log2.h> +#include <linux/mtd/mtd.h>
#include "sf_internal.h"
@@ -177,8 +178,8 @@ static void spi_flash_dual(struct spi_flash *flash, u32 *addr) { switch (flash->dual_flash) { case SF_DUAL_STACKED_FLASH: - if (*addr >= (flash->size >> 1)) { - *addr -= flash->size >> 1; + if (*addr >= (flash->mtd->size >> 1)) { + *addr -= flash->mtd->size >> 1; flash->spi->flags |= SPI_XFER_U_PAGE; } else { flash->spi->flags &= ~SPI_XFER_U_PAGE; @@ -898,6 +899,7 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
int spi_flash_scan(struct spi_flash *flash) { + struct mtd_info *mtd = flash->mtd; const struct spi_flash_params *params; u16 jedec, ext_jedec; u8 idcode[5]; @@ -947,6 +949,9 @@ int spi_flash_scan(struct spi_flash *flash)
/* Assign spi data */ flash->name = params->name; + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; flash->memory_map = flash->spi->memory_map; flash->dual_flash = flash->spi->option;
@@ -955,17 +960,17 @@ int spi_flash_scan(struct spi_flash *flash) flash->flags |= SNOR_F_SST_WR;
/* Assign spi_flash ops */ - flash->write = spi_flash_cmd_write_ops; + mtd->_write = spi_flash_cmd_write_ops; #if defined(CONFIG_SPI_FLASH_SST) if (flash->flags & SNOR_F_SST_WR) { if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) - flash->write = sst_write_bp; + mtd->_write = sst_write_bp; else - flash->write = sst_write_wp; + mtd->_write = sst_write_wp; } #endif - flash->erase = spi_flash_cmd_erase_ops; - flash->read = spi_flash_cmd_read_ops; + mtd->_erase = spi_flash_cmd_erase_ops; + mtd->_read = spi_flash_cmd_read_ops;
/* lock hooks are flash specific - assign them based on idcode0 */ switch (idcode[0]) { @@ -998,27 +1003,28 @@ int spi_flash_scan(struct spi_flash *flash) flash->page_size = 256; } flash->page_size <<= flash->shift; + mtd->writebufsize = flash->page_size; flash->sector_size = params->sector_size << flash->shift; - flash->size = flash->sector_size * params->nr_sectors << flash->shift; + mtd->size = flash->sector_size * params->nr_sectors << flash->shift; #ifdef CONFIG_SF_DUAL_FLASH if (flash->dual_flash & SF_DUAL_STACKED_FLASH) - flash->size <<= 1; + mtd->size <<= 1; #endif
/* Compute erase sector and command */ if (params->flags & SECT_4K) { flash->erase_cmd = CMD_ERASE_4K; - flash->erase_size = 4096 << flash->shift; + mtd->erasesize = 4096 << flash->shift; } else if (params->flags & SECT_32K) { flash->erase_cmd = CMD_ERASE_32K; - flash->erase_size = 32768 << flash->shift; + mtd->erasesize = 32768 << flash->shift; } else { flash->erase_cmd = CMD_ERASE_64K; - flash->erase_size = flash->sector_size; + mtd->erasesize = flash->sector_size; }
/* Now erase size becomes valid sector size */ - flash->sector_size = flash->erase_size; + flash->sector_size = mtd->erasesize;
/* Look for the fastest read cmd */ cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); @@ -1090,8 +1096,8 @@ int spi_flash_scan(struct spi_flash *flash) #ifndef CONFIG_SPL_BUILD printf("SF: Detected %s with page size ", flash->name); print_size(flash->page_size, ", erase size "); - print_size(flash->erase_size, ", total "); - print_size(flash->size, ""); + print_size(mtd->erasesize, ", total "); + print_size(mtd->size, ""); if (flash->memory_map) printf(", mapped at %p", flash->memory_map); puts("\n"); @@ -1099,9 +1105,9 @@ int spi_flash_scan(struct spi_flash *flash)
#ifndef CONFIG_SPI_FLASH_BAR if (((flash->dual_flash == SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN)) || + (mtd->size > SPI_FLASH_16MB_BOUN)) || ((flash->dual_flash > SF_SINGLE_FLASH) && - (flash->size > SPI_FLASH_16MB_BOUN << 1))) { + (mtd->size > SPI_FLASH_16MB_BOUN << 1))) { puts("SF: Warning - Only lower 16MiB accessible,"); puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); } diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 603c6bc..a88d74e 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -14,9 +14,17 @@ #include <malloc.h> #include <spi.h> #include <spi_flash.h> +#include <linux/mtd/mtd.h>
#include "sf_internal.h"
+struct spi_flash_priv { +#ifndef CONFIG_DM_SPI_FLASH + struct spi_flash flash; +#endif + struct mtd_info mtd; +}; + #ifndef CONFIG_DM_SPI_FLASH struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) { @@ -123,12 +131,19 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
int spi_flash_std_probe(struct udevice *dev) { - struct spi_flash *flash = dev_get_uclass_priv(dev); + struct spi_flash_priv *priv = dev_get_priv(dev); struct spi_slave *slave = dev_get_parent_priv(dev); + struct spi_flash *flash; int ret;
- flash->dev = dev; + flash = dev_get_uclass_priv(dev); + flash->mtd = &priv->mtd; + flash->spi = slave; + flash->priv = priv; + + priv->mtd.priv = flash; + flash->dev = dev;
/* Claim spi bus */ ret = spi_claim_bus(slave); @@ -143,19 +158,16 @@ int spi_flash_std_probe(struct udevice *dev) goto err_scan; }
-#ifdef CONFIG_SPI_FLASH_MTD - ret = spi_flash_mtd_register(flash); + ret = add_mtd_device(&priv->mtd); if (ret) { printf("SF: failed to register mtd device: %d\n", ret); goto err_mtd; } -#endif + return ret;
-#ifdef CONFIG_SPI_FLASH_MTD err_mtd: spi_free_slave(slave); -#endif err_scan: spi_release_bus(slave); return ret; @@ -177,7 +189,7 @@ U_BOOT_DRIVER(spi_flash_std) = { .id = UCLASS_SPI_FLASH, .of_match = spi_flash_std_ids, .probe = spi_flash_std_probe, - .priv_auto_alloc_size = sizeof(struct spi_flash), + .priv_auto_alloc_size = sizeof(struct spi_flash_priv), .ops = &spi_flash_std_ops, };
diff --git a/include/spi_flash.h b/include/spi_flash.h index 721b358..15f7471 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -37,6 +37,7 @@ struct spi_slave; * struct spi_flash - SPI flash structure * * @spi: SPI slave + * @mtd: point to a mtd_info structure * @dev: SPI flash device * @name: Name of SPI flash * @dual_flash: Indicates dual flash memories - dual stacked, parallel @@ -54,6 +55,7 @@ struct spi_slave; * @write_cmd: Write cmd - page and quad program. * @dummy_byte: Dummy cycles for read operation. * @memory_map: Address of read-only SPI flash access + * @priv: the private data * @flash_lock: lock a region of the SPI Flash * @flash_unlock: unlock a region of the SPI Flash * @flash_is_locked: check if a region of the SPI Flash is completely locked @@ -67,6 +69,7 @@ struct spi_slave; */ struct spi_flash { struct spi_slave *spi; + struct mtd_info *mtd; #ifdef CONFIG_DM_SPI_FLASH struct udevice *dev; #endif @@ -90,6 +93,7 @@ struct spi_flash { u8 dummy_byte;
void *memory_map; + void *priv;
int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len);

Hi Jagan,
On 26 November 2015 at 04:04, Jagan Teki jteki@openedev.com wrote:
This patch adds mtd_info support to spi_flash layer, MTD has proven core for flash operations so adding MTD to spi_flash will extends more functionality.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_ops.c | 40 +++++++++++++++++++++++----------------- drivers/mtd/spi/sf_probe.c | 28 ++++++++++++++++++++-------- include/spi_flash.h | 4 ++++ 3 files changed, 47 insertions(+), 25 deletions(-)
This uses its own methods instead of driver model - function pointers should be part of operations in a uclass.
Regards, Simon

Hi Simon,
On 26 November 2015 at 23:20, Simon Glass sjg@chromium.org wrote:
Hi Jagan,
On 26 November 2015 at 04:04, Jagan Teki jteki@openedev.com wrote:
This patch adds mtd_info support to spi_flash layer, MTD has proven core for flash operations so adding MTD to spi_flash will extends more functionality.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_ops.c | 40 +++++++++++++++++++++++----------------- drivers/mtd/spi/sf_probe.c | 28 ++++++++++++++++++++-------- include/spi_flash.h | 4 ++++ 3 files changed, 47 insertions(+), 25 deletions(-)
This uses its own methods instead of driver model - function pointers should be part of operations in a uclass.
Because mtd_info having generic ops which is going to use any underlying flash layer so this patch uses those core ops and dropped spi_flash ops.
thanks!

Since MTD support is added in spi_flash layer, this patch uses mtd_info operations instead of legacy spi_flash operations.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 75 +++++++++++++++++++++++++++++----------------- drivers/mtd/spi/sf_probe.c | 30 ------------------- include/spi_flash.h | 24 +++++++-------- 3 files changed, 59 insertions(+), 70 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index c9f0bbd..1356161 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -14,6 +14,7 @@ #include <mapmem.h> #include <spi.h> #include <spi_flash.h> +#include <linux/math64.h> #include <linux/log2.h> #include <linux/mtd/mtd.h>
@@ -298,18 +299,21 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, return ret; }
-static int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, - size_t len) +static int spi_flash_cmd_erase_ops(struct mtd_info *mtd, + struct erase_info *instr) { - u32 erase_size, erase_addr; + struct spi_flash *flash = mtd->priv; + u32 offset, len, erase_addr; u8 cmd[SPI_FLASH_CMD_LEN]; + uint32_t rem; int ret = -1;
- erase_size = flash->erase_size; - if (offset % erase_size || len % erase_size) { - debug("SF: Erase offset/length not multiple of erase size\n"); - return -1; - } + div_u64_rem(instr->len, mtd->erasesize, &rem); + if (rem) + return -EINVAL; + + offset = instr->addr; + len = instr->len;
if (flash->flash_is_locked) { if (flash->flash_is_locked(flash, offset, len) > 0) { @@ -340,19 +344,27 @@ static int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); if (ret < 0) { debug("SF: erase failed\n"); - break; + goto erase_err; }
- offset += erase_size; - len -= erase_size; + offset += mtd->erasesize; + len -= mtd->erasesize; }
+ instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return ret; + +erase_err: + instr->state = MTD_ERASE_FAILED; return ret; }
-static int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, - size_t len, const void *buf) +static int spi_flash_cmd_write_ops(struct mtd_info *mtd, loff_t offset, + size_t len, size_t *retlen, const u_char *buf) { + struct spi_flash *flash = mtd->priv; unsigned long byte_addr, page_size; u32 write_addr; size_t chunk_len, actual; @@ -402,6 +414,7 @@ static int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, }
offset += chunk_len; + *retlen += chunk_len; }
return ret; @@ -435,11 +448,12 @@ void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len) memcpy(data, offset, len); }
-static int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, - size_t len, void *data) +static int spi_flash_cmd_read_ops(struct mtd_info *mtd, loff_t offset, + size_t len, size_t *retlen, u_char *data) { - u8 *cmd, cmdsz; + struct spi_flash *flash = mtd->priv; u32 remain_len, read_len, read_addr; + u8 *cmd, cmdsz; int bank_sel = 0; int ret = -1;
@@ -496,6 +510,7 @@ static int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, offset += read_len; len -= read_len; data += read_len; + *retlen += read_len; }
free(cmd); @@ -503,7 +518,8 @@ static int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, }
#ifdef CONFIG_SPI_FLASH_SST -static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) +static int sst_byte_write(struct spi_flash *flash, u32 offset, + const void *buf, size_t *retlen) { int ret; u8 cmd[4] = { @@ -524,12 +540,15 @@ static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) if (ret) return ret;
+ *retlen += 1; + return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); }
-static int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf) +static int sst_write_wp(struct mtd_info *mtd, loff_t offset, size_t len, + size_t *retlen, const u_char *buf) { + struct spi_flash *flash = mtd->priv; size_t actual, cmd_len; int ret; u8 cmd[4]; @@ -543,7 +562,7 @@ static int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, /* If the data is not word aligned, write out leading single byte */ actual = offset % 2; if (actual) { - ret = sst_byte_write(flash, offset, buf); + ret = sst_byte_write(flash, offset, buf, retlen); if (ret) goto done; } @@ -560,7 +579,7 @@ static int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, cmd[3] = offset;
for (; actual < len - 1; actual += 2) { - debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", + debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06llx }\n", spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, cmd[0], offset);
@@ -577,6 +596,7 @@ static int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
cmd_len = 1; offset += 2; + *retlen += 2; }
if (!ret) @@ -584,19 +604,20 @@ static int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
/* If there is a single trailing byte, write it out */ if (!ret && actual != len) - ret = sst_byte_write(flash, offset, buf + actual); + ret = sst_byte_write(flash, offset, buf + actual, retlen);
done: - debug("SF: sst: program %s %zu bytes @ 0x%zx\n", + debug("SF: sst: program %s %zu bytes @ 0x%llx\n", ret ? "failure" : "success", len, offset - actual);
spi_release_bus(flash->spi); return ret; }
-static int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, - const void *buf) +static int sst_write_bp(struct mtd_info *mtd, loff_t offset, size_t len, + size_t *retlen, const u_char *buf) { + struct spi_flash *flash = mtd->priv; size_t actual; int ret;
@@ -607,7 +628,7 @@ static int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, }
for (actual = 0; actual < len; actual++) { - ret = sst_byte_write(flash, offset, buf + actual); + ret = sst_byte_write(flash, offset, buf + actual, retlen); if (ret) { debug("SF: sst byte program failed\n"); break; @@ -618,7 +639,7 @@ static int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, if (!ret) ret = spi_flash_cmd_write_disable(flash);
- debug("SF: sst: program %s %zu bytes @ 0x%zx\n", + debug("SF: sst: program %s %zu bytes @ 0x%llx\n", ret ? "failure" : "success", len, offset - actual);
spi_release_bus(flash->spi); diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index a88d74e..f882b3f 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -106,29 +106,6 @@ void spi_flash_free(struct spi_flash *flash)
#else /* defined CONFIG_DM_SPI_FLASH */
-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); - - return flash->read(flash, offset, len, buf); -} - -int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) -{ - struct spi_flash *flash = dev_get_uclass_priv(dev); - - return flash->write(flash, offset, len, buf); -} - -int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) -{ - struct spi_flash *flash = dev_get_uclass_priv(dev); - - return flash->erase(flash, offset, len); -} - int spi_flash_std_probe(struct udevice *dev) { struct spi_flash_priv *priv = dev_get_priv(dev); @@ -173,12 +150,6 @@ err_scan: return ret; }
-static const struct dm_spi_flash_ops spi_flash_std_ops = { - .read = spi_flash_std_read, - .write = spi_flash_std_write, - .erase = spi_flash_std_erase, -}; - static const struct udevice_id spi_flash_std_ids[] = { { .compatible = "spi-flash" }, { } @@ -190,7 +161,6 @@ U_BOOT_DRIVER(spi_flash_std) = { .of_match = spi_flash_std_ids, .probe = spi_flash_std_probe, .priv_auto_alloc_size = sizeof(struct spi_flash_priv), - .ops = &spi_flash_std_ops, };
#endif /* CONFIG_DM_SPI_FLASH */ diff --git a/include/spi_flash.h b/include/spi_flash.h index 15f7471..2e81a14 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -17,6 +17,7 @@
#include <dm.h> /* Because we dereference struct udevice here */ #include <linux/types.h> +#include <linux/mtd/mtd.h>
#ifndef CONFIG_SF_DEFAULT_SPEED # define CONFIG_SF_DEFAULT_SPEED 1000000 @@ -59,12 +60,6 @@ struct spi_slave; * @flash_lock: lock a region of the SPI Flash * @flash_unlock: unlock a region of the SPI Flash * @flash_is_locked: check if a region of the SPI Flash is completely locked - * @read: Flash read ops: Read len bytes at offset into buf - * Supported cmds: Fast Array Read - * @write: Flash write ops: Write len bytes from buf into offset - * Supported cmds: Page Program - * @erase: Flash erase ops: Erase len bytes from offset - * Supported cmds: Sector erase 4K, 32K, 64K * return 0 - Success, 1 - Failure */ struct spi_flash { @@ -98,10 +93,6 @@ struct spi_flash { int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); - int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); - int (*write)(struct spi_flash *flash, u32 offset, size_t len, - const void *buf); - int (*erase)(struct spi_flash *flash, u32 offset, size_t len); };
struct dm_spi_flash_ops { @@ -166,19 +157,26 @@ int spi_flash_remove(struct udevice *flash); 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_read(flash->mtd, offset, len, &len, (u_char *)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_write(flash->mtd, offset, len, &len, (u_char *)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); + struct erase_info instr; + + instr.mtd = flash->mtd; + instr.addr = offset; + instr.len = len; + instr.callback = 0; + + return mtd_erase(flash->mtd, &instr); }
struct sandbox_state;

Since mtd got added, replace flash->size with mtd->size.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- common/cmd_sf.c | 16 ++++++++-------- drivers/mtd/spi/sf_ops.c | 23 +++++++++++++---------- include/spi_flash.h | 2 -- 3 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 42862d9..d9f1bd1 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -275,13 +275,13 @@ static int do_spi_flash_read_write(int argc, char * const argv[]) return -1;
if (mtd_arg_off_size(argc - 2, &argv[2], &dev, &offset, &len, - &maxsize, MTD_DEV_TYPE_NOR, flash->size)) + &maxsize, MTD_DEV_TYPE_NOR, flash->mtd->size)) return -1;
/* Consistency checking */ - if (offset + len > flash->size) { - printf("ERROR: attempting %s past flash size (%#x)\n", - argv[0], flash->size); + if (offset + len > flash->mtd->size) { + printf("ERROR: attempting %s past flash size (0x%llx)\n", + argv[0], flash->mtd->size); return 1; }
@@ -327,7 +327,7 @@ static int do_spi_flash_erase(int argc, char * const argv[]) return -1;
if (mtd_arg_off(argv[1], &dev, &offset, &len, &maxsize, - MTD_DEV_TYPE_NOR, flash->size)) + MTD_DEV_TYPE_NOR, flash->mtd->size)) return -1;
ret = sf_parse_len_arg(argv[2], &size); @@ -335,9 +335,9 @@ static int do_spi_flash_erase(int argc, char * const argv[]) return -1;
/* Consistency checking */ - if (offset + size > flash->size) { - printf("ERROR: attempting %s past flash size (%#x)\n", - argv[0], flash->size); + if (offset + size > flash->mtd->size) { + printf("ERROR: attempting %s past flash size (0x%llx)\n", + argv[0], flash->mtd->size); return 1; }
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 1356161..5a7f5d5 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -149,7 +149,7 @@ static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0) u8 curr_bank = 0; int ret;
- if (flash->size <= SPI_FLASH_16MB_BOUN) + if (flash->mtd->size <= SPI_FLASH_16MB_BOUN) goto bank_end;
switch (idcode0) { @@ -651,6 +651,7 @@ static int sst_write_bp(struct mtd_info *mtd, loff_t offset, size_t len, static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, u32 *len) { + struct mtd_info *mtd = flash->mtd; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; int shift = ffs(mask) - 1; int pow; @@ -661,8 +662,8 @@ static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, *len = 0; } else { pow = ((sr & mask) ^ mask) >> shift; - *len = flash->size >> pow; - *ofs = flash->size - *len; + *len = mtd->size >> pow; + *ofs = mtd->size - *len; } }
@@ -724,6 +725,7 @@ int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len) */ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) { + struct mtd_info *mtd = flash->mtd; u8 status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; @@ -734,12 +736,12 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) return ret;
/* SPI NOR always locks to the end */ - if (ofs + len != flash->size) { + if (ofs + len != mtd->size) { /* Does combined region extend to end? */ - if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len, + if (!stm_is_locked_sr(flash, ofs + len, mtd->size - ofs - len, status_old)) return -EINVAL; - len = flash->size - ofs; + len = mtd->size - ofs; }
/* @@ -751,7 +753,7 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) * * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) */ - pow = ilog2(flash->size) - ilog2(len); + pow = ilog2(mtd->size) - ilog2(len); val = mask - (pow << shift); if (val & ~mask) return -EINVAL; @@ -778,6 +780,7 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) */ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) { + struct mtd_info *mtd = flash->mtd; uint8_t status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 shift = ffs(mask) - 1, pow, val; @@ -800,8 +803,8 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) * * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) */ - pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len)); - if (ofs + len == flash->size) { + pow = ilog2(mtd->size) - order_base_2(mtd->size - (ofs + len)); + if (ofs + len == mtd->size) { val = 0; /* fully unlocked */ } else { val = mask - (pow << shift); @@ -908,7 +911,7 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) return 0; }
- if (flash->size != size) { + if (flash->mtd->size != size) { debug("%s: Memory map must cover entire device\n", __func__); return -1; } diff --git a/include/spi_flash.h b/include/spi_flash.h index 2e81a14..0fee203 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -44,7 +44,6 @@ struct spi_slave; * @dual_flash: Indicates dual flash memories - dual stacked, parallel * @shift: Flash shift useful in dual parallel * @flags: Indication of spi flash flags - * @size: Total flash size * @page_size: Write (page) size * @sector_size: Sector size * @erase_size: Erase size @@ -73,7 +72,6 @@ struct spi_flash { u8 shift; u16 flags;
- u32 size; u32 page_size; u32 sector_size; u32 erase_size;

Since mtd got added, replace flash->erase_size with mtd->erasesize.
Cc: Fabio Estevam fabio.estevam@freescale.com Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 4 ++-- include/spi_flash.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 5a7f5d5..2e279e6 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -791,8 +791,8 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) return ret;
/* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(flash, status_old, ofs - flash->erase_size, - flash->erase_size)) + if (stm_is_locked_sr(flash, status_old, ofs - mtd->erasesize, + mtd->erasesize)) return -EINVAL; /* * Need largest pow such that: diff --git a/include/spi_flash.h b/include/spi_flash.h index 0fee203..d66a8ec 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -46,7 +46,6 @@ struct spi_slave; * @flags: Indication of spi flash flags * @page_size: Write (page) size * @sector_size: Sector size - * @erase_size: Erase size * @bank_read_cmd: Bank read cmd * @bank_write_cmd: Bank write cmd * @bank_curr: Current flash bank @@ -74,7 +73,6 @@ struct spi_flash {
u32 page_size; u32 sector_size; - u32 erase_size; #ifdef CONFIG_SPI_FLASH_BAR u8 bank_read_cmd; u8 bank_write_cmd;

Since mtd_info ops got introduced, just drop the unneeded dm_spi_flash operations.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf-uclass.c | 39 -------------------- include/spi_flash.h | 90 +++++++-------------------------------------- 2 files changed, 14 insertions(+), 115 deletions(-)
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 72e0f6b..5cdbd1b 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -11,24 +11,6 @@ #include <dm/device-internal.h> #include "sf_internal.h"
-DECLARE_GLOBAL_DATA_PTR; - -int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf) -{ - return 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 sf_get_ops(dev)->write(dev, offset, len, buf); -} - -int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) -{ - return sf_get_ops(dev)->erase(dev, offset, len); -} - /* * TODO(sjg@chromium.org): This is an old-style function. We should remove * it when all SPI flash drivers use dm @@ -74,29 +56,8 @@ int spi_flash_remove(struct udevice *dev) return device_remove(dev); }
-static int spi_flash_post_bind(struct udevice *dev) -{ -#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; -} - 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/include/spi_flash.h b/include/spi_flash.h index d66a8ec..dd48c97 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -91,65 +91,6 @@ struct spi_flash { int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); };
-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) - -#ifdef CONFIG_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); - -int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode, - struct udevice **devp); - -/* Compatibility function - this is the old U-Boot API */ -struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode); - -/* Compatibility function - this is the old U-Boot API */ -void spi_flash_free(struct spi_flash *flash); - -int spi_flash_remove(struct udevice *flash); - static inline int spi_flash_read(struct spi_flash *flash, u32 offset, size_t len, void *buf) { @@ -175,6 +116,20 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, return mtd_erase(flash->mtd, &instr); }
+#ifdef CONFIG_DM_SPI_FLASH +int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, + unsigned int max_hz, unsigned int spi_mode, + struct udevice **devp); + +/* Compatibility function - this is the old U-Boot API */ +struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int spi_mode); + +/* Compatibility function - this is the old U-Boot API */ +void spi_flash_free(struct spi_flash *flash); + +int spi_flash_remove(struct udevice *flash); + struct sandbox_state;
int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, @@ -200,23 +155,6 @@ struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
void spi_flash_free(struct spi_flash *flash);
-static inline int spi_flash_read(struct spi_flash *flash, u32 offset, - size_t len, void *buf) -{ - return flash->read(flash, offset, len, buf); -} - -static inline int spi_flash_write(struct spi_flash *flash, u32 offset, - size_t len, const void *buf) -{ - return flash->write(flash, offset, len, buf); -} - -static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, - size_t len) -{ - return flash->erase(flash, offset, len); -} #endif
static inline int spi_flash_protect(struct spi_flash *flash, u32 ofs, u32 len,

Hi Jagan,
On 26 November 2015 at 04:04, Jagan Teki jteki@openedev.com wrote:
Since mtd_info ops got introduced, just drop the unneeded dm_spi_flash operations.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf-uclass.c | 39 -------------------- include/spi_flash.h | 90 +++++++-------------------------------------- 2 files changed, 14 insertions(+), 115 deletions(-)
But mtd_info ops should support driver model.
Regards, Simon

Since the spi-flash framework itself is using core MTD functionalities this patch uses lock operation from mtd.
Cc: Fabio Estevam fabio.estevam@freescale.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 9 - drivers/mtd/spi/sf_ops.c | 404 ++++++++++++++++++++++-------------------- include/spi_flash.h | 34 ++-- 3 files changed, 229 insertions(+), 218 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index fda49e9..677f582 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -163,15 +163,6 @@ int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const void *data, size_t data_len);
-/* Lock stmicro spi flash region */ -int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); - -/* Unlock stmicro spi flash region */ -int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); - -/* Check if a stmicro spi flash region is completely locked */ -int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); - /* Enable writing on the SPI flash */ static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) { diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 2e279e6..4e80d66 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -258,6 +258,205 @@ static int spi_flash_cmd_wait_ready(struct spi_flash *flash, return -ETIMEDOUT; }
+#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) +static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, + uint64_t *len) +{ + struct mtd_info *mtd = flash->mtd; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + int shift = ffs(mask) - 1; + int pow; + + if (!(sr & mask)) { + /* No protection */ + *ofs = 0; + *len = 0; + } else { + pow = ((sr & mask) ^ mask) >> shift; + *len = mtd->size >> pow; + *ofs = mtd->size - *len; + } +} + +/* + * Return 1 if the entire region is locked, 0 otherwise + */ +static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, uint64_t len, + u8 sr) +{ + loff_t lock_offs; + uint64_t lock_len; + + stm_get_locked_range(flash, sr, &lock_offs, &lock_len); + + return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); +} + +/* + * Check if a region of the flash is (completely) locked. See stm_lock() for + * more info. + * + * Returns 1 if entire region is locked, 0 if any portion is unlocked, and + * negative on errors. + */ +static int stm_is_locked(struct spi_flash *flash, loff_t ofs, uint64_t len) +{ + int status; + u8 sr; + + status = read_sr(flash, &sr); + if (status < 0) + return status; + + return stm_is_locked_sr(flash, ofs, len, sr); +} + +/* + * Lock a region of the flash. Compatible with ST Micro and similar flash. + * Supports only the block protection bits BP{0,1,2} in the status register + * (SR). Does not support these features found in newer SR bitfields: + * - TB: top/bottom protect - only handle TB=0 (top protect) + * - SEC: sector/block protect - only handle SEC=0 (block protect) + * - CMP: complement protect - only support CMP=0 (range is not complemented) + * + * Sample table portion for 8MB flash (Winbond w25q64fw): + * + * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion + * -------------------------------------------------------------------------- + * X | X | 0 | 0 | 0 | NONE | NONE + * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 + * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 + * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 + * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 + * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 + * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 + * X | X | 1 | 1 | 1 | 8 MB | ALL + * + * Returns negative on errors, 0 on success. + */ +static int stm_lock(struct spi_flash *flash, loff_t ofs, uint64_t len) +{ + struct mtd_info *mtd = flash->mtd; + u8 status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + int ret; + + ret = read_sr(flash, &status_old); + if (ret < 0) + return ret; + + /* SPI NOR always locks to the end */ + if (ofs + len != mtd->size) { + /* Does combined region extend to end? */ + if (!stm_is_locked_sr(flash, ofs + len, mtd->size - ofs - len, + status_old)) + return -EINVAL; + len = mtd->size - ofs; + } + + /* + * Need smallest pow such that: + * + * 1 / (2^pow) <= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) + */ + pow = ilog2(mtd->size) - ilog2(len); + val = mask - (pow << shift); + if (val & ~mask) + return -EINVAL; + + /* Don't "lock" with no region! */ + if (!(val & mask)) + return -EINVAL; + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not unlock other areas */ + if ((status_new & mask) <= (status_old & mask)) + return -EINVAL; + + write_sr(flash, status_new); + + return 0; +} + +/* + * Unlock a region of the flash. See stm_lock() for more info + * + * Returns negative on errors, 0 on success. + */ +static int stm_unlock(struct spi_flash *flash, loff_t ofs, uint64_t len) +{ + struct mtd_info *mtd = flash->mtd; + uint8_t status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + int ret; + + ret = read_sr(flash, &status_old); + if (ret < 0) + return ret; + + /* Cannot unlock; would unlock larger region than requested */ + if (stm_is_locked_sr(flash, status_old, ofs - mtd->erasesize, + mtd->erasesize)) + return -EINVAL; + /* + * Need largest pow such that: + * + * 1 / (2^pow) >= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) + */ + pow = ilog2(mtd->size) - order_base_2(mtd->size - (ofs + len)); + if (ofs + len == mtd->size) { + val = 0; /* fully unlocked */ + } else { + val = mask - (pow << shift); + /* Some power-of-two sizes are not supported */ + if (val & ~mask) + return -EINVAL; + } + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not lock other areas */ + if ((status_new & mask) >= (status_old & mask)) + return -EINVAL; + + write_sr(flash, status_new); + + return 0; +} +#endif /* CONFIG_SPI_FLASH_STMICRO */ + +static int spi_flash_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct spi_flash *flash = mtd->priv; + + return flash->flash_lock(flash, ofs, len); +} + +static int spi_flash_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct spi_flash *flash = mtd->priv; + + return flash->flash_unlock(flash, ofs, len); +} + +static int spi_flash_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct spi_flash *flash = mtd->priv; + + return flash->flash_is_locked(flash, ofs, len); +} + int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, const void *buf, size_t buf_len) { @@ -315,8 +514,8 @@ static int spi_flash_cmd_erase_ops(struct mtd_info *mtd, offset = instr->addr; len = instr->len;
- if (flash->flash_is_locked) { - if (flash->flash_is_locked(flash, offset, len) > 0) { + if (mtd->_is_locked) { + if (mtd->_is_locked(mtd, offset, len) > 0) { printf("offset 0x%x is protected and cannot be erased\n", offset); return -EINVAL; @@ -373,9 +572,9 @@ static int spi_flash_cmd_write_ops(struct mtd_info *mtd, loff_t offset,
page_size = flash->page_size;
- if (flash->flash_is_locked) { - if (flash->flash_is_locked(flash, offset, len) > 0) { - printf("offset 0x%x is protected and cannot be written\n", + if (mtd->_is_locked) { + if (mtd->_is_locked(mtd, offset, len) > 0) { + printf("offset 0x%llx is protected and cannot be written\n", offset); return -EINVAL; } @@ -647,185 +846,6 @@ static int sst_write_bp(struct mtd_info *mtd, loff_t offset, size_t len, } #endif
-#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) -static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, - u32 *len) -{ - struct mtd_info *mtd = flash->mtd; - u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - int shift = ffs(mask) - 1; - int pow; - - if (!(sr & mask)) { - /* No protection */ - *ofs = 0; - *len = 0; - } else { - pow = ((sr & mask) ^ mask) >> shift; - *len = mtd->size >> pow; - *ofs = mtd->size - *len; - } -} - -/* - * Return 1 if the entire region is locked, 0 otherwise - */ -static int stm_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len, - u8 sr) -{ - loff_t lock_offs; - u32 lock_len; - - stm_get_locked_range(flash, sr, &lock_offs, &lock_len); - - return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); -} - -/* - * Check if a region of the flash is (completely) locked. See stm_lock() for - * more info. - * - * Returns 1 if entire region is locked, 0 if any portion is unlocked, and - * negative on errors. - */ -int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len) -{ - int status; - u8 sr; - - status = read_sr(flash, &sr); - if (status < 0) - return status; - - return stm_is_locked_sr(flash, ofs, len, sr); -} - -/* - * Lock a region of the flash. Compatible with ST Micro and similar flash. - * Supports only the block protection bits BP{0,1,2} in the status register - * (SR). Does not support these features found in newer SR bitfields: - * - TB: top/bottom protect - only handle TB=0 (top protect) - * - SEC: sector/block protect - only handle SEC=0 (block protect) - * - CMP: complement protect - only support CMP=0 (range is not complemented) - * - * Sample table portion for 8MB flash (Winbond w25q64fw): - * - * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion - * -------------------------------------------------------------------------- - * X | X | 0 | 0 | 0 | NONE | NONE - * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 - * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 - * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 - * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 - * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 - * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 - * X | X | 1 | 1 | 1 | 8 MB | ALL - * - * Returns negative on errors, 0 on success. - */ -int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) -{ - struct mtd_info *mtd = flash->mtd; - u8 status_old, status_new; - u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - u8 shift = ffs(mask) - 1, pow, val; - int ret; - - ret = read_sr(flash, &status_old); - if (ret < 0) - return ret; - - /* SPI NOR always locks to the end */ - if (ofs + len != mtd->size) { - /* Does combined region extend to end? */ - if (!stm_is_locked_sr(flash, ofs + len, mtd->size - ofs - len, - status_old)) - return -EINVAL; - len = mtd->size - ofs; - } - - /* - * Need smallest pow such that: - * - * 1 / (2^pow) <= (len / size) - * - * so (assuming power-of-2 size) we do: - * - * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) - */ - pow = ilog2(mtd->size) - ilog2(len); - val = mask - (pow << shift); - if (val & ~mask) - return -EINVAL; - - /* Don't "lock" with no region! */ - if (!(val & mask)) - return -EINVAL; - - status_new = (status_old & ~mask) | val; - - /* Only modify protection if it will not unlock other areas */ - if ((status_new & mask) <= (status_old & mask)) - return -EINVAL; - - write_sr(flash, status_new); - - return 0; -} - -/* - * Unlock a region of the flash. See stm_lock() for more info - * - * Returns negative on errors, 0 on success. - */ -int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) -{ - struct mtd_info *mtd = flash->mtd; - uint8_t status_old, status_new; - u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - u8 shift = ffs(mask) - 1, pow, val; - int ret; - - ret = read_sr(flash, &status_old); - if (ret < 0) - return ret; - - /* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(flash, status_old, ofs - mtd->erasesize, - mtd->erasesize)) - return -EINVAL; - /* - * Need largest pow such that: - * - * 1 / (2^pow) >= (len / size) - * - * so (assuming power-of-2 size) we do: - * - * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) - */ - pow = ilog2(mtd->size) - order_base_2(mtd->size - (ofs + len)); - if (ofs + len == mtd->size) { - val = 0; /* fully unlocked */ - } else { - val = mask - (pow << shift); - /* Some power-of-two sizes are not supported */ - if (val & ~mask) - return -EINVAL; - } - - status_new = (status_old & ~mask) | val; - - /* Only modify protection if it will not lock other areas */ - if ((status_new & mask) >= (status_old & mask)) - return -EINVAL; - - write_sr(flash, status_new); - - return 0; -} -#endif - - #ifdef CONFIG_SPI_FLASH_MACRONIX static int spi_flash_set_qeb_mxic(struct spi_flash *flash) { @@ -996,18 +1016,20 @@ int spi_flash_scan(struct spi_flash *flash) mtd->_erase = spi_flash_cmd_erase_ops; mtd->_read = spi_flash_cmd_read_ops;
- /* lock hooks are flash specific - assign them based on idcode0 */ - switch (idcode[0]) { + /* NOR protection support for STmicro/Micron chips and similar */ #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) - case SPI_FLASH_CFI_MFR_STMICRO: - case SPI_FLASH_CFI_MFR_SST: + if ((idcode[0] == SPI_FLASH_CFI_MFR_STMICRO) || + (idcode[0] == SPI_FLASH_CFI_MFR_SST)) { flash->flash_lock = stm_lock; flash->flash_unlock = stm_unlock; flash->flash_is_locked = stm_is_locked; + } #endif - break; - default: - debug("SF: Lock ops not supported for %02x flash\n", idcode[0]); + + if (flash->flash_lock && flash->flash_unlock && flash->flash_is_locked) { + mtd->_lock = spi_flash_lock; + mtd->_unlock = spi_flash_unlock; + mtd->_is_locked = spi_flash_is_locked; }
/* Compute the flash size */ diff --git a/include/spi_flash.h b/include/spi_flash.h index dd48c97..d617061 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -55,9 +55,10 @@ struct spi_slave; * @dummy_byte: Dummy cycles for read operation. * @memory_map: Address of read-only SPI flash access * @priv: the private data - * @flash_lock: lock a region of the SPI Flash - * @flash_unlock: unlock a region of the SPI Flash - * @flash_is_locked: check if a region of the SPI Flash is completely locked + * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR + * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR + * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is + * completely locked * return 0 - Success, 1 - Failure */ struct spi_flash { @@ -86,9 +87,9 @@ struct spi_flash { void *memory_map; void *priv;
- int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); - int (*flash_unlock)(struct spi_flash *flash, u32 ofs, size_t len); - int (*flash_is_locked)(struct spi_flash *flash, u32 ofs, size_t len); + int (*flash_lock)(struct spi_flash *flash, loff_t ofs, uint64_t len); + int (*flash_unlock)(struct spi_flash *flash, loff_t ofs, uint64_t len); + int (*flash_is_locked)(struct spi_flash *flash, loff_t ofs, uint64_t len); };
static inline int spi_flash_read(struct spi_flash *flash, u32 offset, @@ -116,6 +117,15 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, return mtd_erase(flash->mtd, &instr); }
+static inline int spi_flash_protect(struct spi_flash *flash, u32 ofs, u32 len, + bool prot) +{ + if (prot) + return mtd_lock(flash->mtd, ofs, len); + else + return mtd_unlock(flash->mtd, ofs, len); +} + #ifdef CONFIG_DM_SPI_FLASH int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, unsigned int max_hz, unsigned int spi_mode, @@ -157,18 +167,6 @@ void spi_flash_free(struct spi_flash *flash);
#endif
-static inline int spi_flash_protect(struct spi_flash *flash, u32 ofs, u32 len, - bool prot) -{ - if (!flash->flash_lock || !flash->flash_unlock) - return -EOPNOTSUPP; - - if (prot) - return flash->flash_lock(flash, ofs, len); - else - return flash->flash_unlock(flash, ofs, len); -} - void spi_boot(void) __noreturn; void spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst);

This patch adds MTD support to non-dm spi_flash interface code.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_probe.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index f882b3f..51a0c07 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -28,17 +28,24 @@ struct spi_flash_priv { #ifndef CONFIG_DM_SPI_FLASH struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) { + struct spi_flash_priv *priv; struct spi_flash *flash; int ret;
- /* Allocate space if needed (not used by sf-uclass */ - flash = calloc(1, sizeof(*flash)); - if (!flash) { - debug("SF: Failed to allocate spi_flash\n"); + /* Allocate space if needed (not used by sf-uclass) */ + priv = calloc(1, sizeof(*priv)); + if (!priv) { + debug("SF: Failed to allocate spi_flash_priv\n"); return NULL; }
+ flash = &priv->flash; + flash->mtd = &priv->mtd; + flash->spi = bus; + flash->priv = priv; + + priv->mtd.priv = flash;
/* Claim spi bus */ ret = spi_claim_bus(bus); @@ -51,19 +58,16 @@ struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) if (ret) goto err_scan;
-#ifdef CONFIG_SPI_FLASH_MTD - ret = spi_flash_mtd_register(flash); + ret = add_mtd_device(&priv->mtd); if (ret) { printf("SF: failed to register mtd device: %d\n", ret); goto err_mtd; } -#endif + return flash;
-#ifdef CONFIG_SPI_FLASH_MTD err_mtd: spi_free_slave(bus); -#endif err_scan: spi_release_bus(bus); err_claim: @@ -97,9 +101,7 @@ struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
void spi_flash_free(struct spi_flash *flash) { -#ifdef CONFIG_SPI_FLASH_MTD - spi_flash_mtd_unregister(); -#endif + del_mtd_device(flash->mtd); spi_free_slave(flash->spi); free(flash); }

Hi Jagan,
On 26 November 2015 at 04:04, Jagan Teki jteki@openedev.com wrote:
This patch adds MTD support to non-dm spi_flash interface code.
Why add new support to the non-DM SPI flash? You should first make MTD support driver model, then try to drop the old non-DM SPI flash code.
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com
drivers/mtd/spi/sf_probe.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
Regards, Simon

- Use static for file-scope function - Remove unneeded header file - Use spi instead of slave notation for spi_slave {}
Reviewed-by: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_probe.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 51a0c07..17281bd 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -26,7 +26,7 @@ struct spi_flash_priv { };
#ifndef CONFIG_DM_SPI_FLASH -struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) +static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) { struct spi_flash_priv *priv; struct spi_flash *flash; @@ -108,24 +108,24 @@ void spi_flash_free(struct spi_flash *flash)
#else /* defined CONFIG_DM_SPI_FLASH */
-int spi_flash_std_probe(struct udevice *dev) +static int spi_flash_std_probe(struct udevice *dev) { struct spi_flash_priv *priv = dev_get_priv(dev); - struct spi_slave *slave = dev_get_parent_priv(dev); + struct spi_slave *spi = dev_get_parent_priv(dev); struct spi_flash *flash; int ret;
flash = dev_get_uclass_priv(dev); flash->mtd = &priv->mtd;
- flash->spi = slave; + flash->spi = spi; flash->priv = priv;
priv->mtd.priv = flash; flash->dev = dev;
/* Claim spi bus */ - ret = spi_claim_bus(slave); + ret = spi_claim_bus(spi); if (ret) { debug("SF: Failed to claim SPI bus: %d\n", ret); return ret; @@ -146,9 +146,9 @@ int spi_flash_std_probe(struct udevice *dev) return ret;
err_mtd: - spi_free_slave(slave); + spi_free_slave(spi); err_scan: - spi_release_bus(slave); + spi_release_bus(spi); return ret; }

Since mtd_info{} ops are used instead of spi_flash{} ops there is no need to check the flash->flags to SNOR_F_SST_WR as sf_ops behaves as a core to handling generic flash functionalities for both dm and non-dm.
Cc: Bin Meng bmeng.cn@gmail.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 3 +-- drivers/mtd/spi/sf_ops.c | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 677f582..6c4ce77 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -52,8 +52,7 @@ enum { #define SST_WR (SST_BP | SST_WP)
enum spi_nor_option_flags { - SNOR_F_SST_WR = (1 << 0), - SNOR_F_USE_FSR = (1 << 1), + SNOR_F_USE_FSR = (1 << 0), };
#define SPI_FLASH_3B_ADDR_LEN 3 diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 4e80d66..4e2845c 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -999,14 +999,10 @@ int spi_flash_scan(struct spi_flash *flash) flash->memory_map = flash->spi->memory_map; flash->dual_flash = flash->spi->option;
- /* Assign spi flash flags */ - if (params->flags & SST_WR) - flash->flags |= SNOR_F_SST_WR; - /* Assign spi_flash ops */ mtd->_write = spi_flash_cmd_write_ops; #if defined(CONFIG_SPI_FLASH_SST) - if (flash->flags & SNOR_F_SST_WR) { + if (params->flags & SST_WR) { if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) mtd->_write = sst_write_bp; else

SST parts added on sf_params.c supports both SST_WR which consits of both BP and WP and there is a spi controller ich which supports only BP so the relevent _write hook set based on "slave->op_mode_tx" hence there is no respective change required from flash side hance removed these.
Cc: Bin Meng bmeng.cn@gmail.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_internal.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 6c4ce77..1402220 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -44,13 +44,10 @@ enum { #endif SECT_32K = 1 << 1, E_FSR = 1 << 2, - SST_BP = 1 << 3, - SST_WP = 1 << 4, - WR_QPP = 1 << 5, + SST_WR = 1 << 3, + WR_QPP = 1 << 4, };
-#define SST_WR (SST_BP | SST_WP) - enum spi_nor_option_flags { SNOR_F_USE_FSR = (1 << 0), };

For assigning read_bar commands in spansion case, break is missing this patch add that break.
Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_ops.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 4e2845c..bc9cbf7 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -156,6 +156,7 @@ static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0) case SPI_FLASH_CFI_MFR_SPANSION: flash->bank_read_cmd = CMD_BANKADDR_BRRD; flash->bank_write_cmd = CMD_BANKADDR_BRWR; + break; default: flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; flash->bank_write_cmd = CMD_EXTNADDR_WREAR;

Now MTD core has been added as part of spi-flash layer, so there is no need for explicit driver for handling mtd stuff, hence removed all neccessary code regarding SPI_FLASH_MTD driver.
Cc: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/Kconfig | 12 ----- drivers/mtd/spi/Makefile | 1 - drivers/mtd/spi/sf_internal.h | 5 -- drivers/mtd/spi/sf_mtd.c | 104 ------------------------------------------ 4 files changed, 122 deletions(-) delete mode 100644 drivers/mtd/spi/sf_mtd.c
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 3f7433c..78932a4 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -116,16 +116,4 @@ config SPI_FLASH_DATAFLASH
If unsure, say N
-config SPI_FLASH_MTD - bool "SPI Flash MTD support" - depends on SPI_FLASH - help - Enable the MTD support for spi flash layer, this adapter is for - translating mtd_read/mtd_write commands into spi_flash_read/write - commands. It is not intended to use it within sf_cmd or the SPI - flash subsystem. Such an adapter is needed for subsystems like - UBI which can only operate on top of the MTD layer. - - If unsure, say N - endmenu # menu "SPI Flash Support" diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index a24f761..5eb4417 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -14,5 +14,4 @@ endif
obj-$(CONFIG_SPI_FLASH) += sf_probe.o sf_ops.o sf_params.o sf.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o -obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 1402220..77ad8e8 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -189,11 +189,6 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, void *data, size_t data_len);
-#ifdef CONFIG_SPI_FLASH_MTD -int spi_flash_mtd_register(struct spi_flash *flash); -void spi_flash_mtd_unregister(void); -#endif - /** * spi_flash_scan - scan the SPI FLASH * @flash: the spi flash structure diff --git a/drivers/mtd/spi/sf_mtd.c b/drivers/mtd/spi/sf_mtd.c deleted file mode 100644 index 0b9cb62..0000000 --- a/drivers/mtd/spi/sf_mtd.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2012-2014 Daniel Schwierzeck, daniel.schwierzeck@gmail.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <malloc.h> -#include <asm/errno.h> -#include <linux/mtd/mtd.h> -#include <spi_flash.h> - -static struct mtd_info sf_mtd_info; -static char sf_mtd_name[8]; - -static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct spi_flash *flash = mtd->priv; - int err; - - instr->state = MTD_ERASING; - - err = spi_flash_erase(flash, instr->addr, instr->len); - if (err) { - instr->state = MTD_ERASE_FAILED; - instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; - return -EIO; - } - - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); - - return 0; -} - -static int spi_flash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct spi_flash *flash = mtd->priv; - int err; - - err = spi_flash_read(flash, from, len, buf); - if (!err) - *retlen = len; - - return err; -} - -static int spi_flash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct spi_flash *flash = mtd->priv; - int err; - - err = spi_flash_write(flash, to, len, buf); - if (!err) - *retlen = len; - - return err; -} - -static void spi_flash_mtd_sync(struct mtd_info *mtd) -{ -} - -static int spi_flash_mtd_number(void) -{ -#ifdef CONFIG_SYS_MAX_FLASH_BANKS - return CONFIG_SYS_MAX_FLASH_BANKS; -#else - return 0; -#endif -} - -int spi_flash_mtd_register(struct spi_flash *flash) -{ - memset(&sf_mtd_info, 0, sizeof(sf_mtd_info)); - sprintf(sf_mtd_name, "nor%d", spi_flash_mtd_number()); - - sf_mtd_info.name = sf_mtd_name; - sf_mtd_info.type = MTD_NORFLASH; - sf_mtd_info.flags = MTD_CAP_NORFLASH; - sf_mtd_info.writesize = 1; - sf_mtd_info.writebufsize = flash->page_size; - - sf_mtd_info._erase = spi_flash_mtd_erase; - sf_mtd_info._read = spi_flash_mtd_read; - sf_mtd_info._write = spi_flash_mtd_write; - sf_mtd_info._sync = spi_flash_mtd_sync; - - sf_mtd_info.size = flash->size; - sf_mtd_info.priv = flash; - - /* Only uniform flash devices for now */ - sf_mtd_info.numeraseregions = 0; - sf_mtd_info.erasesize = flash->sector_size; - - return add_mtd_device(&sf_mtd_info); -} - -void spi_flash_mtd_unregister(void) -{ - del_mtd_device(&sf_mtd_info); -}

No explict spi-flash mtd handling driver, it's been part of spi-flash layer iteself, hence removed it from board configs.
Cc: Heiko Schocher hs@denx.de Signed-off-by: Jagan Teki jteki@openedev.com --- include/configs/aristainetos-common.h | 1 - include/configs/gw_ventana.h | 1 - include/configs/socfpga_common.h | 1 - 3 files changed, 3 deletions(-)
diff --git a/include/configs/aristainetos-common.h b/include/configs/aristainetos-common.h index 0b97ccc..cbba6be 100644 --- a/include/configs/aristainetos-common.h +++ b/include/configs/aristainetos-common.h @@ -42,7 +42,6 @@ #define CONFIG_PHY_MICREL
#define CONFIG_CMD_SF -#define CONFIG_SPI_FLASH_MTD #define CONFIG_MXC_SPI #define CONFIG_SF_DEFAULT_SPEED 20000000 #define CONFIG_SF_DEFAULT_MODE SPI_MODE_0 diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h index b7b9c78..1ac9420 100644 --- a/include/configs/gw_ventana.h +++ b/include/configs/gw_ventana.h @@ -68,7 +68,6 @@ #define CONFIG_CMD_SF #ifdef CONFIG_CMD_SF #define CONFIG_MXC_SPI - #define CONFIG_SPI_FLASH_MTD #define CONFIG_SPI_FLASH_BAR #define CONFIG_SF_DEFAULT_BUS 0 #define CONFIG_SF_DEFAULT_CS 0 diff --git a/include/configs/socfpga_common.h b/include/configs/socfpga_common.h index b22e3b1..0a68510 100644 --- a/include/configs/socfpga_common.h +++ b/include/configs/socfpga_common.h @@ -191,7 +191,6 @@ unsigned int cm_get_l4_sp_clk_hz(void); */ /* Enable multiple SPI NOR flash manufacturers */ #ifndef CONFIG_SPL_BUILD -#define CONFIG_SPI_FLASH_MTD #define CONFIG_CMD_MTDPARTS #define CONFIG_MTD_DEVICE #define CONFIG_MTD_PARTITIONS

dataflash doesn't require options, memory_map from spi.
Cc: Haikun Wang haikun.wang@freescale.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_dataflash.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index b2a56da..6a9dfef 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -584,6 +584,7 @@ static int spi_dataflash_probe(struct udevice *dev) int ret, status = 0;
spi_flash = dev_get_uclass_priv(dev); + spi_flash->spi = spi; spi_flash->dev = dev;
ret = spi_claim_bus(spi); @@ -664,11 +665,6 @@ static int spi_dataflash_probe(struct udevice *dev) } }
- /* Assign spi data */ - spi_flash->spi = spi; - spi_flash->memory_map = spi->memory_map; - spi_flash->dual_flash = spi->option; - spi_release_bus(spi);
return 0;

Flash id detection should be the first step to enumerate the connected flash on the board, once ie done checking with respective id codes locally in the driver all this should be part of jedec_probe instead of id detection and validated through flash_info{} table separatly.
Cc: Haikun Wang haikun.wang@freescale.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_dataflash.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 6a9dfef..7c6c8d2 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -501,9 +501,10 @@ static struct flash_info dataflash_data[] = { { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, };
-static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id) +static struct flash_info *jedec_probe(struct spi_slave *spi) { int tmp; + uint8_t id[5]; uint32_t jedec; struct flash_info *info; int status; @@ -517,6 +518,11 @@ static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id) * That's not an error; only rev C and newer chips handle it, and * only Atmel sells these chips. */ + tmp = spi_flash_cmd(spi, CMD_READ_ID, id, sizeof(id)); + if (tmp < 0) { + printf("dataflash: error %d reading JEDEC ID\n", tmp); + return ERR_PTR(tmp); + } if (id[0] != 0x1f) return NULL;
@@ -580,7 +586,6 @@ static int spi_dataflash_probe(struct udevice *dev) struct spi_slave *spi = dev_get_parent_priv(dev); struct spi_flash *spi_flash; struct flash_info *info; - u8 idcode[5]; int ret, status = 0;
spi_flash = dev_get_uclass_priv(dev); @@ -591,12 +596,6 @@ static int spi_dataflash_probe(struct udevice *dev) if (ret) return ret;
- ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); - if (ret) { - printf("SPI DataFlash: Failed to get idcodes\n"); - goto err_read_cmd; - } - /* * Try to detect dataflash by JEDEC ID. * If it succeeds we know we have either a C or D part. @@ -604,7 +603,9 @@ static int spi_dataflash_probe(struct udevice *dev) * Both support the security register, though with different * write procedures. */ - info = jedec_probe(spi, idcode); + info = jedec_probe(spi); + if (IS_ERR(info)) + return PTR_ERR(info); if (info != NULL) add_dataflash(dev, info->name, info->nr_pages, info->pagesize, info->pageoffset,

This patch fixed the add_dataflash return logic, so-that it can handle both jedec and older chips same as Linux.
Cc: Haikun Wang haikun.wang@freescale.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_dataflash.c | 127 ++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 66 deletions(-)
diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 7c6c8d2..212aa69 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -586,15 +586,15 @@ static int spi_dataflash_probe(struct udevice *dev) struct spi_slave *spi = dev_get_parent_priv(dev); struct spi_flash *spi_flash; struct flash_info *info; - int ret, status = 0; + int status;
spi_flash = dev_get_uclass_priv(dev); spi_flash->spi = spi; spi_flash->dev = dev;
- ret = spi_claim_bus(spi); - if (ret) - return ret; + status = spi_claim_bus(spi); + if (status) + return status;
/* * Try to detect dataflash by JEDEC ID. @@ -605,74 +605,69 @@ static int spi_dataflash_probe(struct udevice *dev) */ info = jedec_probe(spi); if (IS_ERR(info)) - return PTR_ERR(info); - if (info != NULL) - add_dataflash(dev, info->name, info->nr_pages, - info->pagesize, info->pageoffset, - (info->flags & SUP_POW2PS) ? 'd' : 'c'); - else { - /* - * Older chips support only legacy commands, identifing - * capacity using bits in the status byte. - */ - status = dataflash_status(spi); - if (status <= 0 || status == 0xff) { - printf("SPI DataFlash: read status error %d\n", status); - if (status == 0 || status == 0xff) - status = -ENODEV; - goto err_read_cmd; - } - /* - * if there's a device there, assume it's dataflash. - * board setup should have set spi->max_speed_max to - * match f(car) for continuous reads, mode 0 or 3. - */ - switch (status & 0x3c) { - case 0x0c: /* 0 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB011B", - 512, 264, 9, 0); - break; - case 0x14: /* 0 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB021B", - 1024, 264, 9, 0); - break; - case 0x1c: /* 0 1 1 1 x x */ - status = add_dataflash(dev, "AT45DB041x", - 2048, 264, 9, 0); - break; - case 0x24: /* 1 0 0 1 x x */ - status = add_dataflash(dev, "AT45DB081B", - 4096, 264, 9, 0); - break; - case 0x2c: /* 1 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB161x", - 4096, 528, 10, 0); - break; - case 0x34: /* 1 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB321x", - 8192, 528, 10, 0); - break; - case 0x38: /* 1 1 1 x x x */ - case 0x3c: - status = add_dataflash(dev, "AT45DB642x", - 8192, 1056, 11, 0); - break; - /* obsolete AT45DB1282 not (yet?) supported */ - default: - dev_info(&spi->dev, "unsupported device (%x)\n", - status & 0x3c); + goto err_jedec_probe; + if (info != NULL) { + status = add_dataflash(dev, info->name, info->nr_pages, + info->pagesize, info->pageoffset, + (info->flags & SUP_POW2PS) ? 'd' : 'c'); + if (status < 0) + goto err_status; + } + + /* + * Older chips support only legacy commands, identifing + * capacity using bits in the status byte. + */ + status = dataflash_status(spi); + if (status <= 0 || status == 0xff) { + printf("SPI DataFlash: read status error %d\n", status); + if (status == 0 || status == 0xff) status = -ENODEV; - goto err_read_cmd; - } + goto err_jedec_probe; }
- spi_release_bus(spi); + /* + * if there's a device there, assume it's dataflash. + * board setup should have set spi->max_speed_max to + * match f(car) for continuous reads, mode 0 or 3. + */ + switch (status & 0x3c) { + case 0x0c: /* 0 0 1 1 x x */ + status = add_dataflash(dev, "AT45DB011B", 512, 264, 9, 0); + break; + case 0x14: /* 0 1 0 1 x x */ + status = add_dataflash(dev, "AT45DB021B", 1024, 264, 9, 0); + break; + case 0x1c: /* 0 1 1 1 x x */ + status = add_dataflash(dev, "AT45DB041x", 2048, 264, 9, 0); + break; + case 0x24: /* 1 0 0 1 x x */ + status = add_dataflash(dev, "AT45DB081B", 4096, 264, 9, 0); + break; + case 0x2c: /* 1 0 1 1 x x */ + status = add_dataflash(dev, "AT45DB161x", 4096, 528, 10, 0); + break; + case 0x34: /* 1 1 0 1 x x */ + status = add_dataflash(dev, "AT45DB321x", 8192, 528, 10, 0); + break; + case 0x38: /* 1 1 1 x x x */ + case 0x3c: + status = add_dataflash(dev, "AT45DB642x", 8192, 1056, 11, 0); + break; + /* obsolete AT45DB1282 not (yet?) supported */ + default: + dev_info(&spi->dev, "unsupported device (%x)\n", + status & 0x3c); + status = -ENODEV; + goto err_status; + }
- return 0; + return status;
-err_read_cmd: +err_status: + spi_free_slave(spi); +err_jedec_probe: spi_release_bus(spi); - return status; }

Since spi-flash is using MTD core by inheriting flash operation from mtd_info, legacy spi_flash{} are no longer available so this patch use mtd_info as same as spi-flash.
Cc: Haikun Wang haikun.wang@freescale.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/sf_dataflash.c | 236 ++++++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 112 deletions(-)
diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 212aa69..bdface2 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -2,6 +2,7 @@ * * Atmel DataFlash probing * + * Copyright (C) 2015 Jagan Teki jteki@openedev.com * Copyright (C) 2004-2009, 2015 Freescale Semiconductor, Inc. * Haikun Wang (haikun.wang@freescale.com) * @@ -16,6 +17,7 @@ #include <div64.h> #include <linux/err.h> #include <linux/math64.h> +#include <linux/mtd/mtd.h>
#include "sf_internal.h"
@@ -70,7 +72,11 @@
struct dataflash { uint8_t command[16]; + unsigned short page_offset; /* offset in flash address */ + unsigned int page_size; /* of bytes per page */ + + struct mtd_info mtd; };
/* @@ -117,31 +123,26 @@ 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 dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) { - struct dataflash *dataflash; - struct spi_flash *spi_flash; - struct spi_slave *spi; - unsigned blocksize; + struct spi_flash *flash = mtd->priv; + struct dataflash *priv = flash->priv; + struct spi_slave *spi = flash->spi; + unsigned blocksize = priv->page_size << 3; uint8_t *command; uint32_t rem; int status;
- dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); - spi = spi_flash->spi; - - blocksize = spi_flash->page_size << 3; + memset(priv->command, 0 , sizeof(priv->command)); + command = priv->command;
- memset(dataflash->command, 0 , sizeof(dataflash->command)); - command = dataflash->command; + debug("%s: erase addr=0x%llx len 0x%llx\n", flash->name, + instr->addr, instr->len);
- debug("%s: erase addr=0x%x len 0x%x\n", dev->name, offset, len); - - div_u64_rem(len, spi_flash->page_size, &rem); + div_u64_rem(instr->len, priv->page_size, &rem); if (rem) return -EINVAL; - div_u64_rem(offset, spi_flash->page_size, &rem); + div_u64_rem(instr->addr, priv->page_size, &rem); if (rem) return -EINVAL;
@@ -151,16 +152,16 @@ static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) return status; }
- while (len > 0) { + while (instr->len > 0) { unsigned int pageaddr; int do_block; /* * Calculate flash page address; use block erase (for speed) if * we're at a block boundary and need to erase the whole block. */ - pageaddr = div_u64(offset, spi_flash->page_size); - do_block = (pageaddr & 0x7) == 0 && len >= blocksize; - pageaddr = pageaddr << dataflash->page_offset; + pageaddr = div_u64(instr->addr, priv->page_size); + do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize; + pageaddr = pageaddr << priv->page_offset;
command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; command[1] = (uint8_t)(pageaddr >> 16); @@ -168,67 +169,69 @@ static int spi_dataflash_erase(struct udevice *dev, u32 offset, size_t len) command[3] = 0;
debug("%s ERASE %s: (%x) %x %x %x [%d]\n", - dev->name, do_block ? "block" : "page", + flash->name, do_block ? "block" : "page", command[0], command[1], command[2], command[3], pageaddr);
status = spi_flash_cmd_write(spi, command, 4, NULL, 0); if (status < 0) { - debug("%s: erase send command error!\n", dev->name); + debug("%s: erase send command error!\n", flash->name); return -EIO; }
status = dataflash_waitready(spi); if (status < 0) { - debug("%s: erase waitready error!\n", dev->name); + debug("%s: erase waitready error!\n", flash->name); return status; }
if (do_block) { - offset += blocksize; - len -= blocksize; + instr->addr += blocksize; + instr->len -= blocksize; } else { - offset += spi_flash->page_size; - len -= spi_flash->page_size; + instr->addr += priv->page_size; + instr->len -= priv->page_size; } }
spi_release_bus(spi);
+ /* Inform MTD subsystem that erase is complete */ + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + return 0; }
/* * Read from the DataFlash device. - * offset : Start offset in flash device + * from : Start offset in flash device * len : Amount to read + * retlen : About of data actually read * buf : Buffer containing the data */ -static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len, - void *buf) +static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) { - struct dataflash *dataflash; - struct spi_flash *spi_flash; - struct spi_slave *spi; + struct spi_flash *flash = mtd->priv; + struct dataflash *priv = flash->priv; + struct spi_slave *spi = flash->spi; unsigned int addr; uint8_t *command; int status;
- dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); - spi = spi_flash->spi; + memset(priv->command, 0 , sizeof(priv->command)); + command = priv->command;
- 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: read 0x%x..0x%x\n", flash->name, (unsigned)from, + (unsigned)(from + len)); debug("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
/* Calculate flash page/byte address */ - addr = (((unsigned)offset / spi_flash->page_size) - << dataflash->page_offset) - + ((unsigned)offset % spi_flash->page_size); + addr = (((unsigned)from / priv->page_size) + << priv->page_offset) + + ((unsigned)from % priv->page_size);
status = spi_claim_bus(spi); if (status) { @@ -248,6 +251,10 @@ static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len,
/* plus 4 "don't care" bytes, command len: 4 + 4 "don't care" bytes */ status = spi_flash_cmd_read(spi, command, 8, buf, len); + if (status >= 0) { + *retlen = len - 8; + status = 0; + }
spi_release_bus(spi);
@@ -256,35 +263,33 @@ static int spi_dataflash_read(struct udevice *dev, u32 offset, size_t len,
/* * Write to the DataFlash device. - * offset : Start offset in flash device + * to : Start offset in flash device * len : Amount to write + * retlen : Amount of data actually written * buf : Buffer containing the data */ -int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) +static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) { - struct dataflash *dataflash; - struct spi_flash *spi_flash; - struct spi_slave *spi; + struct spi_flash *flash = mtd->priv; + struct dataflash *priv = flash->priv; + struct spi_slave *spi = flash->spi; uint8_t *command; - unsigned int pageaddr, addr, to, writelen; + unsigned int pageaddr, addr, offset, writelen; size_t remaining = len; u_char *writebuf = (u_char *)buf; int status = -EINVAL;
- dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); - spi = spi_flash->spi; + memset(priv->command, 0 , sizeof(priv->command)); + command = priv->command;
- memset(dataflash->command, 0 , sizeof(dataflash->command)); - command = dataflash->command; + debug("%s: write 0x%x..0x%x\n", flash->name, (unsigned)to, + (unsigned)(to + len));
- debug("%s: write 0x%x..0x%x\n", dev->name, offset, (offset + len)); - - pageaddr = ((unsigned)offset / spi_flash->page_size); - to = ((unsigned)offset % spi_flash->page_size); - if (to + len > spi_flash->page_size) - writelen = spi_flash->page_size - to; + pageaddr = ((unsigned)to / priv->page_size); + offset = ((unsigned)to % priv->page_size); + if (offset + len > priv->page_size) + writelen = priv->page_size - offset; else writelen = len;
@@ -295,7 +300,7 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, }
while (remaining > 0) { - debug("write @ %d:%d len=%d\n", pageaddr, to, writelen); + debug("write @ %d:%d len=%d\n", pageaddr, offset, writelen);
/* * REVISIT: @@ -314,10 +319,10 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, * support boot-from-DataFlash.) */
- addr = pageaddr << dataflash->page_offset; + addr = pageaddr << priv->page_offset;
/* (1) Maybe transfer partial page to Buffer1 */ - if (writelen != spi_flash->page_size) { + if (writelen != priv->page_size) { command[0] = OP_TRANSFER_BUF1; command[1] = (addr & 0x00FF0000) >> 16; command[2] = (addr & 0x0000FF00) >> 8; @@ -329,20 +334,20 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, status = spi_flash_cmd_write(spi, command, 4, NULL, 0); if (status < 0) { debug("%s: write(<pagesize) command error!\n", - dev->name); + flash->name); return -EIO; }
status = dataflash_waitready(spi); if (status < 0) { debug("%s: write(<pagesize) waitready error!\n", - dev->name); + flash->name); return status; } }
/* (2) Program full page via Buffer1 */ - addr += to; + addr += offset; command[0] = OP_PROGRAM_VIA_BUF1; command[1] = (addr & 0x00FF0000) >> 16; command[2] = (addr & 0x0000FF00) >> 8; @@ -354,19 +359,19 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, status = spi_flash_cmd_write(spi, command, 4, writebuf, writelen); if (status < 0) { - debug("%s: write send command error!\n", dev->name); + debug("%s: write send command error!\n", flash->name); return -EIO; }
status = dataflash_waitready(spi); if (status < 0) { - debug("%s: write waitready error!\n", dev->name); + debug("%s: write waitready error!\n", flash->name); return status; }
#ifdef CONFIG_SPI_DATAFLASH_WRITE_VERIFY /* (3) Compare to Buffer1 */ - addr = pageaddr << dataflash->page_offset; + addr = pageaddr << priv->page_offset; command[0] = OP_COMPARE_BUF1; command[1] = (addr & 0x00FF0000) >> 16; command[2] = (addr & 0x0000FF00) >> 8; @@ -379,7 +384,7 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, 4, writebuf, writelen); if (status < 0) { debug("%s: write(compare) send command error!\n", - dev->name); + flash->name); return -EIO; }
@@ -399,11 +404,12 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, #endif /* CONFIG_SPI_DATAFLASH_WRITE_VERIFY */ remaining = remaining - writelen; pageaddr++; - to = 0; + offset = 0; writebuf += writelen; + *retlen += writelen;
- if (remaining > spi_flash->page_size) - writelen = spi_flash->page_size; + if (remaining > priv->page_size) + writelen = priv->page_size; else writelen = remaining; } @@ -413,32 +419,40 @@ int spi_dataflash_write(struct udevice *dev, u32 offset, size_t len, return 0; }
-static int add_dataflash(struct udevice *dev, char *name, int nr_pages, +static int add_dataflash(struct spi_flash *flash, char *name, int nr_pages, int pagesize, int pageoffset, char revision) { - struct spi_flash *spi_flash; - struct dataflash *dataflash; - - dataflash = dev_get_priv(dev); - spi_flash = dev_get_uclass_priv(dev); + struct mtd_info *mtd = flash->mtd; + struct dataflash *priv = flash->priv; + int ret;
- dataflash->page_offset = pageoffset; + priv->page_size = pagesize; + priv->page_offset = pageoffset;
- spi_flash->name = name; - spi_flash->page_size = pagesize; - spi_flash->size = nr_pages * pagesize; - spi_flash->erase_size = pagesize; + flash->name = name; + mtd->size = nr_pages * pagesize; + mtd->erasesize = pagesize; + mtd->writesize = pagesize; + mtd->type = MTD_DATAFLASH; + mtd->flags = MTD_WRITEABLE; + mtd->_erase = dataflash_erase; + mtd->_read = dataflash_read; + mtd->_write = dataflash_write;
#ifndef CONFIG_SPL_BUILD - printf("SPI DataFlash: Detected %s with page size ", spi_flash->name); - print_size(spi_flash->page_size, ", erase size "); - print_size(spi_flash->erase_size, ", total "); - print_size(spi_flash->size, ""); + printf("SPI DataFlash: Detected %s with page size ", flash->name); + print_size(priv->page_size, ", erase size "); + print_size(mtd->erasesize, ", total "); + print_size(mtd->size, ""); printf(", revision %c", revision); puts("\n"); #endif
- return 0; + ret = add_mtd_device(mtd); + if (ret) + return ret; + + return ret; }
struct flash_info { @@ -583,14 +597,19 @@ static struct flash_info *jedec_probe(struct spi_slave *spi) */ static int spi_dataflash_probe(struct udevice *dev) { - struct spi_slave *spi = dev_get_parent_priv(dev); - struct spi_flash *spi_flash; - struct flash_info *info; + struct dataflash *priv = dev_get_priv(dev); + struct spi_slave *spi = dev_get_parent_priv(dev); + struct spi_flash *flash = dev_get_uclass_priv(dev); + struct flash_info *info; int status;
- spi_flash = dev_get_uclass_priv(dev); - spi_flash->spi = spi; - spi_flash->dev = dev; + flash->mtd = &priv->mtd; + + flash->spi = spi; + flash->priv = priv; + + priv->mtd.priv = flash; + flash->dev = dev;
status = spi_claim_bus(spi); if (status) @@ -607,7 +626,7 @@ static int spi_dataflash_probe(struct udevice *dev) if (IS_ERR(info)) goto err_jedec_probe; if (info != NULL) { - status = add_dataflash(dev, info->name, info->nr_pages, + status = add_dataflash(flash, info->name, info->nr_pages, info->pagesize, info->pageoffset, (info->flags & SUP_POW2PS) ? 'd' : 'c'); if (status < 0) @@ -633,31 +652,31 @@ static int spi_dataflash_probe(struct udevice *dev) */ switch (status & 0x3c) { case 0x0c: /* 0 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB011B", 512, 264, 9, 0); + status = add_dataflash(flash, "AT45DB011B", 512, 264, 9, 0); break; case 0x14: /* 0 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB021B", 1024, 264, 9, 0); + status = add_dataflash(flash, "AT45DB021B", 1024, 264, 9, 0); break; case 0x1c: /* 0 1 1 1 x x */ - status = add_dataflash(dev, "AT45DB041x", 2048, 264, 9, 0); + status = add_dataflash(flash, "AT45DB041x", 2048, 264, 9, 0); break; case 0x24: /* 1 0 0 1 x x */ - status = add_dataflash(dev, "AT45DB081B", 4096, 264, 9, 0); + status = add_dataflash(flash, "AT45DB081B", 4096, 264, 9, 0); break; case 0x2c: /* 1 0 1 1 x x */ - status = add_dataflash(dev, "AT45DB161x", 4096, 528, 10, 0); + status = add_dataflash(flash, "AT45DB161x", 4096, 528, 10, 0); break; case 0x34: /* 1 1 0 1 x x */ - status = add_dataflash(dev, "AT45DB321x", 8192, 528, 10, 0); + status = add_dataflash(flash, "AT45DB321x", 8192, 528, 10, 0); break; case 0x38: /* 1 1 1 x x x */ case 0x3c: - status = add_dataflash(dev, "AT45DB642x", 8192, 1056, 11, 0); + status = add_dataflash(flash, "AT45DB642x", 8192, 1056, 11, 0); break; /* obsolete AT45DB1282 not (yet?) supported */ default: dev_info(&spi->dev, "unsupported device (%x)\n", - status & 0x3c); + status & 0x3c); status = -ENODEV; goto err_status; } @@ -671,12 +690,6 @@ err_jedec_probe: return status; }
-static const struct dm_spi_flash_ops spi_dataflash_ops = { - .read = spi_dataflash_read, - .write = spi_dataflash_write, - .erase = spi_dataflash_erase, -}; - static const struct udevice_id spi_dataflash_ids[] = { { .compatible = "atmel,at45", }, { .compatible = "atmel,dataflash", }, @@ -689,5 +702,4 @@ U_BOOT_DRIVER(spi_dataflash) = { .of_match = spi_dataflash_ids, .probe = spi_dataflash_probe, .priv_auto_alloc_size = sizeof(struct dataflash), - .ops = &spi_dataflash_ops, };

Since dataflash driver is using mtd_info core functionalities this patch renames file and config name similar way as Linux.
Cc: Haikun Wang haikun.wang@freescale.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/Kconfig | 2 +- drivers/mtd/spi/Makefile | 2 +- drivers/mtd/spi/{sf_dataflash.c => mtd_dataflash.c} | 0 include/configs/ls1021aqds.h | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename drivers/mtd/spi/{sf_dataflash.c => mtd_dataflash.c} (100%)
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 78932a4..6e9cc07 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -101,7 +101,7 @@ config SPI_FLASH_USE_4K_SECTORS Please note that some tools/drivers/filesystems may not work with 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
-config SPI_FLASH_DATAFLASH +config MTD_DATAFLASH bool "AT45xxx DataFlash support" depends on SPI_FLASH && DM_SPI_FLASH help diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 5eb4417..780e75f 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -13,5 +13,5 @@ obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o endif
obj-$(CONFIG_SPI_FLASH) += sf_probe.o sf_ops.o sf_params.o sf.o -obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o +obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/mtd_dataflash.c similarity index 100% rename from drivers/mtd/spi/sf_dataflash.c rename to drivers/mtd/spi/mtd_dataflash.c diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h index 00640cd..2ce6eb5 100644 --- a/include/configs/ls1021aqds.h +++ b/include/configs/ls1021aqds.h @@ -423,7 +423,7 @@ unsigned long get_board_ddr_clk(void); #if defined(CONFIG_FSL_DSPI) || defined(CONFIG_FSL_QSPI) #define CONFIG_CMD_SF #define CONFIG_DM_SPI_FLASH -#define CONFIG_SPI_FLASH_DATAFLASH +#define CONFIG_MTD_DATAFLASH #endif #endif

- fix single line comments - remove unneeded spaces - ascending order of include files - rename spi_dataflash_* to dataflash_* - rename SPI DATAFLASH to dataflash - rename SPI DataFlash to dataflash - return NULL replaced with error code
Cc: Haikun Wang haikun.wang@freescale.com Signed-off-by: Jagan Teki jteki@openedev.com --- drivers/mtd/spi/mtd_dataflash.c | 50 +++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 29 deletions(-)
diff --git a/drivers/mtd/spi/mtd_dataflash.c b/drivers/mtd/spi/mtd_dataflash.c index bdface2..65ac5e9 100644 --- a/drivers/mtd/spi/mtd_dataflash.c +++ b/drivers/mtd/spi/mtd_dataflash.c @@ -1,5 +1,4 @@ /* - * * Atmel DataFlash probing * * Copyright (C) 2015 Jagan Teki jteki@openedev.com @@ -7,14 +6,15 @@ * Haikun Wang (haikun.wang@freescale.com) * * SPDX-License-Identifier: GPL-2.0+ -*/ + */ + #include <common.h> +#include <div64.h> #include <dm.h> #include <errno.h> #include <fdtdec.h> #include <spi.h> #include <spi_flash.h> -#include <div64.h> #include <linux/err.h> #include <linux/math64.h> #include <linux/mtd/mtd.h> @@ -69,7 +69,6 @@ #define OP_WRITE_SECURITY_REVC 0x9A #define OP_WRITE_SECURITY 0x9B /* revision D */
- struct dataflash { uint8_t command[16];
@@ -79,9 +78,7 @@ struct dataflash { struct mtd_info mtd; };
-/* - * Return the status of the DataFlash device. - */ +/* Return the status of the DataFlash device */ static inline int dataflash_status(struct spi_slave *spi) { int ret; @@ -120,9 +117,7 @@ static int dataflash_waitready(struct spi_slave *spi) return -ETIME; }
-/* - * Erase pages of flash. - */ +/* Erase pages of flash */ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) { struct spi_flash *flash = mtd->priv; @@ -148,7 +143,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
status = spi_claim_bus(spi); if (status) { - debug("SPI DATAFLASH: unable to claim SPI bus\n"); + debug("dataflash: unable to claim SPI bus\n"); return status; }
@@ -235,7 +230,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
status = spi_claim_bus(spi); if (status) { - debug("SPI DATAFLASH: unable to claim SPI bus\n"); + debug("dataflash: unable to claim SPI bus\n"); return status; }
@@ -295,7 +290,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
status = spi_claim_bus(spi); if (status) { - debug("SPI DATAFLASH: unable to claim SPI bus\n"); + debug("dataflash: unable to claim SPI bus\n"); return status; }
@@ -392,7 +387,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
/* Check result of the compare operation */ if (status & (1 << 6)) { - printf("SPI DataFlash: write compare page %u, err %d\n", + printf("dataflash: write compare page %u, err %d\n", pageaddr, status); remaining = 0; status = -EIO; @@ -440,7 +435,7 @@ static int add_dataflash(struct spi_flash *flash, char *name, int nr_pages, mtd->_write = dataflash_write;
#ifndef CONFIG_SPL_BUILD - printf("SPI DataFlash: Detected %s with page size ", flash->name); + printf("DATAFLASH: Detected %s with page size ", flash->name); print_size(priv->page_size, ", erase size "); print_size(mtd->erasesize, ", total "); print_size(mtd->size, ""); @@ -553,7 +548,7 @@ static struct flash_info *jedec_probe(struct spi_slave *spi) if (info->flags & SUP_POW2PS) { status = dataflash_status(spi); if (status < 0) { - debug("SPI DataFlash: status error %d\n", + debug("dataflash: status error %d\n", status); return NULL; } @@ -575,10 +570,8 @@ static struct flash_info *jedec_probe(struct spi_slave *spi) * size (it might be binary) even when we can tell which density * class is involved (legacy chip id scheme). */ - printf("SPI DataFlash: Unsupported flash IDs: "); - printf("manuf %02x, jedec %04x, ext_jedec %04x\n", - id[0], jedec, id[3] << 8 | id[4]); - return NULL; + printf("dataflash: JEDEC id %06x not handled\n", jedec); + return ERR_PTR(-ENODEV); }
/* @@ -595,7 +588,7 @@ static struct flash_info *jedec_probe(struct spi_slave *spi) * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 */ -static int spi_dataflash_probe(struct udevice *dev) +static int dataflash_probe(struct udevice *dev) { struct dataflash *priv = dev_get_priv(dev); struct spi_slave *spi = dev_get_parent_priv(dev); @@ -633,19 +626,19 @@ static int spi_dataflash_probe(struct udevice *dev) goto err_status; }
- /* + /* * Older chips support only legacy commands, identifing * capacity using bits in the status byte. */ status = dataflash_status(spi); if (status <= 0 || status == 0xff) { - printf("SPI DataFlash: read status error %d\n", status); + printf("dataflash: read status error %d\n", status); if (status == 0 || status == 0xff) status = -ENODEV; goto err_jedec_probe; }
- /* + /* * if there's a device there, assume it's dataflash. * board setup should have set spi->max_speed_max to * match f(car) for continuous reads, mode 0 or 3. @@ -675,8 +668,7 @@ static int spi_dataflash_probe(struct udevice *dev) break; /* obsolete AT45DB1282 not (yet?) supported */ default: - dev_info(&spi->dev, "unsupported device (%x)\n", - status & 0x3c); + printf("dataflash: unsupported device (%x)\n", status & 0x3c); status = -ENODEV; goto err_status; } @@ -690,7 +682,7 @@ err_jedec_probe: return status; }
-static const struct udevice_id spi_dataflash_ids[] = { +static const struct udevice_id dataflash_ids[] = { { .compatible = "atmel,at45", }, { .compatible = "atmel,dataflash", }, { } @@ -699,7 +691,7 @@ static const struct udevice_id spi_dataflash_ids[] = { U_BOOT_DRIVER(spi_dataflash) = { .name = "spi_dataflash", .id = UCLASS_SPI_FLASH, - .of_match = spi_dataflash_ids, - .probe = spi_dataflash_probe, + .of_match = dataflash_ids, + .probe = dataflash_probe, .priv_auto_alloc_size = sizeof(struct dataflash), };

On 26 November 2015 at 17:33, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
Tested whole series except 'sf prot' and dataflash.
Tested-by: Jagan Teki jteki@openedev.com
thanks!

Hi Jagan,
On 26.11.2015 13:24, Jagan Teki wrote:
On 26 November 2015 at 17:33, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
Tested whole series except 'sf prot' and dataflash.
Tested-by: Jagan Teki jteki@openedev.com
Thanks.
BTW: Is this series also tested on a board with SPL_DM and DM_SPI and DM_SPI_FLASH enabled? By loading in SPL the main U-Boot image via SPI NOR flash?
I'm asking since I'm currently struggling to get this working on MVEBU. And am experiencing problems with the DM SPI bus and device probing. Without SPL_DM this is working just fine.
Thanks, Stefan

Hi Stefan,
On 26 November 2015 at 18:02, Stefan Roese sr@denx.de wrote:
Hi Jagan,
On 26.11.2015 13:24, Jagan Teki wrote:
On 26 November 2015 at 17:33, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and
non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
Tested whole series except 'sf prot' and dataflash.
Tested-by: Jagan Teki jteki@openedev.com
Thanks.
BTW: Is this series also tested on a board with SPL_DM and DM_SPI and DM_SPI_FLASH enabled? By loading in SPL the main U-Boot image via SPI NOR flash?
Don't know the reason yet SPL is not working with my microzed board(even with MMC), so I took the fsbl instead of SPL. The combination I have verified with both dm and non-dm cases on u-boot.
Michal, Can you verify the SPI_SPL flow as well.
I'm asking since I'm currently struggling to get this working on MVEBU. And am experiencing problems with the DM SPI bus and device probing. Without SPL_DM this is working just fine.
OK, means you're trying for SPI_SPL with DM is it? what kind of issue? is it failed to probe device or something? I will verify the same and let you know.
thanks!

Hi Jagan,
(added Simon, as he's the DM guru)
On 26.11.2015 13:46, Jagan Teki wrote:
Hi Stefan,
On 26 November 2015 at 18:02, Stefan Roese sr@denx.de wrote:
Hi Jagan,
On 26.11.2015 13:24, Jagan Teki wrote:
On 26 November 2015 at 17:33, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and
non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
Tested whole series except 'sf prot' and dataflash.
Tested-by: Jagan Teki jteki@openedev.com
Thanks.
BTW: Is this series also tested on a board with SPL_DM and DM_SPI and DM_SPI_FLASH enabled? By loading in SPL the main U-Boot image via SPI NOR flash?
Don't know the reason yet SPL is not working with my microzed board(even with MMC), so I took the fsbl instead of SPL. The combination I have verified with both dm and non-dm cases on u-boot.
Michal, Can you verify the SPI_SPL flow as well.
So you have no experience with DM in SPL?
I'm asking since I'm currently struggling to get this working on MVEBU. And am experiencing problems with the DM SPI bus and device probing. Without SPL_DM this is working just fine.
OK, means you're trying for SPI_SPL with DM is it?
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
what kind of issue? is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type | -------------------------------- | 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 | -------------------------------- PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
I will verify the same and let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
Thanks, Stefan

Hi Stefan,
On 26 November 2015 at 18:34, Stefan Roese sr@denx.de wrote:
Hi Jagan,
(added Simon, as he's the DM guru)
I think you missed adding Simon + Simon
On 26.11.2015 13:46, Jagan Teki wrote:
Hi Stefan,
On 26 November 2015 at 18:02, Stefan Roese sr@denx.de wrote:
Hi Jagan,
On 26.11.2015 13:24, Jagan Teki wrote:
On 26 November 2015 at 17:33, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and
non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
Tested whole series except 'sf prot' and dataflash.
Tested-by: Jagan Teki jteki@openedev.com
Thanks.
BTW: Is this series also tested on a board with SPL_DM and DM_SPI and DM_SPI_FLASH enabled? By loading in SPL the main U-Boot image via SPI NOR flash?
Don't know the reason yet SPL is not working with my microzed board(even with MMC), so I took the fsbl instead of SPL. The combination I have verified with both dm and non-dm cases on u-boot.
Michal, Can you verify the SPI_SPL flow as well.
So you have no experience with DM in SPL?
I'm asking since I'm currently struggling to get this working on MVEBU. And am experiencing problems with the DM SPI bus and device probing. Without SPL_DM this is working just fine.
OK, means you're trying for SPI_SPL with DM is it?
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
what kind of issue? is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0
- -1 -1
- not found
bind node serial@12000
- found match at 'ns16550_serial'
Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0
- -1 -1
- not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type |
| 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 |
PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0
- not found
uclass_find_device_by_seq: 1 0
- not found
Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
I will verify the same and let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
I'm saying I shall also debug this further.
thanks!

Hi Stefan,
On 26 November 2015 at 05:04, Stefan Roese sr@denx.de wrote:
Hi Jagan,
(added Simon, as he's the DM guru)
On 26.11.2015 13:46, Jagan Teki wrote:
Hi Stefan,
On 26 November 2015 at 18:02, Stefan Roese sr@denx.de wrote:
Hi Jagan,
On 26.11.2015 13:24, Jagan Teki wrote:
On 26 November 2015 at 17:33, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and
non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
Tested whole series except 'sf prot' and dataflash.
Tested-by: Jagan Teki jteki@openedev.com
Thanks.
BTW: Is this series also tested on a board with SPL_DM and DM_SPI and DM_SPI_FLASH enabled? By loading in SPL the main U-Boot image via SPI NOR flash?
Don't know the reason yet SPL is not working with my microzed board(even with MMC), so I took the fsbl instead of SPL. The combination I have verified with both dm and non-dm cases on u-boot.
Michal, Can you verify the SPI_SPL flow as well.
So you have no experience with DM in SPL?
I'm asking since I'm currently struggling to get this working on MVEBU. And am experiencing problems with the DM SPI bus and device probing. Without SPL_DM this is working just fine.
OK, means you're trying for SPI_SPL with DM is it?
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
what kind of issue? is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0
- -1 -1
- not found
bind node serial@12000
- found match at 'ns16550_serial'
Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0
- -1 -1
- not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type |
| 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 |
PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0
- not found
uclass_find_device_by_seq: 1 0
- not found
Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
I will verify the same and let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
-19 means -ENODEV. I suppose CONFIG_SPL_OF_CONTROL is enabled. You can check the device tree used for SPL in your build directory - spl/u-boot-spl.dtb.
From the debugging it looks like you have no SPI flash devices.
You can check chromebook_jerry which uses this feature. See this node:
&spi2 { status = "okay"; u-boot,dm-pre-reloc;
spi_flash: spiflash@0 { u-boot,dm-pre-reloc; compatible = "spidev", "spi-flash"; spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */ reg = <0>; }; };
Regards, Simon

Hi Simon,
On 26.11.2015 17:48, Simon Glass wrote:
<snip>
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
what kind of issue? is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type |
| 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 |
PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
I will verify the same and let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
-19 means -ENODEV. I suppose CONFIG_SPL_OF_CONTROL is enabled.
Yes.
You can check the device tree used for SPL in your build directory - spl/u-boot-spl.dtb.
From the debugging it looks like you have no SPI flash devices.
That is my understanding as well. And I fail to see, where this device get added to the list of UCLASS devices.
You can check chromebook_jerry which uses this feature. See this node:
&spi2 { status = "okay"; u-boot,dm-pre-reloc;
spi_flash: spiflash@0 { u-boot,dm-pre-reloc; compatible = "spidev", "spi-flash"; spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */ reg = <0>; };
};
I've checked this now and reworked the dts a bit. But still no cigar. The debug output is identical to the last one.
I've attached the dts / dtb and the current .config. It would be great if you could take a quick look at it to see, what I am missing here.
Thanks, Stefan

Hi Stefan,
On 26 November 2015 at 09:47, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 17:48, Simon Glass wrote:
<snip>
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
what kind of issue? is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type |
| 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 |
PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
I will verify the same and let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
-19 means -ENODEV. I suppose CONFIG_SPL_OF_CONTROL is enabled.
Yes.
You can check the device tree used for SPL in your build directory - spl/u-boot-spl.dtb.
From the debugging it looks like you have no SPI flash devices.
That is my understanding as well. And I fail to see, where this device get added to the list of UCLASS devices.
You can check chromebook_jerry which uses this feature. See this node:
&spi2 { status = "okay"; u-boot,dm-pre-reloc;
spi_flash: spiflash@0 { u-boot,dm-pre-reloc; compatible = "spidev", "spi-flash"; spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */ reg = <0>; };
};
I've checked this now and reworked the dts a bit. But still no cigar. The debug output is identical to the last one.
I've attached the dts / dtb and the current .config. It would be great if you could take a quick look at it to see, what I am missing here.
CONFIG_SPL_OF_TRANSLATE should be defined I think, and also you need a u-boot,dm-pre-reloc in the soc {} node, otherwise the properties there will not appear.
You can call dm_dump_all() in SPL, and dm_dump_uclass(), to see what devices are present.
Regards, Simon

Hi Simon,
On 26.11.2015 18:55, Simon Glass wrote:
Hi Stefan,
On 26 November 2015 at 09:47, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 17:48, Simon Glass wrote:
<snip>
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
what kind of issue? is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type |
| 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 |
PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
I will verify the same and let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
-19 means -ENODEV. I suppose CONFIG_SPL_OF_CONTROL is enabled.
Yes.
You can check the device tree used for SPL in your build directory - spl/u-boot-spl.dtb.
From the debugging it looks like you have no SPI flash devices.
That is my understanding as well. And I fail to see, where this device get added to the list of UCLASS devices.
You can check chromebook_jerry which uses this feature. See this node:
&spi2 { status = "okay"; u-boot,dm-pre-reloc;
spi_flash: spiflash@0 { u-boot,dm-pre-reloc; compatible = "spidev", "spi-flash"; spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */ reg = <0>; };
};
I've checked this now and reworked the dts a bit. But still no cigar. The debug output is identical to the last one.
I've attached the dts / dtb and the current .config. It would be great if you could take a quick look at it to see, what I am missing here.
CONFIG_SPL_OF_TRANSLATE should be defined I think,
Yes. But this does not explain why this device is not found at all. This would only result in an incorrect base-address. And this works since the serial node seems to be okay (DM in SPL here as well).
and also you need a u-boot,dm-pre-reloc in the soc {} node, otherwise the properties there will not appear.
Its already there in the dtsi file. I've added it again in this dts file as well.
You can call dm_dump_all() in SPL, and dm_dump_uclass(), to see what devices are present.
Ah, this is helpful. Thanks. Here the output for your profound inspection: ;)
Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. Class Probed Name ---------------------------------------- root [ + ] root_driver serial [ + ] `-- serial@12000 uclass 0: root - * root_driver @ 40029f18, seq 0, (req -1)
Cannot find uclass for id 1: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 2: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 3: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 4: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 5: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 6: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 7: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 8: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 9: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 10: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 11: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 12: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 13: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 14: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 15: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 16: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 17: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 18: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 19: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 20: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 21: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 22: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 23: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 24: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 25: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 26: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 27: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 28: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 29: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 30: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 31: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 32: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 33: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 34: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 35: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 36: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 37: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 38: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 39: please add the UCLASS_DRIVER() declaration for this UCLASS_... id uclass 40: serial - * serial@12000 @ 40029f84, seq 0, (req -1)
uclass 41: spi uclass 42: spi_flash uclass 43: spi_generic Cannot find uclass for id 44: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 45: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 46: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 47: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 48: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 49: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 50: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 51: please add the UCLASS_DRIVER() declaration for this UCLASS_... id SPL: failed to boot from all boot devices
Any more ideas? Can you send me the output of these *dump* functions on the chromebook_jerry please?
Thanks, Stefan

Hi Stefan,
On 26 November 2015 at 10:12, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 18:55, Simon Glass wrote:
Hi Stefan,
On 26 November 2015 at 09:47, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 17:48, Simon Glass wrote:
<snip>
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
what kind of issue? is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type |
| 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 |
PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
I will verify the same and let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
-19 means -ENODEV. I suppose CONFIG_SPL_OF_CONTROL is enabled.
Yes.
You can check the device tree used for SPL in your build directory - spl/u-boot-spl.dtb.
From the debugging it looks like you have no SPI flash devices.
That is my understanding as well. And I fail to see, where this device get added to the list of UCLASS devices.
You can check chromebook_jerry which uses this feature. See this node:
&spi2 { status = "okay"; u-boot,dm-pre-reloc;
spi_flash: spiflash@0 { u-boot,dm-pre-reloc; compatible = "spidev", "spi-flash"; spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */ reg = <0>; };
};
I've checked this now and reworked the dts a bit. But still no cigar. The debug output is identical to the last one.
I've attached the dts / dtb and the current .config. It would be great if you could take a quick look at it to see, what I am missing here.
CONFIG_SPL_OF_TRANSLATE should be defined I think,
Yes. But this does not explain why this device is not found at all. This would only result in an incorrect base-address. And this works since the serial node seems to be okay (DM in SPL here as well).
and also you need a u-boot,dm-pre-reloc in the soc {} node, otherwise the properties there will not appear.
Its already there in the dtsi file. I've added it again in this dts file as well.
You can call dm_dump_all() in SPL, and dm_dump_uclass(), to see what devices are present.
Ah, this is helpful. Thanks. Here the output for your profound inspection: ;)
Trying to boot from SPI uclass_find_device_by_seq: 0 0
- not found
uclass_find_device_by_seq: 1 0
- not found
Invalid bus 0 (err=-19) SPI probe failed. Class Probed Name
root [ + ] root_driver serial [ + ] `-- serial@12000
That shows that the SPI device or driver is not being found. I don't see a driver for 'marvell,armada-380-spi' in the tree anyway - is it your own private patches?
If you add DEBUG to drivers/core/lists.c you may be able to see why it is not finding a driver for that node.
uclass 0: root
- root_driver @ 40029f18, seq 0, (req -1)
Cannot find uclass for id 1: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 2: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 3: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 4: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 5: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 6: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 7: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 8: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 9: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 10: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 11: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 12: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 13: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 14: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 15: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 16: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 17: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 18: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 19: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 20: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 21: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 22: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 23: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 24: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 25: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 26: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 27: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 28: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 29: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 30: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 31: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 32: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 33: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 34: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 35: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 36: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 37: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 38: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 39: please add the UCLASS_DRIVER() declaration for this UCLASS_... id uclass 40: serial
- serial@12000 @ 40029f84, seq 0, (req -1)
uclass 41: spi uclass 42: spi_flash uclass 43: spi_generic Cannot find uclass for id 44: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 45: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 46: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 47: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 48: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 49: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 50: please add the UCLASS_DRIVER() declaration for this UCLASS_... id Cannot find uclass for id 51: please add the UCLASS_DRIVER() declaration for this UCLASS_... id SPL: failed to boot from all boot devices
Any more ideas? Can you send me the output of these *dump* functions on the chromebook_jerry please?
I can do that when I am back next week...but I'm pretty sure it would show the SPI and SPI flash to be available.
Regards, Simon

Hi Simon,
On 26.11.2015 19:22, Simon Glass wrote:
Hi Stefan,
On 26 November 2015 at 10:12, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 18:55, Simon Glass wrote:
Hi Stefan,
On 26 November 2015 at 09:47, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 17:48, Simon Glass wrote:
<snip>
Yes. I'm trying to enable SPL_DM on MVEBU. And this with DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood SPI driver ported to DM here for this (patches will follow).
> what kind of issue? > is it failed to probe device or something?
Here the log (with some debug() enabled):
----------<------------------------------- uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver uclass_find_device_by_seq: 0 -1 uclass_find_device_by_seq: 0 0 - -1 -1 - not found
U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) High speed PHY - Version: 2.0 Detected Device ID 6828 board SerDes lanes topology details: | Lane # | Speed | Type | -------------------------------- | 0 | 5 | PCIe0 | | 1 | 3 | SATA0 | | 2 | 3 | SATA1 | | 3 | 3 | SATA3 | | 4 | 3 | SATA2 | | 5 | 5 | USB3 HOST1 | -------------------------------- PCIe, Idx 0: detected no link High speed PHY - Ended Successfully DDR3 Training Sequence - Ver TIP-1.29.0 DDR3 Training Sequence - Switching XBAR Window to FastPath Window DDR3 Training Sequence - Ended Successfully Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### ----------<-------------------------------
Simon, do you have a clue what's missing here? SPI NOR booting is working just fine in SPL without SPL_DM enabled on this platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" properties to the dts.
> I will verify the same and > let you know.
How can you verify this if SPI is not working at all for you? Or did I misunderstand you (see above)?
-19 means -ENODEV. I suppose CONFIG_SPL_OF_CONTROL is enabled.
Yes.
You can check the device tree used for SPL in your build directory - spl/u-boot-spl.dtb.
From the debugging it looks like you have no SPI flash devices.
That is my understanding as well. And I fail to see, where this device get added to the list of UCLASS devices.
You can check chromebook_jerry which uses this feature. See this node:
&spi2 { status = "okay"; u-boot,dm-pre-reloc;
spi_flash: spiflash@0 { u-boot,dm-pre-reloc; compatible = "spidev", "spi-flash"; spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */ reg = <0>; };
};
I've checked this now and reworked the dts a bit. But still no cigar. The debug output is identical to the last one.
I've attached the dts / dtb and the current .config. It would be great if you could take a quick look at it to see, what I am missing here.
CONFIG_SPL_OF_TRANSLATE should be defined I think,
Yes. But this does not explain why this device is not found at all. This would only result in an incorrect base-address. And this works since the serial node seems to be okay (DM in SPL here as well).
and also you need a u-boot,dm-pre-reloc in the soc {} node, otherwise the properties there will not appear.
Its already there in the dtsi file. I've added it again in this dts file as well.
You can call dm_dump_all() in SPL, and dm_dump_uclass(), to see what devices are present.
Ah, this is helpful. Thanks. Here the output for your profound inspection: ;)
Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. Class Probed Name
root [ + ] root_driver serial [ + ] `-- serial@12000
That shows that the SPI device or driver is not being found. I don't see a driver for 'marvell,armada-380-spi' in the tree anyway - is it your own private patches?
Yes, this is in my local tree - waiting for this issue to get resolved before sending to the list.
If you add DEBUG to drivers/core/lists.c you may be able to see why it is not finding a driver for that node.
"#define DEBUG" is already set in lists.c.
I have the notion that drivers are not added "automatically" to the lists. My debugging has shown that for example the serial driver is only added to the list after this call in serial-uclass.c:
lists_bind_fdt(gd->dm_root, blob, node, &dev)
Before this call, I have this output from dm_dump_all():
Class Probed Name ---------------------------------------- root [ + ] root_driver
Then, calling lists_bind_fdt() results in this debug output:
bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver
And now, dm_dump_all() shows this directly after the lists_bind_fdt():
Class Probed Name ---------------------------------------- root [ + ] root_driver serial [ ] `-- serial@12000
Seems that drivers need to get actively "binded" to the lists. And this is not happening for the SPI driver.
What am I missing?
Thanks, Stefan

Hi Simon,
On 27.11.2015 05:01, Stefan Roese wrote:
Hi Simon,
On 26.11.2015 19:22, Simon Glass wrote:
Hi Stefan,
On 26 November 2015 at 10:12, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 18:55, Simon Glass wrote:
Hi Stefan,
On 26 November 2015 at 09:47, Stefan Roese sr@denx.de wrote:
Hi Simon,
On 26.11.2015 17:48, Simon Glass wrote:
<snip>
> Yes. I'm trying to enable SPL_DM on MVEBU. And this with > DM_SPI and DM_SPI_FLASH enabled as well. I've the kirkwood > SPI driver ported to DM here for this (patches will follow). > >> what kind of issue? >> is it failed to probe device or something? > > > Here the log (with some debug() enabled): > > ----------<------------------------------- > uclass_find_device_by_seq: 0 -1 > uclass_find_device_by_seq: 0 0 > - -1 -1 > - not found > bind node serial@12000 > - found match at 'ns16550_serial' > Bound device serial@12000 to root_driver > uclass_find_device_by_seq: 0 -1 > uclass_find_device_by_seq: 0 0 > - -1 -1 > - not found > > U-Boot SPL 2016.01-rc1-00267-gdb3362c-dirty (Nov 26 2015 - 14:00:16) > High speed PHY - Version: 2.0 > Detected Device ID 6828 > board SerDes lanes topology details: > | Lane # | Speed | Type | > -------------------------------- > | 0 | 5 | PCIe0 | > | 1 | 3 | SATA0 | > | 2 | 3 | SATA1 | > | 3 | 3 | SATA3 | > | 4 | 3 | SATA2 | > | 5 | 5 | USB3 HOST1 | > -------------------------------- > PCIe, Idx 0: detected no link > High speed PHY - Ended Successfully > DDR3 Training Sequence - Ver TIP-1.29.0 > DDR3 Training Sequence - Switching XBAR Window to FastPath Window > DDR3 Training Sequence - Ended Successfully > Trying to boot from SPI > uclass_find_device_by_seq: 0 0 > - not found > uclass_find_device_by_seq: 1 0 > - not found > Invalid bus 0 (err=-19) > SPI probe failed. > SPL: failed to boot from all boot devices > ### ERROR ### Please RESET the board ### > ----------<------------------------------- > > Simon, do you have a clue what's missing here? SPI NOR booting > is working just fine in SPL without SPL_DM enabled on this > platform. AFAICT, I've added the required "u-boot,dm-pre-reloc" > properties to the dts. > >> I will verify the same and >> let you know. > > > How can you verify this if SPI is not working at all for you? Or > did I misunderstand you (see above)?
-19 means -ENODEV. I suppose CONFIG_SPL_OF_CONTROL is enabled.
Yes.
You can check the device tree used for SPL in your build directory - spl/u-boot-spl.dtb.
From the debugging it looks like you have no SPI flash devices.
That is my understanding as well. And I fail to see, where this device get added to the list of UCLASS devices.
You can check chromebook_jerry which uses this feature. See this node:
&spi2 { status = "okay"; u-boot,dm-pre-reloc;
spi_flash: spiflash@0 { u-boot,dm-pre-reloc; compatible = "spidev", "spi-flash"; spi-max-frequency = <20000000>; /* Reduce for Dediprog
em100 pro */ reg = <0>; }; };
I've checked this now and reworked the dts a bit. But still no cigar. The debug output is identical to the last one.
I've attached the dts / dtb and the current .config. It would be great if you could take a quick look at it to see, what I am missing here.
CONFIG_SPL_OF_TRANSLATE should be defined I think,
Yes. But this does not explain why this device is not found at all. This would only result in an incorrect base-address. And this works since the serial node seems to be okay (DM in SPL here as well).
and also you need a u-boot,dm-pre-reloc in the soc {} node, otherwise the properties there will not appear.
Its already there in the dtsi file. I've added it again in this dts file as well.
You can call dm_dump_all() in SPL, and dm_dump_uclass(), to see what devices are present.
Ah, this is helpful. Thanks. Here the output for your profound inspection: ;)
Trying to boot from SPI uclass_find_device_by_seq: 0 0 - not found uclass_find_device_by_seq: 1 0 - not found Invalid bus 0 (err=-19) SPI probe failed. Class Probed Name
root [ + ] root_driver serial [ + ] `-- serial@12000
That shows that the SPI device or driver is not being found. I don't see a driver for 'marvell,armada-380-spi' in the tree anyway - is it your own private patches?
Yes, this is in my local tree - waiting for this issue to get resolved before sending to the list.
If you add DEBUG to drivers/core/lists.c you may be able to see why it is not finding a driver for that node.
"#define DEBUG" is already set in lists.c.
I have the notion that drivers are not added "automatically" to the lists. My debugging has shown that for example the serial driver is only added to the list after this call in serial-uclass.c:
lists_bind_fdt(gd->dm_root, blob, node, &dev)
Before this call, I have this output from dm_dump_all():
Class Probed Name
root [ + ] root_driver
Then, calling lists_bind_fdt() results in this debug output:
bind node serial@12000 - found match at 'ns16550_serial' Bound device serial@12000 to root_driver
And now, dm_dump_all() shows this directly after the lists_bind_fdt():
Class Probed Name
root [ + ] root_driver serial [ ] `-- serial@12000
Seems that drivers need to get actively "binded" to the lists. And this is not happening for the SPI driver.
What am I missing?
I finally found it. I had CONFIG_SPL_SIMPLE_BUS disabled. So all devices behind this "simple-bus" where not visible to DM. Now this looks much better.
Thanks, Stefan

+Fabio
Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
This seems to build on the patch which adds the flash locking stuff for non-DM SPI flash - commit c3c016cf. When I asked about this a week ago Tom mentioned that Fabio was going to fix this up so that it supports driver model.
As I tried to explain last time I reviewed this, the problem with this series is that it adds new functionality to non-DM code. In fact this series takes a backwards step, since it plumbs in DM SPI flash to non-DM SPI MTD, since the latter does not support driver model.
I am obviously failing to explain what I mean here - let me try again...
Function methods should be implemented as 'ops' structs in driver model and use the 'ops' member of the driver to provide the implementation. There should be no other function pointers or structs of function pointers.
Drivers should be declared as DM drivers, and devices should be created by driver model when it finds a definition in the device tree, or dynamically if needed for probing buses (e.g. PCI, USB, I2C in some cases). There should not be calls to 'register' and memory allocations. That is a sign that you are bypassing driver model for these things.
I do understand that the SPI flash DM conversion is incomplete - there are still many boards which have yet to be converted for SPI or SPI flash. Until that is done I think the efforts should be directed towards that goal, and things like SPI MTD should be introduced for DM only. At present it seems that we have created yet another migration task (SPI MTD) that would be better avoided.
I know you have sent detailed emails about the software layers, etc. I do understand that (or at least I think I do), but in the DM world, each layer should be a uclass with its own API and its own devices.
How can we move forward on this and get everything moved over to DM in short order?
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
common/cmd_sf.c | 16 +- drivers/mtd/spi/Kconfig | 14 +- drivers/mtd/spi/Makefile | 9 +- .../mtd/spi/{sf_dataflash.c => mtd_dataflash.c} | 402 ++++++----- drivers/mtd/spi/sf-uclass.c | 39 -- drivers/mtd/spi/sf_internal.h | 74 +- drivers/mtd/spi/sf_mtd.c | 104 --- drivers/mtd/spi/sf_ops.c | 769 ++++++++++++++++----- drivers/mtd/spi/sf_probe.c | 508 ++------------ include/configs/aristainetos-common.h | 1 - include/configs/gw_ventana.h | 1 - include/configs/ls1021aqds.h | 2 +- include/configs/socfpga_common.h | 1 - include/configs/zynq-common.h | 1 + include/spi_flash.h | 163 ++--- 15 files changed, 926 insertions(+), 1178 deletions(-) rename drivers/mtd/spi/{sf_dataflash.c => mtd_dataflash.c} (64%) delete mode 100644 drivers/mtd/spi/sf_mtd.c
-- 1.9.1
Regards, Simon

Hi Simon,
Some how I'm unclear about your comments in previous series probably I my misunderstanding or something. let me explain about my plan on spi-nor development.
The entire spi-flash code is generic for all means there is no separate code for any platform or device. So I call it as spi-flash core. spi-flash core having functionaries like read_jedec, flash read/write/erase all these were calling from cmd_sf using dm and non-dm version, here I'm replacing this MTD since it is core interface it doesn't handle any specific device or uclass and mtd operations are being used directly without any dm except the probe.
So spi-flash shouldn't need dm and the respective probe sf_probe will follow dm as it allocates spi_flash and by taking spi_slave{} setup spi-uclass. spi-flash operation are common and there is no different ops for different drivers or devices or something and mtd_ops are manged directly from cmd_sf like nand and spi-nor in Linux.
And once core sits stable spi-flash will implemented as spi-nor core and the bellowed drivers becomes spi-nor drivers like spi-nor to spi driver interface and spi-nor controller drivers these are dm-driven it's having dm ops similar to spi-flash ops and spi-flash no where required.
cmd_sf ======= MTD ======= spi-nor or spi-flash =============== "spi-nor to spi drivers" and spi-nor controller driver =======================================
On 26 November 2015 at 23:20, Simon Glass sjg@chromium.org wrote:
+Fabio
Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
This seems to build on the patch which adds the flash locking stuff for non-DM SPI flash - commit c3c016cf. When I asked about this a week ago Tom mentioned that Fabio was going to fix this up so that it supports driver model.
As I tried to explain last time I reviewed this, the problem with this series is that it adds new functionality to non-DM code. In fact this series takes a backwards step, since it plumbs in DM SPI flash to non-DM SPI MTD, since the latter does not support driver model.
"adds new functionality to non-DM code." means code with #ifndef CONFIG_DM_SPI_FLASH sf_probe.c? ie because for mtd should available for non-dm drivers as well. Once all move to dm this will drop anyway.
I am obviously failing to explain what I mean here - let me try again...
Function methods should be implemented as 'ops' structs in driver model and use the 'ops' member of the driver to provide the implementation. There should be no other function pointers or structs of function pointers.
Drivers should be declared as DM drivers, and devices should be created by driver model when it finds a definition in the device tree, or dynamically if needed for probing buses (e.g. PCI, USB, I2C in some cases). There should not be calls to 'register' and memory allocations. That is a sign that you are bypassing driver model for these things.
I do understand that the SPI flash DM conversion is incomplete - there are still many boards which have yet to be converted for SPI or SPI flash. Until that is done I think the efforts should be directed towards that goal, and things like SPI MTD should be introduced for DM only. At present it seems that we have created yet another migration task (SPI MTD) that would be better avoided.
I know you have sent detailed emails about the software layers, etc. I do understand that (or at least I think I do), but in the DM world, each layer should be a uclass with its own API and its own devices.
How can we move forward on this and get everything moved over to DM in short order?
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
common/cmd_sf.c | 16 +- drivers/mtd/spi/Kconfig | 14 +- drivers/mtd/spi/Makefile | 9 +- .../mtd/spi/{sf_dataflash.c => mtd_dataflash.c} | 402 ++++++----- drivers/mtd/spi/sf-uclass.c | 39 -- drivers/mtd/spi/sf_internal.h | 74 +- drivers/mtd/spi/sf_mtd.c | 104 --- drivers/mtd/spi/sf_ops.c | 769 ++++++++++++++++----- drivers/mtd/spi/sf_probe.c | 508 ++------------ include/configs/aristainetos-common.h | 1 - include/configs/gw_ventana.h | 1 - include/configs/ls1021aqds.h | 2 +- include/configs/socfpga_common.h | 1 - include/configs/zynq-common.h | 1 + include/spi_flash.h | 163 ++--- 15 files changed, 926 insertions(+), 1178 deletions(-) rename drivers/mtd/spi/{sf_dataflash.c => mtd_dataflash.c} (64%) delete mode 100644 drivers/mtd/spi/sf_mtd.c
thanks!

Hi Jagan,
On Fri, Nov 27, 2015 at 2:54 AM, Jagan Teki jteki@openedev.com wrote:
Hi Simon,
Some how I'm unclear about your comments in previous series probably I my misunderstanding or something. let me explain about my plan on spi-nor development.
The entire spi-flash code is generic for all means there is no separate code for any platform or device. So I call it as spi-flash core. spi-flash core having functionaries like read_jedec, flash read/write/erase all these were calling from cmd_sf using dm and non-dm version, here I'm replacing this MTD since it is core interface it doesn't handle any specific device or uclass and mtd operations are being used directly without any dm except the probe.
So spi-flash shouldn't need dm and the respective probe sf_probe will follow dm as it allocates spi_flash and by taking spi_slave{} setup spi-uclass. spi-flash operation are common and there is no different ops for different drivers or devices or something and mtd_ops are manged directly from cmd_sf like nand and spi-nor in Linux.
And once core sits stable spi-flash will implemented as spi-nor core and the bellowed drivers becomes spi-nor drivers like spi-nor to spi driver interface and spi-nor controller drivers these are dm-driven it's having dm ops similar to spi-flash ops and spi-flash no where required.
My understanding is that when we introduce a new driver feature, it should target driver model by default. This is to encourage boards to take advantage of driver model, and all these *new* features. This is what Simon asked for. As Simon mentioned, probably we should make the SPI flash DM conversion complete now instead of adding any new feature on top of it.
cmd_sf
MTD
spi-nor or spi-flash
"spi-nor to spi drivers" and spi-nor controller driver
[snip]
Regards, Bin

Hi Bin,
On 27 November 2015 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Jagan,
On Fri, Nov 27, 2015 at 2:54 AM, Jagan Teki jteki@openedev.com wrote:
Hi Simon,
Some how I'm unclear about your comments in previous series probably I my misunderstanding or something. let me explain about my plan on spi-nor development.
The entire spi-flash code is generic for all means there is no separate code for any platform or device. So I call it as spi-flash core. spi-flash core having functionaries like read_jedec, flash read/write/erase all these were calling from cmd_sf using dm and non-dm version, here I'm replacing this MTD since it is core interface it doesn't handle any specific device or uclass and mtd operations are being used directly without any dm except the probe.
So spi-flash shouldn't need dm and the respective probe sf_probe will follow dm as it allocates spi_flash and by taking spi_slave{} setup spi-uclass. spi-flash operation are common and there is no different ops for different drivers or devices or something and mtd_ops are manged directly from cmd_sf like nand and spi-nor in Linux.
And once core sits stable spi-flash will implemented as spi-nor core and the bellowed drivers becomes spi-nor drivers like spi-nor to spi driver interface and spi-nor controller drivers these are dm-driven it's having dm ops similar to spi-flash ops and spi-flash no where required.
My understanding is that when we introduce a new driver feature, it should target driver model by default. This is to encourage boards to take advantage of driver model, and all these *new* features. This is what Simon asked for. As Simon mentioned, probably we should make the SPI flash DM conversion complete now instead of adding any new feature on top of it.
I'm not introduced any new driver feature here, instead I re-used the existing mtd core features and functionalities.
The current code looks as below: -------------------------------------------- sf_probe.c: 1) having both non-dm and dm spi-flash and calls to 2) spi_flash_probe_slave for spi_flash detection and setting up hooks (spi_flash ops)
sf_ops.c: 1) having all spi_flash ops definitions.
These are the changes I did a) Moved spi_flash probing like definition of spi_flash_probe_slave from sf_probe.c to sf_ops.c so sf_ops.c having all core spi-flash code like flash detection, setting up hooks (spi_flash ops) and spi_flash ops definitions. b) from above point a) sf_probe.c having both dm and non-dm interface with a common call to sf_ops.c for spi-flash core functionalities using spi_flash_scan. c) Replaced existing spi_flash_mtd_register (sf_mtd.c) registration with generic mtd core using add_mtd_device in sf_probe.c for both dm and non-dm interfaces. d) In sf_ops.c Updated all mtd_info structure filling and replaced spi_flash ops hooks with mtd_info hooks - where dm_spi_flash_ops got dropped. e) Called mtd core operations from spi_flash.h like mtd_erase|write|read instead of direct calls to sf_ops.c with spi_flash operation as they are not needed, so mtd core calls will in turn call mtd hooks on spi-flash like nand, cfi and spi-nor in Linux.
The code after these changes: ---------------------------------------- sf_probe.c: 1) having both non-dm and dm spi-flash and calls to 2) spi_flash_scan for spi-flash core functionalities and register with core mtd.
sf_ops.c: 1) core spi-flash operations => spi_flash detection + setting up hooks (mtd ops) + having all mtd_info ops definitions.
I couldn't understand what's wrong with this approach, because I have not added any new feature instead I reused it existing MTD core. I agree that the dm_spi_flash_ops are removed as mtd_info ops are used instead and sf_probe.c is still with dm.
Please let me know your inputs.
cmd_sf
MTD
spi-nor or spi-flash
"spi-nor to spi drivers" and spi-nor controller driver
thanks!

Hi Jagan,
On 27 November 2015 at 02:21, Jagan Teki jteki@openedev.com wrote:
Hi Bin,
On 27 November 2015 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Jagan,
On Fri, Nov 27, 2015 at 2:54 AM, Jagan Teki jteki@openedev.com wrote:
Hi Simon,
Some how I'm unclear about your comments in previous series probably I my misunderstanding or something. let me explain about my plan on spi-nor development.
The entire spi-flash code is generic for all means there is no separate code for any platform or device. So I call it as spi-flash core. spi-flash core having functionaries like read_jedec, flash read/write/erase all these were calling from cmd_sf using dm and non-dm version, here I'm replacing this MTD since it is core interface it doesn't handle any specific device or uclass and mtd operations are being used directly without any dm except the probe.
So spi-flash shouldn't need dm and the respective probe sf_probe will follow dm as it allocates spi_flash and by taking spi_slave{} setup spi-uclass. spi-flash operation are common and there is no different ops for different drivers or devices or something and mtd_ops are manged directly from cmd_sf like nand and spi-nor in Linux.
And once core sits stable spi-flash will implemented as spi-nor core and the bellowed drivers becomes spi-nor drivers like spi-nor to spi driver interface and spi-nor controller drivers these are dm-driven it's having dm ops similar to spi-flash ops and spi-flash no where required.
My understanding is that when we introduce a new driver feature, it should target driver model by default. This is to encourage boards to take advantage of driver model, and all these *new* features. This is what Simon asked for. As Simon mentioned, probably we should make the SPI flash DM conversion complete now instead of adding any new feature on top of it.
I'm not introduced any new driver feature here, instead I re-used the existing mtd core features and functionalities.
The current code looks as below:
sf_probe.c:
- having both non-dm and dm spi-flash and calls to
- spi_flash_probe_slave for spi_flash detection and setting up hooks
(spi_flash ops)
sf_ops.c:
- having all spi_flash ops definitions.
These are the changes I did a) Moved spi_flash probing like definition of spi_flash_probe_slave from sf_probe.c to sf_ops.c so sf_ops.c having all core spi-flash code like flash detection, setting up hooks (spi_flash ops) and spi_flash ops definitions. b) from above point a) sf_probe.c having both dm and non-dm interface with a common call to sf_ops.c for spi-flash core functionalities using spi_flash_scan. c) Replaced existing spi_flash_mtd_register (sf_mtd.c) registration with generic mtd core using add_mtd_device in sf_probe.c for both dm and non-dm interfaces. d) In sf_ops.c Updated all mtd_info structure filling and replaced spi_flash ops hooks with mtd_info hooks - where dm_spi_flash_ops got dropped. e) Called mtd core operations from spi_flash.h like mtd_erase|write|read instead of direct calls to sf_ops.c with spi_flash operation as they are not needed, so mtd core calls will in turn call mtd hooks on spi-flash like nand, cfi and spi-nor in Linux.
The code after these changes:
sf_probe.c:
- having both non-dm and dm spi-flash and calls to
- spi_flash_scan for spi-flash core functionalities and register with core mtd.
sf_ops.c:
- core spi-flash operations => spi_flash detection + setting up hooks
(mtd ops) + having all mtd_info ops definitions.
I couldn't understand what's wrong with this approach, because I have not added any new feature instead I reused it existing MTD core. I agree that the dm_spi_flash_ops are removed as mtd_info ops are used instead and sf_probe.c is still with dm.
Please let me know your inputs.
Conceptually this seems problematic.
SPI flash is a uclass and supports driver model. It has operations, etc. Your patches remove the operations in favour of calling MTD. But MTD does not support driver model. This is getting really messy.
Before going any further we need to at least figure out the end goal.
To repeat my question from the previous email:
Is it intended that SPI flash should be a driver for the MTD uclass? Others would be NAND and CFI. From what I can tell MTD has the same operations as SPI flash (erase, read, write) and adds a lot more.
Or is SPI flash really a separate uclass from MTD, with SPI flash being at a higher level?
cmd_sf
MTD
spi-nor or spi-flash
"spi-nor to spi drivers" and spi-nor controller driver
thanks!
Jagan | openedev. _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Regards, Simon

Hi Simon,
On 1 December 2015 at 04:47, Simon Glass sjg@chromium.org wrote:
Hi Jagan,
On 27 November 2015 at 02:21, Jagan Teki jteki@openedev.com wrote:
Hi Bin,
On 27 November 2015 at 07:55, Bin Meng bmeng.cn@gmail.com wrote:
Hi Jagan,
On Fri, Nov 27, 2015 at 2:54 AM, Jagan Teki jteki@openedev.com wrote:
Hi Simon,
Some how I'm unclear about your comments in previous series probably I my misunderstanding or something. let me explain about my plan on spi-nor development.
The entire spi-flash code is generic for all means there is no separate code for any platform or device. So I call it as spi-flash core. spi-flash core having functionaries like read_jedec, flash read/write/erase all these were calling from cmd_sf using dm and non-dm version, here I'm replacing this MTD since it is core interface it doesn't handle any specific device or uclass and mtd operations are being used directly without any dm except the probe.
So spi-flash shouldn't need dm and the respective probe sf_probe will follow dm as it allocates spi_flash and by taking spi_slave{} setup spi-uclass. spi-flash operation are common and there is no different ops for different drivers or devices or something and mtd_ops are manged directly from cmd_sf like nand and spi-nor in Linux.
And once core sits stable spi-flash will implemented as spi-nor core and the bellowed drivers becomes spi-nor drivers like spi-nor to spi driver interface and spi-nor controller drivers these are dm-driven it's having dm ops similar to spi-flash ops and spi-flash no where required.
My understanding is that when we introduce a new driver feature, it should target driver model by default. This is to encourage boards to take advantage of driver model, and all these *new* features. This is what Simon asked for. As Simon mentioned, probably we should make the SPI flash DM conversion complete now instead of adding any new feature on top of it.
I'm not introduced any new driver feature here, instead I re-used the existing mtd core features and functionalities.
The current code looks as below:
sf_probe.c:
- having both non-dm and dm spi-flash and calls to
- spi_flash_probe_slave for spi_flash detection and setting up hooks
(spi_flash ops)
sf_ops.c:
- having all spi_flash ops definitions.
These are the changes I did a) Moved spi_flash probing like definition of spi_flash_probe_slave from sf_probe.c to sf_ops.c so sf_ops.c having all core spi-flash code like flash detection, setting up hooks (spi_flash ops) and spi_flash ops definitions. b) from above point a) sf_probe.c having both dm and non-dm interface with a common call to sf_ops.c for spi-flash core functionalities using spi_flash_scan. c) Replaced existing spi_flash_mtd_register (sf_mtd.c) registration with generic mtd core using add_mtd_device in sf_probe.c for both dm and non-dm interfaces. d) In sf_ops.c Updated all mtd_info structure filling and replaced spi_flash ops hooks with mtd_info hooks - where dm_spi_flash_ops got dropped. e) Called mtd core operations from spi_flash.h like mtd_erase|write|read instead of direct calls to sf_ops.c with spi_flash operation as they are not needed, so mtd core calls will in turn call mtd hooks on spi-flash like nand, cfi and spi-nor in Linux.
The code after these changes:
sf_probe.c:
- having both non-dm and dm spi-flash and calls to
- spi_flash_scan for spi-flash core functionalities and register with core mtd.
sf_ops.c:
- core spi-flash operations => spi_flash detection + setting up hooks
(mtd ops) + having all mtd_info ops definitions.
I couldn't understand what's wrong with this approach, because I have not added any new feature instead I reused it existing MTD core. I agree that the dm_spi_flash_ops are removed as mtd_info ops are used instead and sf_probe.c is still with dm.
Please let me know your inputs.
Conceptually this seems problematic.
SPI flash is a uclass and supports driver model. It has operations, etc. Your patches remove the operations in favour of calling MTD. But MTD does not support driver model. This is getting really messy.
Before going any further we need to at least figure out the end goal.
To repeat my question from the previous email:
Please continue your comments on separate on this thread "[U-Boot] dm: Introduce SPI-NOR framework"
Is it intended that SPI flash should be a driver for the MTD uclass? Others would be NAND and CFI. From what I can tell MTD has the same operations as SPI flash (erase, read, write) and adds a lot more.
Or is SPI flash really a separate uclass from MTD, with SPI flash being at a higher level?
cmd_sf
MTD
spi-nor or spi-flash
"spi-nor to spi drivers" and spi-nor controller driver
thanks!

Hi Jagan,
On 26 November 2015 at 10:54, Jagan Teki jteki@openedev.com wrote:
Hi Simon,
Some how I'm unclear about your comments in previous series probably I my misunderstanding or something. let me explain about my plan on spi-nor development.
The entire spi-flash code is generic for all means there is no separate code for any platform or device. So I call it as spi-flash core. spi-flash core having functionaries like read_jedec, flash read/write/erase all these were calling from cmd_sf using dm and non-dm version, here I'm replacing this MTD since it is core interface it doesn't handle any specific device or uclass and mtd operations are being used directly without any dm except the probe.
So spi-flash shouldn't need dm and the respective probe sf_probe will follow dm as it allocates spi_flash and by taking spi_slave{} setup spi-uclass. spi-flash operation are common and there is no different ops for different drivers or devices or something and mtd_ops are manged directly from cmd_sf like nand and spi-nor in Linux.
And once core sits stable spi-flash will implemented as spi-nor core and the bellowed drivers becomes spi-nor drivers like spi-nor to spi driver interface and spi-nor controller drivers these are dm-driven it's having dm ops similar to spi-flash ops and spi-flash no where required.
cmd_sf
MTD
spi-nor or spi-flash
"spi-nor to spi drivers" and spi-nor controller driver
I think having read through the series and your emails I am starting to understand things.
But I'm still not quite there...
Is it intended that SPI flash should be a driver for the MTD uclass? Others would be NAND and CFI. From what I can tell MTD has the same operations as SPI flash (erase, read, write) and adds a lot more.
Or is SPI flash really a separate uclass from MTD, with SPI flash being at a higher level?
Your diagram above suggests that MTD calls into SPI NOR or SPI flash, but when I look at (for exampe) spi_flash_erase(), it is calling mtd_erase(), suggesting that it is above MTD in the software stack, the opposite of your diagram above.
On 26 November 2015 at 23:20, Simon Glass sjg@chromium.org wrote:
+Fabio
Hi Jagan,
On 26 November 2015 at 04:03, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
This seems to build on the patch which adds the flash locking stuff for non-DM SPI flash - commit c3c016cf. When I asked about this a week ago Tom mentioned that Fabio was going to fix this up so that it supports driver model.
As I tried to explain last time I reviewed this, the problem with this series is that it adds new functionality to non-DM code. In fact this series takes a backwards step, since it plumbs in DM SPI flash to non-DM SPI MTD, since the latter does not support driver model.
"adds new functionality to non-DM code." means code with #ifndef CONFIG_DM_SPI_FLASH sf_probe.c? ie because for mtd should available for non-dm drivers as well. Once all move to dm this will drop anyway.
The question in my mind is whether we are getting closer or further away from that day.
I am obviously failing to explain what I mean here - let me try again...
Function methods should be implemented as 'ops' structs in driver model and use the 'ops' member of the driver to provide the implementation. There should be no other function pointers or structs of function pointers.
Drivers should be declared as DM drivers, and devices should be created by driver model when it finds a definition in the device tree, or dynamically if needed for probing buses (e.g. PCI, USB, I2C in some cases). There should not be calls to 'register' and memory allocations. That is a sign that you are bypassing driver model for these things.
I do understand that the SPI flash DM conversion is incomplete - there are still many boards which have yet to be converted for SPI or SPI flash. Until that is done I think the efforts should be directed towards that goal, and things like SPI MTD should be introduced for DM only. At present it seems that we have created yet another migration task (SPI MTD) that would be better avoided.
I know you have sent detailed emails about the software layers, etc. I do understand that (or at least I think I do), but in the DM world, each layer should be a uclass with its own API and its own devices.
How can we move forward on this and get everything moved over to DM in short order?
So the above is the key question here. I'm still not clear on this, as above...
Jagan Teki (34): sf: spi_flash_validate_params => spi_flash_scan sf: Move spi_flash_scan code to sf_ops sf: Move read_id code to sf_ops sf: probe: Code cleanup sf: Use static for file-scope functions sf: Fix Makefile sf: Use simple name for register access functions sf: Use flash function pointers in dm_spi_flash_ops sf: Flash power up read-only based on idcode0 sf: Use static for file-scope functions sf: Remove unneeded header includes sf: probe: Use spi_flash_scan in dm-spi-flash sf: Re-factorize spi_flash_probe_tail code dm-sf: Re-factorize spi_flash_std_probe code zynq: Enable CONFIG_SPL_MTD_SUPPORT sf: Add MTD support to spi_flash sf: Use mtd_info ops instead of spi_flash ops cmd_sf: Use mtd->size instead of flash->size sf: Use mtd->erasesize instead of flash->erase_size dm-sf: use mtd_ops, drop dm_spi_flash_ops sf: Use MTD lock operations sf: Add MTD support for non-dm spi_flash interface sf: probe: Minor cleanup sf: Drop SNOR_F_SST_WR flash->flags sf: Remove unneeded SST_BP and SST_WP sf: ops: Fix missing break on spansion read_bar sf: Drop SPI_FLASH_MTD driver configs: Remove CONFIG_SPI_FLASH_MTD sf: dataflash: Remove unneeded spi data sf: dataflash: Move flash id detection into jedec_probe sf: dataflash: Fix add_dataflash return logic sf: dataflash: Add MTD core support sf: dataflash: Rename sf_dataflash.c to mtd_dataflash.c mtd: dataflash: Minor cleanups
common/cmd_sf.c | 16 +- drivers/mtd/spi/Kconfig | 14 +- drivers/mtd/spi/Makefile | 9 +- .../mtd/spi/{sf_dataflash.c => mtd_dataflash.c} | 402 ++++++----- drivers/mtd/spi/sf-uclass.c | 39 -- drivers/mtd/spi/sf_internal.h | 74 +- drivers/mtd/spi/sf_mtd.c | 104 --- drivers/mtd/spi/sf_ops.c | 769 ++++++++++++++++----- drivers/mtd/spi/sf_probe.c | 508 ++------------ include/configs/aristainetos-common.h | 1 - include/configs/gw_ventana.h | 1 - include/configs/ls1021aqds.h | 2 +- include/configs/socfpga_common.h | 1 - include/configs/zynq-common.h | 1 + include/spi_flash.h | 163 ++--- 15 files changed, 926 insertions(+), 1178 deletions(-) rename drivers/mtd/spi/{sf_dataflash.c => mtd_dataflash.c} (64%) delete mode 100644 drivers/mtd/spi/sf_mtd.c
thanks!
Jagan | openedev.
Regards, Simon

Hi Jagan,
On Thu, Nov 26, 2015 at 8:03 PM, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
There is no next-spi-nor-mtd branch in the spi git repo. What is the correct branch for testing this series?
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks! Jagan.
Regards, Bin

Hi Bin,
On 27 November 2015 at 07:24, Bin Meng bmeng.cn@gmail.com wrote:
Hi Jagan,
On Thu, Nov 26, 2015 at 8:03 PM, Jagan Teki jteki@openedev.com wrote:
This series is combination of mtd and sf tunning stuff in previous version patches.[1][2]
This is whole patch series for add mtd support to spi-flash framework and related stuff.
The idea is to introduce the spi-nor flash framework which similar to Linux with driver-model support.
Detail changes:
- drivers/mtd/spi/sf_probe.c: spi-flash to spi drivers interface(dm and non-dm)
- drivers/mtd/spi/sf_ops.c: Core spi-flash functionalities.
- spi_flash ops and dm_spi_ops are not needed as flash opertaion are common for dm and non-dm via MTD
Changes in v7:
- Rebase to master
- Added MTD core support to dataflash
- Few patch bisectable separations
Changes in v6, v5, v4, v3, v2:
- One patch bisectable separation
- Rebase to master
- added newly mtd stuff patches.
Testing: $ git clone git://git.denx.de/u-boot-spi.git $ cd u-boot-spi $ git checkout -b spi-nor-mtd origin/next-spi-nor-mtd
There is no next-spi-nor-mtd branch in the spi git repo. What is the correct branch for testing this series?
Sorry, spi-nor-mtd is the correct branch.
[1] http://u-boot.10912.n7.nabble.com/PATCH-v6-00-23-sf-MTD-support-td233769.htm... [2] http://lists.denx.de/pipermail/u-boot/2015-October/229857.html
thanks!
participants (4)
-
Bin Meng
-
Jagan Teki
-
Simon Glass
-
Stefan Roese