[PATCH] mtd: spi-nor: spansion: Add SMPT fixup for S25FS512S
Marek Vasut
marek.vasut+renesas at mailbox.org
Sat Sep 14 15:08:16 PDT 2024
The S25FS512S chip datasheet rev.O Table 71 on page 153 JEDEC Sector Map
Parameter Dword-6 Config. Detect-3 does use CR3NV bit 1 to discern 64kiB
and 256kiB uniform sectors device configuration, however according to
section 7.5.5.1 Configuration Register 3 Non-volatile (CR3NV) page 61,
the CR3NV bit 1 is RFU Reserved for Future Use, and is set to 0 on newly
manufactured devices, which means 64kiB sectors. Since the device does not
support 64kiB uniform sectors in any configuration, parsing SMPT table
cannot find a valid sector map entry and fails.
Fix this up by setting SMPT configuration index bit 0, which is populated
exactly by the CR3NV bit 1 being 1. This is implemented via new .post_smpt
fixup hook and a wrapper function. The only implementation of the hook is
currently specific to S25FS512S.
This fixes the following failure on S25FS512S:
spi-nor spi0.0: Failed to parse optional parameter table: ff81 (err=-22)
Signed-off-by: Marek Vasut <marek.vasut+renesas at mailbox.org>
---
Cc: Geert Uytterhoeven <geert+renesas at glider.be>
Cc: Michael Walle <mwalle at kernel.org>
Cc: Miquel Raynal <miquel.raynal at bootlin.com>
Cc: Pratyush Yadav <pratyush at kernel.org>
Cc: Richard Weinberger <richard at nod.at>
Cc: Tudor Ambarus <tudor.ambarus at linaro.org>
Cc: Vignesh Raghavendra <vigneshr at ti.com>
Cc: linux-mtd at lists.infradead.org
Cc: linux-renesas-soc at vger.kernel.org
---
drivers/mtd/spi-nor/core.c | 17 +++++++++++++++++
drivers/mtd/spi-nor/core.h | 5 +++++
drivers/mtd/spi-nor/sfdp.c | 4 ++++
drivers/mtd/spi-nor/spansion.c | 27 ++++++++++++++++++++++++++-
4 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 9d6e85bf227b..ca65f36e5638 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2405,6 +2405,23 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
return 0;
}
+int spi_nor_post_smpt_fixups(struct spi_nor *nor, u8 *smpt)
+{
+ int ret;
+
+ if (nor->manufacturer && nor->manufacturer->fixups &&
+ nor->manufacturer->fixups->post_smpt) {
+ ret = nor->manufacturer->fixups->post_smpt(nor, smpt);
+ if (ret)
+ return ret;
+ }
+
+ if (nor->info->fixups && nor->info->fixups->post_smpt)
+ return nor->info->fixups->post_smpt(nor, smpt);
+
+ return 0;
+}
+
static int spi_nor_select_read(struct spi_nor *nor,
u32 shared_hwcaps)
{
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 1516b6d0dc37..d5294424ab9d 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -413,6 +413,8 @@ struct spi_nor_flash_parameter {
* parameters that could not be extracted by other means (i.e.
* when information provided by the SFDP/flash_info tables are
* incomplete or wrong).
+ * @post_smpt: update sector map configuration ID selector according to
+ * chip-specific quirks.
* @late_init: used to initialize flash parameters that are not declared in the
* JESD216 SFDP standard, or where SFDP tables not defined at all.
* Will replace the default_init() hook.
@@ -426,6 +428,7 @@ struct spi_nor_fixups {
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt);
int (*post_sfdp)(struct spi_nor *nor);
+ int (*post_smpt)(struct spi_nor *nor, u8 *smpt);
int (*late_init)(struct spi_nor *nor);
};
@@ -660,6 +663,8 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt);
+int spi_nor_post_smpt_fixups(struct spi_nor *nor, u8 *stmp);
+
void spi_nor_init_default_locking_ops(struct spi_nor *nor);
void spi_nor_try_unlock_all(struct spi_nor *nor);
void spi_nor_set_mtd_locking_ops(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 5b1117265bd2..542c775918ad 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -765,6 +765,10 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
map_id = map_id << 1 | !!(*buf & read_data_mask);
}
+ err = spi_nor_post_smpt_fixups(nor, &map_id);
+ if (err)
+ return ERR_PTR(err);
+
/*
* If command descriptors are provided, they always precede map
* descriptors in the table. There is no need to start the iteration
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index d6c92595f6bc..d446d12371e1 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -757,6 +757,31 @@ static const struct spi_nor_fixups s25fs_s_nor_fixups = {
.post_bfpt = s25fs_s_nor_post_bfpt_fixups,
};
+static int s25fs512s_nor_post_smpt_fixups(struct spi_nor *nor, u8 *smpt)
+{
+ /*
+ * The S25FS512S chip datasheet rev.O Table 71 on page 153
+ * JEDEC Sector Map Parameter Dword-6 Config. Detect-3 does
+ * use CR3NV bit 1 to discern 64kiB/256kiB uniform sectors
+ * device configuration, however according to section 7.5.5.1
+ * Configuration Register 3 Non-volatile (CR3NV) page 61, the
+ * CR3NV bit 1 is RFU Reserved for Future Use, and is set to
+ * 0 on newly manufactured devices, which means 64kiB sectors.
+ * Since the device does not support 64kiB uniform sectors in
+ * any configuration, parsing SMPT table cannot find a valid
+ * sector map entry and fails. Fix this up by setting SMPT
+ * configuration index bit 0, which is populated exactly by
+ * the CR3NV bit 1 being 1.
+ */
+ *smpt |= BIT(0);
+ return 0;
+}
+
+static const struct spi_nor_fixups s25fs512s_nor_fixups = {
+ .post_bfpt = s25fs_s_nor_post_bfpt_fixups,
+ .post_smpt = s25fs512s_nor_post_smpt_fixups,
+};
+
static const struct flash_info spansion_nor_parts[] = {
{
.id = SNOR_ID(0x01, 0x02, 0x12),
@@ -829,7 +854,7 @@ 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,
+ .fixups = &s25fs512s_nor_fixups,
}, {
.id = SNOR_ID(0x01, 0x20, 0x18, 0x03, 0x00),
.name = "s25sl12800",
--
2.45.2
More information about the linux-mtd
mailing list