[PATCH v1 1/3] mtd: spi-nor: Modify rule for parse sfdp

Jaime Liao jaimeliao.tw at gmail.com
Thu Jul 13 03:50:56 PDT 2023


From: JaimeLiao <jaimeliao.tw at gmail.com>

    With various vendors adhering to the JEDEC Standard, the percentage
    of SPI-NOR flash devices on the market that can read SFDP table is
    increasing.
    To enhance reliance on SFDP table, remove PARSE_SFDP flag,
    allowing all SPI-NOR flash devices to read SFDP talbe. The exception
    to this ule is for ICs that included SPI_NOR_SKIP_SFDP flag.
    Furthermore, to establish a complementary relationship between ID
    table information and SFDP talbe, organize no_sfdp_flags into
    nor->info->flags.
    The flash parameters are then organized by spi_nor_init_flags.

Signed-off-by: JaimeLiao <jaimeliao.tw at gmail.com>
---
 drivers/mtd/spi-nor/core.c | 82 ++++++++++++++++++++------------------
 drivers/mtd/spi-nor/core.h | 39 +++++++-----------
 2 files changed, 59 insertions(+), 62 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 5f29fac8669a..bd2685a03c94 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2024,7 +2024,6 @@ static const struct flash_info spi_nor_generic_flash = {
 	 * sane default.
 	 */
 	.page_size = 256,
-	.parse_sfdp = true,
 };
 
 static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
@@ -2760,50 +2759,51 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 }
 
 /**
- * spi_nor_no_sfdp_init_params() - Initialize the flash's parameters and
- * settings based on nor->info->sfdp_flags. This method should be called only by
- * flashes that do not define SFDP tables. If the flash supports SFDP but the
- * information is wrong and the settings from this function can not be retrieved
+ * spi_nor_flags_init_params() - Initialize the flash's parameters and
+ * settings based on nor->flags. This method should be called by flashes
+ * that define both on SFDP tables and id table informations.
+ * If the flash supports SFDP but the information is wrong
+ * and the settings from this function can not be retrieved
  * by parsing SFDP, one should instead use the fixup hooks and update the wrong
  * bits.
  * @nor:	pointer to a 'struct spi_nor'.
  */
-static void spi_nor_no_sfdp_init_params(struct spi_nor *nor)
+static void spi_nor_flags_init_params(struct spi_nor *nor)
 {
 	struct spi_nor_flash_parameter *params = nor->params;
 	struct spi_nor_erase_map *map = &params->erase_map;
-	const u8 no_sfdp_flags = nor->info->no_sfdp_flags;
+	const u32 flags = nor->flags;
 	u8 i, erase_mask;
 
-	if (no_sfdp_flags & SPI_NOR_DUAL_READ) {
+	if (flags & SPI_NOR_DUAL_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_2],
 					  0, 8, SPINOR_OP_READ_1_1_2,
 					  SNOR_PROTO_1_1_2);
 	}
 
-	if (no_sfdp_flags & SPI_NOR_QUAD_READ) {
+	if (flags & SPI_NOR_QUAD_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_4],
 					  0, 8, SPINOR_OP_READ_1_1_4,
 					  SNOR_PROTO_1_1_4);
 	}
 
-	if (no_sfdp_flags & SPI_NOR_OCTAL_READ) {
+	if (flags & SPI_NOR_OCTAL_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_8],
 					  0, 8, SPINOR_OP_READ_1_1_8,
 					  SNOR_PROTO_1_1_8);
 	}
 
-	if (no_sfdp_flags & SPI_NOR_OCTAL_DTR_READ) {
+	if (flags & SPI_NOR_OCTAL_DTR_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8_DTR],
 					  0, 20, SPINOR_OP_READ_FAST,
 					  SNOR_PROTO_8_8_8_DTR);
 	}
 
