From: Takahiro Kuwano <takahiro.kuw...@infineon.com> Our SFDP parsing is everything we need to support all basic operations of a flash device. If the flash isn't found in our in-kernel flash database, gracefully fall back to a driver described solely by its SFDP tables.
This patch ports the commit in Linux: 773bbe104497 ("mtd: spi-nor: add generic flash driver") A new flag named SPI_NOR_PARSE_SFDP is defined to perform SFDP parse for the spi-nor-generic. And spi_nor_read_id() is moved to later part than SFDP functions. Signed-off-by: Takahiro Kuwano <takahiro.kuw...@infineon.com> --- drivers/mtd/spi/sf_internal.h | 1 + drivers/mtd/spi/spi-nor-core.c | 95 ++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 57608750c9..f7b0cea983 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -68,6 +68,7 @@ struct flash_info { #define SPI_NOR_HAS_SST26LOCK BIT(14) /* Flash supports lock/unlock via BPR */ #define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ #define SPI_NOR_OCTAL_DTR_READ BIT(16) /* Flash supports Octal DTR Read */ +#define SPI_NOR_PARSE_SFDP BIT(17) /* Parse SFDP tables */ }; extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index feafc48a49..c1186271a4 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -1509,31 +1509,6 @@ static int stm_is_unlocked(struct spi_nor *nor, loff_t ofs, uint64_t len) #endif /* CONFIG_SPI_FLASH_STMICRO */ #endif -static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) -{ - int tmp; - u8 id[SPI_NOR_MAX_ID_LEN]; - const struct flash_info *info; - - tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); - if (tmp < 0) { - dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); - return ERR_PTR(tmp); - } - - info = spi_nor_ids; - for (; info->name; info++) { - if (info->id_len) { - if (!memcmp(info->id, id, info->id_len)) - return info; - } - } - - dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", - id[0], id[1], id[2]); - return ERR_PTR(-ENODEV); -} - static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { @@ -2154,6 +2129,17 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, } #if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) + +static const struct flash_info spi_nor_generic_flash = { + .name = "spi-nor-generic", + /* + * JESD216 rev A doesn't specify the page size, therefore we need a + * sane default. + */ + .page_size = 256, + .flags = SPI_NOR_PARSE_SFDP, +}; + /* * Serial Flash Discoverable Parameters (SFDP) parsing. */ @@ -2724,6 +2710,32 @@ out: return ret; } +/** + * spi_nor_check_sfdp_signature() - check for a valid SFDP signature + * @nor: pointer to a 'struct spi_nor' + * + * Used to detect if the flash supports the RDSFDP command as well as the + * presence of a valid SFDP table. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_check_sfdp_signature(struct spi_nor *nor) +{ + u32 signature; + int err; + + /* Get the SFDP header. */ + err = spi_nor_read_sfdp(nor, 0, sizeof(signature), &signature); + if (err < 0) + return err; + + /* Check the SFDP signature. */ + if (le32_to_cpu(signature) != SFDP_SIGNATURE) + return -EINVAL; + + return 0; +} + /** * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' @@ -3014,7 +3026,7 @@ static int spi_nor_init_params(struct spi_nor *nor, nor->addr_width = 0; nor->mtd.erasesize = 0; if (info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | - SPI_NOR_OCTAL_DTR_READ)) { + SPI_NOR_OCTAL_DTR_READ | SPI_NOR_PARSE_SFDP)) { struct spi_nor_flash_parameter sfdp_params; memcpy(&sfdp_params, params, sizeof(sfdp_params)); @@ -4170,6 +4182,37 @@ void spi_nor_set_fixups(struct spi_nor *nor) #endif /* SPI_FLASH_MACRONIX */ } +static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) +{ + int tmp; + u8 id[SPI_NOR_MAX_ID_LEN]; + const struct flash_info *info; + + tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + if (tmp < 0) { + dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); + return ERR_PTR(tmp); + } + + info = spi_nor_ids; + for (; info->name; info++) { + if (info->id_len) { + if (!memcmp(info->id, id, info->id_len)) + return info; + } + } + +#if CONFIG_IS_ENABLED(SPI_FLASH_SFDP_SUPPORT) + /* Fallback to a generic flash described only by its SFDP data. */ + if (!spi_nor_check_sfdp_signature(nor)) + return &spi_nor_generic_flash; +#endif + + dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); +} + int spi_nor_scan(struct spi_nor *nor) { struct spi_nor_flash_parameter params; -- 2.34.1