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


Reply via email to