-	if (no_sfdp_flags & SPI_NOR_OCTAL_DTR_PP) {
+	if (flags & SPI_NOR_OCTAL_DTR_PP) {
 		params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
 		/*
 		 * Since xSPI Page Program opcode is backward compatible with
@@ -2819,7 +2819,7 @@ static void spi_nor_no_sfdp_init_params(struct spi_nor *nor)
 	 */
 	erase_mask = 0;
 	i = 0;
-	if (no_sfdp_flags & SECT_4K) {
+	if (flags & SECT_4K) {
 		erase_mask |= BIT(i);
 		spi_nor_set_erase_type(&map->erase_type[i], 4096u,
 				       SPINOR_OP_BE_4K);
@@ -2832,8 +2832,8 @@ static void spi_nor_no_sfdp_init_params(struct spi_nor *nor)
 }
 
 /**
- * spi_nor_init_flags() - Initialize NOR flags for settings that are not defined
- * in the JESD216 SFDP standard, thus can not be retrieved when parsing SFDP.
+ * spi_nor_init_flags() - Initialize NOR flags for settings that are defined
+ * in the id table information.
  * @nor:	pointer to a 'struct spi_nor'
  */
 static void spi_nor_init_flags(struct spi_nor *nor)
@@ -2868,6 +2868,24 @@ static void spi_nor_init_flags(struct spi_nor *nor)
 	if (flags & SPI_NOR_RWW && nor->info->n_banks > 1 &&
 	    !nor->controller_ops)
 		nor->flags |= SNOR_F_RWW;
+
+	if (nor->info->flags & SECT_4K)
+		nor->flags |= SNOR_F_SECT_4K;
+
+	if (nor->info->flags & SPI_NOR_DUAL_READ)
+		nor->flags |= SNOR_F_DUAL_READ;
+
+	if (nor->info->flags & SPI_NOR_QUAD_READ)
+		nor->flags |= SNOR_F_QUAD_READ;
+
+	if (nor->info->flags & SPI_NOR_OCTAL_READ)
+		nor->flags |= SNOR_F_OCTAL_READ;
+
+	if (nor->info->flags & SPI_NOR_OCTAL_DTR_READ)
+		nor->flags |= SNOR_F_OCTAL_DTR_READ;
+
+	if (nor->info->flags & SPI_NOR_OCTAL_DTR_PP)
+		nor->flags |= SNOR_F_OCTAL_DTR_PP;
 }
 
 /**
@@ -2901,6 +2919,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 {
 	struct spi_nor_flash_parameter *params = nor->params;
 
+	spi_nor_manufacturer_init_params(nor);
+
 	if (nor->manufacturer && nor->manufacturer->fixups &&
 	    nor->manufacturer->fixups->late_init)
 		nor->manufacturer->fixups->late_init(nor);
@@ -2915,6 +2935,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 	spi_nor_init_flags(nor);
 	spi_nor_init_fixup_flags(nor);
 
+	spi_nor_flags_init_params(nor);
+
 	/*
 	 * NOR protection support. When locking_ops are not provided, we pick
 	 * the default ones.
@@ -2952,19 +2974,17 @@ static void spi_nor_sfdp_init_params_deprecated(struct spi_nor *nor)
  * @nor:	pointer to a 'struct spi_nor'.
  *
  * The method assumes that flash doesn't support SFDP so it initializes flash
- * parameters in spi_nor_no_sfdp_init_params() which later on can be overwritten
+ * parameters in spi_nor_late_init_params() which later on can be overwritten
  * when parsing SFDP, if supported.
  */
 static void spi_nor_init_params_deprecated(struct spi_nor *nor)
 {
-	spi_nor_no_sfdp_init_params(nor);
-
 	spi_nor_manufacturer_init_params(nor);
 
-	if (nor->info->no_sfdp_flags & (SPI_NOR_DUAL_READ |
-					SPI_NOR_QUAD_READ |
-					SPI_NOR_OCTAL_READ |
-					SPI_NOR_OCTAL_DTR_READ))
+	if (nor->info->flags & (SPI_NOR_DUAL_READ |
+				SPI_NOR_QUAD_READ |
+				SPI_NOR_OCTAL_READ |
+				SPI_NOR_OCTAL_DTR_READ))
 		spi_nor_sfdp_init_params_deprecated(nor);
 }
 
@@ -3041,19 +3061,7 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
  *		spi_nor_manufacturer_init_params()
  *
  * which can be overwritten by:
- * 3/ SFDP flash parameters initialization. JESD216 SFDP is a standard and
- *    should be more accurate that the above.
- *		spi_nor_parse_sfdp() or spi_nor_no_sfdp_init_params()
- *
- *    Please note that there is a ->post_bfpt() fixup hook that can overwrite
- *    the flash parameters and settings immediately after parsing the Basic
- *    Flash Parameter Table.
- *    spi_nor_post_sfdp_fixups() is called after the SFDP tables are parsed.
- *    It is used to tweak various flash parameters when information provided
- *    by the SFDP tables are wrong.
- *
- * which can be overwritten by:
- * 4/ Late flash parameters initialization, used to initialize flash
+ * 3/ Late flash parameters initialization, used to initialize flash
  * parameters that are not declared in the JESD216 SFDP standard, or where SFDP
  * tables are not defined at all.
  *		spi_nor_late_init_params()
@@ -3070,14 +3078,12 @@ static int spi_nor_init_params(struct spi_nor *nor)
 
 	spi_nor_init_default_params(nor);
 
-	if (nor->info->parse_sfdp) {
+	if (!(nor->info->flags & SPI_NOR_SKIP_SFDP)) {
 		ret = spi_nor_parse_sfdp(nor);
 		if (ret) {
 			dev_err(nor->dev, "BFPT parsing failed. Please consider using SPI_NOR_SKIP_SFDP when declaring the flash\n");
 			return ret;
 		}
-	} else if (nor->info->no_sfdp_flags & SPI_NOR_SKIP_SFDP) {
-		spi_nor_no_sfdp_init_params(nor);
 	} else {
 		spi_nor_init_params_deprecated(nor);
 	}
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 4fb5ff09c63a..f6de738a506c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -132,6 +132,13 @@ enum spi_nor_option_flags {
 	SNOR_F_SWP_IS_VOLATILE	= BIT(13),
 	SNOR_F_RWW		= BIT(14),
 	SNOR_F_ECC		= BIT(15),
+	SNOR_F_SECT_4K		= BIT(16),
+	SNOR_F_DUAL_READ	= BIT(17),
+	SNOR_F_QUAD_READ	= BIT(18),
+	SNOR_F_OCTAL_READ	= BIT(19),
+	SNOR_F_OCTAL_DTR_READ	= BIT(20),
+	SNOR_F_OCTAL_DTR_PP	= BIT(21),
+
 };
 
 struct spi_nor_read_command {
@@ -447,9 +454,6 @@ struct spi_nor_fixups {
  * @page_size:      the flash's page size.
  * @addr_nbytes:    number of address bytes to send.
  *
- * @parse_sfdp:     true when flash supports SFDP tables. The false value has no
- *                  meaning. If one wants to skip the SFDP tables, one should
- *                  instead use the SPI_NOR_SKIP_SFDP sfdp_flag.
  * @flags:          flags that indicate support that is not defined by the
  *                  JESD216 standard in its SFDP tables. Flag meanings:
  *   SPI_NOR_HAS_LOCK:        flash supports lock/unlock via SR
@@ -469,10 +473,6 @@ struct spi_nor_fixups {
  *   SPI_NOR_NO_FR:           can't do fastread.
  *   SPI_NOR_QUAD_PP:         flash supports Quad Input Page Program.
  *   SPI_NOR_RWW:             flash supports reads while write.
- *
- * @no_sfdp_flags:  flags that indicate support that can be discovered via SFDP.
- *                  Used when SFDP tables are not defined in the flash. These
- *                  flags are used together with the SPI_NOR_SKIP_SFDP flag.
  *   SPI_NOR_SKIP_SFDP:       skip parsing of SFDP tables.
  *   SECT_4K:                 SPINOR_OP_BE_4K works uniformly.
  *   SPI_NOR_DUAL_READ:       flash supports Dual Read.
@@ -508,8 +508,7 @@ struct flash_info {
 	u8 n_banks;
 	u8 addr_nbytes;
 
-	bool parse_sfdp;
-	u16 flags;
+	u32 flags;
 #define SPI_NOR_HAS_LOCK		BIT(0)
 #define SPI_NOR_HAS_TB			BIT(1)
 #define SPI_NOR_TB_SR_BIT6		BIT(2)
@@ -521,15 +520,13 @@ struct flash_info {
 #define SPI_NOR_NO_FR			BIT(8)
 #define SPI_NOR_QUAD_PP			BIT(9)
 #define SPI_NOR_RWW			BIT(10)
-
-	u8 no_sfdp_flags;
-#define SPI_NOR_SKIP_SFDP		BIT(0)
-#define SECT_4K				BIT(1)
-#define SPI_NOR_DUAL_READ		BIT(3)
-#define SPI_NOR_QUAD_READ		BIT(4)
-#define SPI_NOR_OCTAL_READ		BIT(5)
-#define SPI_NOR_OCTAL_DTR_READ		BIT(6)
-#define SPI_NOR_OCTAL_DTR_PP		BIT(7)
+#define SPI_NOR_SKIP_SFDP		BIT(11)
+#define SECT_4K				BIT(12)
+#define SPI_NOR_DUAL_READ		BIT(13)
+#define SPI_NOR_QUAD_READ		BIT(14)
+#define SPI_NOR_OCTAL_READ		BIT(15)
+#define SPI_NOR_OCTAL_DTR_READ		BIT(16)
+#define SPI_NOR_OCTAL_DTR_PP		BIT(17)
 
 	u8 fixup_flags;
 #define SPI_NOR_4B_OPCODES		BIT(0)
@@ -587,15 +584,9 @@ struct flash_info {
 			.n_regions = (_n_regions),			\
 		},
 
-#define PARSE_SFDP							\
-	.parse_sfdp = true,						\
-
 #define FLAGS(_flags)							\
 		.flags = (_flags),					\
 
-#define NO_SFDP_FLAGS(_no_sfdp_flags)					\
-		.no_sfdp_flags = (_no_sfdp_flags),			\
-
 #define FIXUP_FLAGS(_fixup_flags)					\
 		.fixup_flags = (_fixup_flags),				\
 
-- 
2.25.1




More information about the linux-mtd mailing list