@@ -194,47 +194,40 @@ static const struct flash_info atmel_nor_parts[] = {
.size = SZ_512K,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
.no_sfdp_flags = SECT_4K,
- .fixups = &atmel_nor_global_protection_fixups,
}, {
.id = SNOR_ID(0x1f, 0x45, 0x01),
.name = "at26df081a",
.size = SZ_1M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
.no_sfdp_flags = SECT_4K,
- .fixups = &atmel_nor_global_protection_fixups
}, {
.id = SNOR_ID(0x1f, 0x46, 0x01),
.name = "at26df161a",
.size = SZ_2M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
.no_sfdp_flags = SECT_4K,
- .fixups = &atmel_nor_global_protection_fixups
}, {
.id = SNOR_ID(0x1f, 0x47, 0x00),
.name = "at25df321",
.size = SZ_4M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
.no_sfdp_flags = SECT_4K,
- .fixups = &atmel_nor_global_protection_fixups
}, {
.id = SNOR_ID(0x1f, 0x47, 0x01),
.name = "at25df321a",
.size = SZ_4M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
.no_sfdp_flags = SECT_4K,
- .fixups = &atmel_nor_global_protection_fixups
}, {
.id = SNOR_ID(0x1f, 0x47, 0x08),
.name = "at25ff321a",
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
- .fixups = &atmel_nor_global_protection_fixups
}, {
.id = SNOR_ID(0x1f, 0x48, 0x00),
.name = "at25df641",
.size = SZ_8M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
.no_sfdp_flags = SECT_4K,
- .fixups = &atmel_nor_global_protection_fixups
}, {
.id = SNOR_ID(0x1f, 0x66, 0x01),
.name = "at25fs010",
@@ -242,14 +235,12 @@ static const struct flash_info atmel_nor_parts[] = {
.size = SZ_128K,
.flags = SPI_NOR_HAS_LOCK,
.no_sfdp_flags = SECT_4K,
- .fixups = &at25fs_nor_fixups
}, {
.id = SNOR_ID(0x1f, 0x66, 0x04),
.name = "at25fs040",
.size = SZ_512K,
.flags = SPI_NOR_HAS_LOCK,
.no_sfdp_flags = SECT_4K,
- .fixups = &at25fs_nor_fixups
}, {
.id = SNOR_ID(0x1f, 0x87, 0x01),
.size = SZ_4M,
@@ -257,8 +248,22 @@ static const struct flash_info atmel_nor_parts[] = {
},
};
+static const struct spi_nor_fixup atmel_fixups[] = {
+ { .id = SNOR_ID(0x1f, 0x44, 0x01), .fixups = &atmel_nor_global_protection_fixups },
+ { .id = SNOR_ID(0x1f, 0x45, 0x01), .fixups = &atmel_nor_global_protection_fixups },
+ { .id = SNOR_ID(0x1f, 0x46, 0x01), .fixups = &atmel_nor_global_protection_fixups },
+ { .id = SNOR_ID(0x1f, 0x47, 0x00), .fixups = &atmel_nor_global_protection_fixups },
+ { .id = SNOR_ID(0x1f, 0x47, 0x01), .fixups = &atmel_nor_global_protection_fixups },
+ { .id = SNOR_ID(0x1f, 0x47, 0x08), .fixups = &atmel_nor_global_protection_fixups },
+ { .id = SNOR_ID(0x1f, 0x48, 0x00), .fixups = &atmel_nor_global_protection_fixups },
+ { .id = SNOR_ID(0x1f, 0x66, 0x01), .fixups = &at25fs_nor_fixups },
+ { .id = SNOR_ID(0x1f, 0x66, 0x04), .fixups = &at25fs_nor_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_atmel = {
.name = "atmel",
.parts = atmel_nor_parts,
.nparts = ARRAY_SIZE(atmel_nor_parts),
+ .fixups = atmel_fixups,
+ .nfixups = ARRAY_SIZE(atmel_fixups),
};
@@ -2357,19 +2357,24 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt)
{
+ const struct spi_nor_fixup *fixups;
int ret;
+ unsigned int i;
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->post_bfpt) {
- ret = nor->manufacturer->fixups->post_bfpt(nor, bfpt_header,
- bfpt);
- if (ret)
- return ret;
+ if (!nor->manufacturer || !nor->manufacturer->fixups)
+ return 0;
+
+ fixups = nor->manufacturer->fixups;
+
+ for (i = 0; i < nor->manufacturer->nfixups; i++) {
+ if (fixups[i].fixups->post_bfpt &&
+ spi_nor_fixup_match(nor, &fixups[i])) {
+ ret = fixups[i].fixups->post_bfpt(nor, bfpt_header, bfpt);
+ if (ret)
+ return ret;
+ }
}
- if (nor->info->fixups && nor->info->fixups->post_bfpt)
- return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt);
-
return 0;
}
@@ -2626,6 +2631,26 @@ static int spi_nor_setup(struct spi_nor *nor,
return spi_nor_set_addr_nbytes(nor);
}
+bool spi_nor_fixup_match(const struct spi_nor *nor,
+ const struct spi_nor_fixup *fixup)
+{
+ const struct spi_nor_id *id = nor->info ? nor->info->id : NULL;
+
+ /* Filter by ID first, if available */
+ if (fixup->id) {
+ if (!id || fixup->id->len > id->len ||
+ memcmp(id->bytes, fixup->id->bytes, fixup->id->len))
+ return false;
+ }
+
+ /* Further filter with the match callback, if provided */
+ if (fixup->match)
+ return fixup->match(nor);
+
+ /* Either there was an ID and it matched, or it is a catch-all entry */
+ return true;
+}
+
/**
* spi_nor_manufacturer_init_params() - Initialize the flash's parameters and
* settings based on MFR register and ->default_init() hook.
@@ -2633,12 +2658,19 @@ static int spi_nor_setup(struct spi_nor *nor,
*/
static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->default_init)
- nor->manufacturer->fixups->default_init(nor);
+ const struct spi_nor_fixup *fixups;
+ unsigned int i;
- if (nor->info->fixups && nor->info->fixups->default_init)
- nor->info->fixups->default_init(nor);
+ if (!nor->manufacturer || !nor->manufacturer->fixups)
+ return;
+
+ fixups = nor->manufacturer->fixups;
+
+ for (i = 0; i < nor->manufacturer->nfixups; i++) {
+ if (fixups[i].fixups->default_init &&
+ spi_nor_fixup_match(nor, &fixups[i]))
+ fixups[i].fixups->default_init(nor);
+ }
}
/**
@@ -2787,22 +2819,24 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor)
static int spi_nor_late_init_params(struct spi_nor *nor)
{
struct spi_nor_flash_parameter *params = nor->params;
+ const struct spi_nor_fixup *fixups;
+ unsigned int i;
int ret;
/* Needed by some late_init hooks */
spi_nor_init_flags(nor);
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->late_init) {
- ret = nor->manufacturer->fixups->late_init(nor);
- if (ret)
- return ret;
- }
+ if (nor->manufacturer && nor->manufacturer->fixups) {
+ fixups = nor->manufacturer->fixups;
- if (nor->info->fixups && nor->info->fixups->late_init) {
- ret = nor->info->fixups->late_init(nor);
- if (ret)
- return ret;
+ for (i = 0; i < nor->manufacturer->nfixups; i++) {
+ if (fixups[i].fixups->late_init &&
+ spi_nor_fixup_match(nor, &fixups[i])) {
+ ret = fixups[i].fixups->late_init(nor);
+ if (ret)
+ return ret;
+ }
+ }
}
if (!nor->params->opcodes.die_erase)
@@ -445,6 +445,19 @@ struct spi_nor_fixups {
int (*late_init)(struct spi_nor *nor);
};
+/**
+ * struct spi_nor_fixup - SPI NOR fixup registration.
+ * @id: (optional) flash ID this fixup applies to, may only match the
+ * ID prefix, eg. just the first few bytes to match a whole family
+ * @match: (optional) custom match function (can be used together with @id)
+ * @fixups: the fixup hooks to apply when this entry matches
+ */
+struct spi_nor_fixup {
+ const struct spi_nor_id *id;
+ bool (*match)(const struct spi_nor *nor);
+ const struct spi_nor_fixups *fixups;
+};
+
/**
* struct spi_nor_id - SPI NOR flash ID.
*
@@ -560,7 +573,6 @@ struct flash_info {
u8 mfr_flags;
const struct spi_nor_otp_organization *otp;
- const struct spi_nor_fixups *fixups;
};
#define SNOR_ID(...) \
@@ -582,13 +594,16 @@ struct flash_info {
* @name: manufacturer name
* @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()
+ * @fixups: list of fixups, each matched by ID (or a custom match function),
+ * applied to any part of this manufacturer.
+ * @nfixups: number of entries in the fixups array
*/
struct spi_nor_manufacturer {
const char *name;
const struct flash_info *parts;
unsigned int nparts;
- const struct spi_nor_fixups *fixups;
+ const struct spi_nor_fixup *fixups;
+ unsigned int nfixups;
};
/**
@@ -619,6 +634,8 @@ extern const struct spi_nor_manufacturer spi_nor_xmc;
extern const struct attribute_group *spi_nor_sysfs_groups[];
+bool spi_nor_fixup_match(const struct spi_nor *nor,
+ const struct spi_nor_fixup *fixup);
void spi_nor_spimem_setup_op(const struct spi_nor *nor,
struct spi_mem_op *op,
const enum spi_nor_protocol proto);
@@ -44,9 +44,14 @@ static const struct spi_nor_fixups everspin_nor_fixups = {
.default_init = everspin_nor_default_init,
};
+static const struct spi_nor_fixup everspin_fixups[] = {
+ { .fixups = &everspin_nor_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_everspin = {
.name = "everspin",
.parts = everspin_nor_parts,
.nparts = ARRAY_SIZE(everspin_nor_parts),
- .fixups = &everspin_nor_fixups,
+ .fixups = everspin_fixups,
+ .nfixups = ARRAY_SIZE(everspin_fixups),
};
@@ -64,7 +64,6 @@ static const struct flash_info gigadevice_nor_parts[] = {
.id = SNOR_ID(0xc8, 0x40, 0x19),
.name = "gd25q256",
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6,
- .fixups = &gd25q256_fixups,
.fixup_flags = SPI_NOR_4B_OPCODES,
}, {
.id = SNOR_ID(0xc8, 0x60, 0x16),
@@ -87,8 +86,14 @@ static const struct flash_info gigadevice_nor_parts[] = {
},
};
+static const struct spi_nor_fixup gigadevice_fixups[] = {
+ { .id = SNOR_ID(0xc8, 0x40, 0x19), .fixups = &gd25q256_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_gigadevice = {
.name = "gigadevice",
.parts = gigadevice_nor_parts,
.nparts = ARRAY_SIZE(gigadevice_nor_parts),
+ .fixups = gigadevice_fixups,
+ .nfixups = ARRAY_SIZE(gigadevice_fixups),
};
@@ -52,13 +52,11 @@ static const struct flash_info issi_nor_parts[] = {
.sector_size = SZ_32K,
.size = SZ_64K,
.no_sfdp_flags = SECT_4K,
- .fixups = &pm25lv_nor_fixups
}, {
.name = "pm25lv010",
.sector_size = SZ_32K,
.size = SZ_128K,
.no_sfdp_flags = SECT_4K,
- .fixups = &pm25lv_nor_fixups
}, {
.id = SNOR_ID(0x7f, 0x9d, 0x20),
.name = "is25cd512",
@@ -103,7 +101,6 @@ static const struct flash_info issi_nor_parts[] = {
}, {
.id = SNOR_ID(0x9d, 0x60, 0x19),
.name = "is25lp256",
- .fixups = &is25lp256_fixups,
.fixup_flags = SPI_NOR_4B_OPCODES,
}, {
.id = SNOR_ID(0x9d, 0x70, 0x16),
@@ -124,7 +121,6 @@ static const struct flash_info issi_nor_parts[] = {
.id = SNOR_ID(0x9d, 0x70, 0x19),
.name = "is25wp256",
.flags = SPI_NOR_QUAD_PP,
- .fixups = &is25lp256_fixups,
.fixup_flags = SPI_NOR_4B_OPCODES,
}
};
@@ -139,9 +135,25 @@ static const struct spi_nor_fixups issi_fixups = {
.default_init = issi_nor_default_init,
};
+/* PM25LV parts have no JEDEC ID and are likely matched by name */
+static bool issi_pm25lv_match(const struct spi_nor *nor)
+{
+ const char *name = nor->info ? nor->info->name : NULL;
+
+ return name && strstarts(name, "pm25lv");
+}
+
+static const struct spi_nor_fixup issi_fixup_list[] = {
+ { .fixups = &issi_fixups },
+ { .match = issi_pm25lv_match, .fixups = &pm25lv_nor_fixups },
+ { .id = SNOR_ID(0x9d, 0x60, 0x19), .fixups = &is25lp256_fixups },
+ { .id = SNOR_ID(0x9d, 0x70, 0x19), .fixups = &is25lp256_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_issi = {
.name = "issi",
.parts = issi_nor_parts,
.nparts = ARRAY_SIZE(issi_nor_parts),
- .fixups = &issi_fixups,
+ .fixups = issi_fixup_list,
+ .nfixups = ARRAY_SIZE(issi_fixup_list),
};
@@ -137,20 +137,16 @@ static const struct flash_info macronix_nor_parts[] = {
}, {
/* MX25L25635E, MX25L25645G */
.id = SNOR_ID(0xc2, 0x20, 0x19),
- .fixups = &mx25l25635_fixups
}, {
/* MX66L51235F */
.id = SNOR_ID(0xc2, 0x20, 0x1a),
.fixup_flags = SPI_NOR_4B_OPCODES,
- .fixups = ¯onix_qpp4b_fixups,
}, {
/* MX66L1G45G */
.id = SNOR_ID(0xc2, 0x20, 0x1b),
- .fixups = ¯onix_qpp4b_fixups,
}, {
/* MX66L2G45G */
.id = SNOR_ID(0xc2, 0x20, 0x1c),
- .fixups = ¯onix_qpp4b_fixups,
}, {
.id = SNOR_ID(0xc2, 0x23, 0x14),
.name = "mx25v8035f",
@@ -189,15 +185,12 @@ static const struct flash_info macronix_nor_parts[] = {
}, {
/* MX25U51245G */
.id = SNOR_ID(0xc2, 0x25, 0x3a),
- .fixups = ¯onix_qpp4b_fixups,
}, {
/* MX66U1G45G */
.id = SNOR_ID(0xc2, 0x25, 0x3b),
- .fixups = ¯onix_qpp4b_fixups,
}, {
/* MX66U2G45G */
.id = SNOR_ID(0xc2, 0x25, 0x3c),
- .fixups = ¯onix_qpp4b_fixups,
}, {
.id = SNOR_ID(0xc2, 0x26, 0x18),
.name = "mx25l12855e",
@@ -229,7 +222,6 @@ static const struct flash_info macronix_nor_parts[] = {
}, {
/* MX25L3255E */
.id = SNOR_ID(0xc2, 0x9e, 0x16),
- .fixups = &mx25l3255e_fixups,
},
/*
* This spares us of adding new flash entries for flashes that can be
@@ -333,9 +325,22 @@ static const struct spi_nor_fixups macronix_nor_fixups = {
.late_init = macronix_nor_late_init,
};
+static const struct spi_nor_fixup macronix_fixups[] = {
+ { .fixups = ¯onix_nor_fixups },
+ { .id = SNOR_ID(0xc2, 0x20, 0x19), .fixups = &mx25l25635_fixups },
+ { .id = SNOR_ID(0xc2, 0x20, 0x1a), .fixups = ¯onix_qpp4b_fixups },
+ { .id = SNOR_ID(0xc2, 0x20, 0x1b), .fixups = ¯onix_qpp4b_fixups },
+ { .id = SNOR_ID(0xc2, 0x20, 0x1c), .fixups = ¯onix_qpp4b_fixups },
+ { .id = SNOR_ID(0xc2, 0x25, 0x3a), .fixups = ¯onix_qpp4b_fixups },
+ { .id = SNOR_ID(0xc2, 0x25, 0x3b), .fixups = ¯onix_qpp4b_fixups },
+ { .id = SNOR_ID(0xc2, 0x25, 0x3c), .fixups = ¯onix_qpp4b_fixups },
+ { .id = SNOR_ID(0xc2, 0x9e, 0x16), .fixups = &mx25l3255e_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_macronix = {
.name = "macronix",
.parts = macronix_nor_parts,
.nparts = ARRAY_SIZE(macronix_nor_parts),
- .fixups = ¯onix_nor_fixups,
+ .fixups = macronix_fixups,
+ .nfixups = ARRAY_SIZE(macronix_fixups),
};
@@ -206,13 +206,11 @@ static const struct flash_info micron_nor_parts[] = {
.id = SNOR_ID(0x2c, 0x5b, 0x1a),
.mfr_flags = USE_FSR,
.fixup_flags = SPI_NOR_IO_MODE_EN_VOLATILE,
- .fixups = &mt35xu512aba_fixups,
}, {
/* MT35XU01GBBA */
.id = SNOR_ID(0x2c, 0x5b, 0x1b),
.mfr_flags = USE_FSR,
.fixup_flags = SPI_NOR_IO_MODE_EN_VOLATILE,
- .fixups = &mt35_two_die_fixups,
}, {
.id = SNOR_ID(0x2c, 0x5b, 0x1c),
.name = "mt35xu02g",
@@ -221,7 +219,6 @@ static const struct flash_info micron_nor_parts[] = {
.no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ,
.mfr_flags = USE_FSR,
.fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
- .fixups = &mt35_two_die_fixups,
},
};
@@ -233,6 +230,17 @@ static int mt25qu512a_post_bfpt_fixup(struct spi_nor *nor,
return 0;
}
+/*
+ * n25q00a parts share the first same 3 ID bytes with mt25qu01g.
+ * In order to not mix the fixups, further filter out using the part name.
+ */
+static bool n25q00a_match(const struct spi_nor *nor)
+{
+ const char *name = nor->info ? nor->info->name : NULL;
+
+ return name && !strncmp(name, "n25q00a", 7);
+}
+
static const struct spi_nor_fixups mt25qu512a_fixups = {
.post_bfpt = mt25qu512a_post_bfpt_fixup,
};
@@ -426,14 +434,12 @@ static const struct flash_info st_nor_parts[] = {
SPI_NOR_BP3_SR_BIT6,
.no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
.mfr_flags = USE_FSR,
- .fixups = &n25q00_fixups,
}, {
.id = SNOR_ID(0x20, 0xba, 0x22),
.name = "mt25ql02g",
.size = SZ_256M,
.no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
.mfr_flags = USE_FSR,
- .fixups = &mt25q02_fixups,
}, {
.id = SNOR_ID(0x20, 0xbb, 0x15),
.name = "n25q016a",
@@ -480,7 +486,6 @@ static const struct flash_info st_nor_parts[] = {
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
SPI_NOR_BP3_SR_BIT6,
.mfr_flags = USE_FSR,
- .fixups = &mt25qu512a_fixups,
}, {
.id = SNOR_ID(0x20, 0xbb, 0x20),
.name = "n25q512a",
@@ -493,21 +498,18 @@ static const struct flash_info st_nor_parts[] = {
.id = SNOR_ID(0x20, 0xbb, 0x21, 0x10, 0x44, 0x00),
.name = "mt25qu01g",
.mfr_flags = USE_FSR,
- .fixups = &mt25q01_fixups,
}, {
.id = SNOR_ID(0x20, 0xbb, 0x21),
.name = "n25q00a",
.size = SZ_128M,
.no_sfdp_flags = SECT_4K | SPI_NOR_QUAD_READ,
.mfr_flags = USE_FSR,
- .fixups = &n25q00_fixups,
}, {
.id = SNOR_ID(0x20, 0xbb, 0x22),
.name = "mt25qu02g",
.size = SZ_256M,
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
.mfr_flags = USE_FSR,
- .fixups = &mt25q02_fixups,
}
};
@@ -657,16 +659,35 @@ static const struct spi_nor_fixups micron_st_nor_fixups = {
.late_init = micron_st_nor_late_init,
};
+static const struct spi_nor_fixup micron_fixups[] = {
+ { .fixups = µn_st_nor_fixups },
+ { .id = SNOR_ID(0x2c, 0x5b, 0x1a), .fixups = &mt35xu512aba_fixups },
+ { .id = SNOR_ID(0x2c, 0x5b, 0x1b), .fixups = &mt35_two_die_fixups },
+ { .id = SNOR_ID(0x2c, 0x5b, 0x1c), .fixups = &mt35_two_die_fixups },
+};
+
+static const struct spi_nor_fixup st_fixups[] = {
+ { .fixups = µn_st_nor_fixups },
+ { .id = SNOR_ID(0x20, 0xba, 0x21), .fixups = &n25q00_fixups },
+ { .id = SNOR_ID(0x20, 0xba, 0x22), .fixups = &mt25q02_fixups },
+ { .id = SNOR_ID(0x20, 0xbb, 0x20, 0x10, 0x44, 0x00), .fixups = &mt25qu512a_fixups },
+ { .id = SNOR_ID(0x20, 0xbb, 0x21, 0x10, 0x44, 0x00), .fixups = &mt25q01_fixups },
+ { .id = SNOR_ID(0x20, 0xbb, 0x21), .match = n25q00a_match, .fixups = &n25q00_fixups },
+ { .id = SNOR_ID(0x20, 0xbb, 0x22), .fixups = &mt25q02_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_micron = {
.name = "micron",
.parts = micron_nor_parts,
.nparts = ARRAY_SIZE(micron_nor_parts),
- .fixups = µn_st_nor_fixups,
+ .fixups = micron_fixups,
+ .nfixups = ARRAY_SIZE(micron_fixups),
};
const struct spi_nor_manufacturer spi_nor_st = {
.name = "st",
.parts = st_nor_parts,
.nparts = ARRAY_SIZE(st_nor_parts),
- .fixups = µn_st_nor_fixups,
+ .fixups = st_fixups,
+ .nfixups = ARRAY_SIZE(st_fixups),
};
@@ -727,12 +727,19 @@ static u8 spi_nor_smpt_addr_nbytes(const struct spi_nor *nor, const u32 settings
static void spi_nor_smpt_read_dummy_fixups(const struct spi_nor *nor,
u8 *read_dummy)
{
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->smpt_read_dummy)
- nor->manufacturer->fixups->smpt_read_dummy(nor, read_dummy);
+ const struct spi_nor_fixup *fixups;
+ unsigned int i;
- if (nor->info->fixups && nor->info->fixups->smpt_read_dummy)
- nor->info->fixups->smpt_read_dummy(nor, read_dummy);
+ if (!nor->manufacturer || !nor->manufacturer->fixups)
+ return;
+
+ fixups = nor->manufacturer->fixups;
+
+ for (i = 0; i < nor->manufacturer->nfixups; i++) {
+ if (fixups[i].fixups->smpt_read_dummy &&
+ spi_nor_fixup_match(nor, &fixups[i]))
+ fixups[i].fixups->smpt_read_dummy(nor, read_dummy);
+ }
}
/**
@@ -757,12 +764,19 @@ static u8 spi_nor_smpt_read_dummy(const struct spi_nor *nor, const u32 settings)
static void spi_nor_smpt_map_id_fixups(const struct spi_nor *nor, u8 *map_id)
{
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->smpt_map_id)
- nor->manufacturer->fixups->smpt_map_id(nor, map_id);
+ const struct spi_nor_fixup *fixups;
+ unsigned int i;
- if (nor->info->fixups && nor->info->fixups->smpt_map_id)
- nor->info->fixups->smpt_map_id(nor, map_id);
+ if (!nor->manufacturer || !nor->manufacturer->fixups)
+ return;
+
+ fixups = nor->manufacturer->fixups;
+
+ for (i = 0; i < nor->manufacturer->nfixups; i++) {
+ if (fixups[i].fixups->smpt_map_id &&
+ spi_nor_fixup_match(nor, &fixups[i]))
+ fixups[i].fixups->smpt_map_id(nor, map_id);
+ }
}
/**
@@ -1406,17 +1420,23 @@ static int spi_nor_parse_sccr_mc(struct spi_nor *nor,
*/
static int spi_nor_post_sfdp_fixups(struct spi_nor *nor)
{
+ const struct spi_nor_fixup *fixups;
+ unsigned int i;
int ret;
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->post_sfdp) {
- ret = nor->manufacturer->fixups->post_sfdp(nor);
- if (ret)
- return ret;
- }
+ if (!nor->manufacturer || !nor->manufacturer->fixups)
+ return 0;
- if (nor->info->fixups && nor->info->fixups->post_sfdp)
- return nor->info->fixups->post_sfdp(nor);
+ fixups = nor->manufacturer->fixups;
+
+ for (i = 0; i < nor->manufacturer->nfixups; i++) {
+ if (fixups[i].fixups->post_sfdp &&
+ spi_nor_fixup_match(nor, &fixups[i])) {
+ ret = fixups[i].fixups->post_sfdp(nor);
+ if (ret)
+ return ret;
+ }
+ }
return 0;
}
@@ -905,7 +905,6 @@ static const struct flash_info spansion_nor_parts[] = {
.sector_size = SZ_256K,
.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
.mfr_flags = USE_CLSR,
- .fixups = &s25fs_s_nor_fixups,
}, {
.id = SNOR_ID(0x01, 0x20, 0x18, 0x03, 0x00),
.name = "s25sl12800",
@@ -941,7 +940,6 @@ static const struct flash_info spansion_nor_parts[] = {
.size = SZ_16M,
.no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
.mfr_flags = USE_CLSR,
- .fixups = &s25fs_s_nor_fixups,
}, {
.id = SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01),
.name = "s25fl129p1",
@@ -1001,76 +999,61 @@ static const struct flash_info spansion_nor_parts[] = {
.id = SNOR_ID(0x34, 0x2a, 0x1a, 0x0f, 0x03, 0x90),
.name = "s25hl512t",
.mfr_flags = USE_CLPEF,
- .fixups = &s25hx_t_fixups
}, {
.id = SNOR_ID(0x34, 0x2a, 0x1b, 0x0f, 0x03, 0x90),
.name = "s25hl01gt",
.mfr_flags = USE_CLPEF,
- .fixups = &s25hx_t_fixups
}, {
.id = SNOR_ID(0x34, 0x2a, 0x1c, 0x0f, 0x00, 0x90),
.name = "s25hl02gt",
.mfr_flags = USE_CLPEF,
- .fixups = &s25hx_t_fixups
}, {
.id = SNOR_ID(0x34, 0x2b, 0x19, 0x0f, 0x08, 0x90),
.name = "s25fs256t",
.mfr_flags = USE_CLPEF,
- .fixups = &s25fs256t_fixups
}, {
.id = SNOR_ID(0x34, 0x2b, 0x1a, 0x0f, 0x03, 0x90),
.name = "s25hs512t",
.mfr_flags = USE_CLPEF,
- .fixups = &s25hx_t_fixups
}, {
.id = SNOR_ID(0x34, 0x2b, 0x1b, 0x0f, 0x03, 0x90),
.name = "s25hs01gt",
.mfr_flags = USE_CLPEF,
- .fixups = &s25hx_t_fixups
}, {
.id = SNOR_ID(0x34, 0x2b, 0x1c, 0x0f, 0x00, 0x90),
.name = "s25hs02gt",
.mfr_flags = USE_CLPEF,
- .fixups = &s25hx_t_fixups
}, {
/* S28HL256T */
.id = SNOR_ID(0x34, 0x5a, 0x19),
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
.id = SNOR_ID(0x34, 0x5a, 0x1a),
.name = "s28hl512t",
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
.id = SNOR_ID(0x34, 0x5a, 0x1b),
.name = "s28hl01gt",
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
/* S28HL02GT */
.id = SNOR_ID(0x34, 0x5a, 0x1c),
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
.id = SNOR_ID(0x34, 0x5b, 0x19),
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
.id = SNOR_ID(0x34, 0x5b, 0x1a),
.name = "s28hs512t",
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
.id = SNOR_ID(0x34, 0x5b, 0x1b),
.name = "s28hs01gt",
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
.id = SNOR_ID(0x34, 0x5b, 0x1c),
.name = "s28hs02gt",
.mfr_flags = USE_CLPEF,
- .fixups = &s28hx_t_fixups,
}, {
.id = SNOR_ID(0xef, 0x40, 0x13),
.name = "s25fl004k",
@@ -1170,9 +1153,31 @@ static const struct spi_nor_fixups spansion_nor_fixups = {
.late_init = spansion_nor_late_init,
};
+static const struct spi_nor_fixup spansion_fixups[] = {
+ { .fixups = &spansion_nor_fixups },
+ { .id = SNOR_ID(0x01, 0x02, 0x20, 0x4d, 0x00, 0x81), .fixups = &s25fs_s_nor_fixups },
+ { .id = SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01, 0x81), .fixups = &s25fs_s_nor_fixups },
+ { .id = SNOR_ID(0x34, 0x2a, 0x1a, 0x0f, 0x03, 0x90), .fixups = &s25hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x2a, 0x1b, 0x0f, 0x03, 0x90), .fixups = &s25hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x2a, 0x1c, 0x0f, 0x00, 0x90), .fixups = &s25hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x2b, 0x19, 0x0f, 0x08, 0x90), .fixups = &s25fs256t_fixups },
+ { .id = SNOR_ID(0x34, 0x2b, 0x1a, 0x0f, 0x03, 0x90), .fixups = &s25hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x2b, 0x1b, 0x0f, 0x03, 0x90), .fixups = &s25hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x2b, 0x1c, 0x0f, 0x00, 0x90), .fixups = &s25hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5a, 0x19), .fixups = &s28hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5a, 0x1a), .fixups = &s28hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5a, 0x1b), .fixups = &s28hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5a, 0x1c), .fixups = &s28hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5b, 0x19), .fixups = &s28hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5b, 0x1a), .fixups = &s28hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5b, 0x1b), .fixups = &s28hx_t_fixups },
+ { .id = SNOR_ID(0x34, 0x5b, 0x1c), .fixups = &s28hx_t_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_spansion = {
.name = "spansion",
.parts = spansion_nor_parts,
.nparts = ARRAY_SIZE(spansion_nor_parts),
- .fixups = &spansion_nor_fixups,
+ .fixups = spansion_fixups,
+ .nfixups = ARRAY_SIZE(spansion_fixups),
};
@@ -152,14 +152,12 @@ static const struct flash_info sst_nor_parts[] = {
.id = SNOR_ID(0xbf, 0x26, 0x42),
.name = "sst26vf032b",
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
- .fixups = &sst26vf_nor_fixups,
}, {
.id = SNOR_ID(0xbf, 0x26, 0x43),
.name = "sst26vf064b",
.size = SZ_8M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE,
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
- .fixups = &sst26vf_nor_fixups,
}, {
.id = SNOR_ID(0xbf, 0x26, 0x51),
.name = "sst26wf016b",
@@ -278,9 +276,16 @@ static const struct spi_nor_fixups sst_nor_fixups = {
.late_init = sst_nor_late_init,
};
+static const struct spi_nor_fixup sst_fixups[] = {
+ { .fixups = &sst_nor_fixups },
+ { .id = SNOR_ID(0xbf, 0x26, 0x42), .fixups = &sst26vf_nor_fixups },
+ { .id = SNOR_ID(0xbf, 0x26, 0x43), .fixups = &sst26vf_nor_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_sst = {
.name = "sst",
.parts = sst_nor_parts,
.nparts = ARRAY_SIZE(sst_nor_parts),
- .fixups = &sst_nor_fixups,
+ .fixups = sst_fixups,
+ .nfixups = ARRAY_SIZE(sst_fixups),
};
@@ -219,7 +219,6 @@ static const struct flash_info winbond_nor_parts[] = {
.size = SZ_16M,
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
.flags = SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_HAS_CMP,
- .fixups = &w25q128_fixups,
}, {
/* W25Q256JV-Q/N */
.id = SNOR_ID(0xef, 0x40, 0x19),
@@ -228,7 +227,6 @@ static const struct flash_info winbond_nor_parts[] = {
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
.flags = SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP,
- .fixups = &w25q256_fixups,
}, {
/* W25Q512JV-Q/N */
.id = SNOR_ID(0xef, 0x40, 0x20),
@@ -242,7 +240,6 @@ static const struct flash_info winbond_nor_parts[] = {
.id = SNOR_ID(0xef, 0x40, 0x21),
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 |
SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP,
- .fixups = &winbond_nor_multi_die_fixups,
}, {
.id = SNOR_ID(0xef, 0x50, 0x12),
.name = "w25q20bw",
@@ -345,13 +342,11 @@ static const struct flash_info winbond_nor_parts[] = {
.id = SNOR_ID(0xef, 0x70, 0x21),
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 |
SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP,
- .fixups = &winbond_nor_multi_die_fixups,
}, {
/* W25Q02JV-M */
.id = SNOR_ID(0xef, 0x70, 0x22),
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 |
SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP,
- .fixups = &winbond_nor_multi_die_fixups,
}, {
.id = SNOR_ID(0xef, 0x71, 0x19),
.name = "w25m512jv",
@@ -553,9 +548,19 @@ static const struct spi_nor_fixups winbond_nor_fixups = {
.late_init = winbond_nor_late_init,
};
+static const struct spi_nor_fixup winbond_fixups[] = {
+ { .fixups = &winbond_nor_fixups },
+ { .id = SNOR_ID(0xef, 0x40, 0x18), .fixups = &w25q128_fixups },
+ { .id = SNOR_ID(0xef, 0x40, 0x19), .fixups = &w25q256_fixups },
+ { .id = SNOR_ID(0xef, 0x40, 0x21), .fixups = &winbond_nor_multi_die_fixups },
+ { .id = SNOR_ID(0xef, 0x70, 0x21), .fixups = &winbond_nor_multi_die_fixups },
+ { .id = SNOR_ID(0xef, 0x70, 0x22), .fixups = &winbond_nor_multi_die_fixups },
+};
+
const struct spi_nor_manufacturer spi_nor_winbond = {
.name = "winbond",
.parts = winbond_nor_parts,
.nparts = ARRAY_SIZE(winbond_nor_parts),
- .fixups = &winbond_nor_fixups,
+ .fixups = winbond_fixups,
+ .nfixups = ARRAY_SIZE(winbond_fixups),
};