From: Takahiro Kuwano <[email protected]> Port spi_nor_manufacturer struct from Linux but ommit 'name' as we don't print manufacturer name in u-boot, and add 'set_fixups' function pointer to assign chip specific fixups in manufacturer drivers.Since the u-boot has size constraint, we should keep having chip-specific fixups in struct spi_nor instead of flash_info. The 'fixups' and 'set_fixups' are excluded for tiny.
The manufacturers array and match_id helper are placed in spi-nor-ids.c as those need to be referred from both core and tiny. Signed-off-by: Takahiro Kuwano <[email protected]> --- drivers/mtd/spi/sf_internal.h | 18 ++++++++++++++++++ drivers/mtd/spi/sfdp.c | 9 +++++++++ drivers/mtd/spi/spi-nor-core.c | 13 +++++++++++++ drivers/mtd/spi/spi-nor-ids.c | 21 +++++++++++++++++++++ drivers/mtd/spi/spi-nor-tiny.c | 4 ++++ include/linux/mtd/spi-nor.h | 2 ++ 6 files changed, 67 insertions(+) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 576617beb70..3b6b51cb11c 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -97,6 +97,22 @@ struct flash_info { #define SPI_NOR_OCTAL_DTR_READ BIT(17) /* Flash supports Octal DTR Read */ }; +/** + * struct spi_nor_manufacturer - SPI NOR manufacturer object + * @parts: array of parts supported by this manufacturer + * @nparts: number of entries in the parts array + * @fixups: hooks called at various points in time during spi_nor_scan() + * @set_fixups: called to assign chip-specific fixups + */ +struct spi_nor_manufacturer { + const struct flash_info *parts; + unsigned int nparts; +#if !CONFIG_IS_ENABLED(SPI_FLASH_TINY) + const struct spi_nor_fixups *fixups; + void (*set_fixups)(struct spi_nor *nor); +#endif +}; + extern const struct flash_info spi_nor_ids[]; #define JEDEC_MFR(info) ((info)->id[0]) @@ -143,4 +159,6 @@ int macronix_quad_enable(struct spi_nor *nor); int spi_nor_hwcaps_read2cmd(u32 hwcaps); int spansion_no_read_cr_quad_enable(struct spi_nor *nor); +const struct flash_info *spi_nor_match_id(struct spi_nor *nor, const u8 *id); + #endif /* _SF_INTERNAL_H_ */ diff --git a/drivers/mtd/spi/sfdp.c b/drivers/mtd/spi/sfdp.c index fd545796d50..db9dda12e27 100644 --- a/drivers/mtd/spi/sfdp.c +++ b/drivers/mtd/spi/sfdp.c @@ -219,6 +219,15 @@ spi_nor_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_bfpt *bfpt, struct spi_nor_flash_parameter *params) { + int ret; + + if (nor->manufacturer->fixups && nor->manufacturer->fixups->post_bfpt) { + ret = nor->manufacturer->fixups->post_bfpt(nor, bfpt_header, + bfpt, params); + if (ret) + return ret; + } + if (nor->fixups && nor->fixups->post_bfpt) return nor->fixups->post_bfpt(nor, bfpt_header, bfpt, params); diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index b99a1a45d8f..697e443bf5a 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -1405,6 +1405,10 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) return ERR_PTR(tmp); } + info = spi_nor_match_id(nor, id); + if (info) + return info; + info = spi_nor_ids; for (; info->name; info++) { if (info->id_len) { @@ -2190,6 +2194,9 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, static void spi_nor_post_sfdp_fixups(struct spi_nor *nor, struct spi_nor_flash_parameter *params) { + if (nor->manufacturer->fixups && nor->manufacturer->fixups->post_sfdp) + nor->manufacturer->fixups->post_sfdp(nor, params); + if (nor->fixups && nor->fixups->post_sfdp) nor->fixups->post_sfdp(nor, params); } @@ -2197,6 +2204,9 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor, static void spi_nor_late_init_fixups(struct spi_nor *nor, struct spi_nor_flash_parameter *params) { + if (nor->manufacturer->fixups && nor->manufacturer->fixups->late_init) + nor->manufacturer->fixups->late_init(nor, params); + if (nor->fixups && nor->fixups->late_init) nor->fixups->late_init(nor, params); } @@ -3640,6 +3650,9 @@ int spi_nor_remove(struct spi_nor *nor) void spi_nor_set_fixups(struct spi_nor *nor) { + if (nor->manufacturer->set_fixups) + nor->manufacturer->set_fixups(nor); + #ifdef CONFIG_SPI_FLASH_SPANSION if (JEDEC_MFR(nor->info) == SNOR_MFR_CYPRESS) { switch (nor->info->id[1]) { diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index c0fa98424aa..45e9b866795 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -723,3 +723,24 @@ const struct flash_info spi_nor_ids[] = { #endif { }, }; + +static const struct spi_nor_manufacturer *manufacturers[] = { +}; + +const struct flash_info *spi_nor_match_id(struct spi_nor *nor, const u8 *id) +{ + const struct flash_info *part; + unsigned int i, j; + + for (i = 0; i < ARRAY_SIZE(manufacturers); i++) { + for (j = 0; j < manufacturers[i]->nparts; j++) { + part = &manufacturers[i]->parts[j]; + if (!memcmp(part->id, id, part->id_len)) { + nor->manufacturer = manufacturers[i]; + return part; + } + } + } + + return NULL; +} diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c index cf00473ee83..c7824285191 100644 --- a/drivers/mtd/spi/spi-nor-tiny.c +++ b/drivers/mtd/spi/spi-nor-tiny.c @@ -383,6 +383,10 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) return ERR_PTR(tmp); } + info = spi_nor_match_id(nor, id); + if (info) + return info; + info = spi_nor_ids; for (; info->sector_size != 0; info++) { if (info->id_len) { diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 4eef4ab0488..08567a80472 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -508,6 +508,7 @@ struct spi_flash { * @lock: the lock for the read/write/erase/lock/unlock operations * @dev: point to a spi device, or a spi nor controller device. * @info: spi-nor part JDEC MFR id and other info + * @manufacturer: SPI NOR manufacturer * @manufacturer_sfdp: manufacturer specific SFDP table * @page_size: the page size of the SPI NOR * @addr_width: number of address bytes @@ -559,6 +560,7 @@ struct spi_nor { struct udevice *dev; struct spi_slave *spi; const struct flash_info *info; + const struct spi_nor_manufacturer *manufacturer; u8 *manufacturer_sfdp; u32 page_size; u8 addr_width; -- 2.43.0

