diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 4129764fad8c..19680304d14c 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2496,6 +2496,35 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor, return 0; } +/* + * spi_nor_post_get_map_id_fixups - Perform post-processing + * fixups after getting the flash device's map ID. + * @nor: Pointer to the spi_nor structure describing the flash device. + * @smpt: Pointer to the sector map parameter table retrieved from the flash device. + * @smpt_len: Length of the sector map parameter table. + * @map_id: Pointer to the variable storing the map ID of the flash device (output). + * + * This function allows for post-processing fixups to be applied after obtaining the map ID + * of the flash device. It checks if there are any registered fixup functions provided by + * the flash device's info structure. If a fixup function is available, it is called to perform + * any necessary adjustments or corrections. If the fixup function returns a non-zero value, + * it updates the map ID accordingly. + * + * @return: None. + */ +void spi_nor_post_get_map_id_fixups(struct spi_nor *nor, const u32 *smpt, + u8 smpt_len, u8 *map_id) +{ + int ret = 0; + + if (nor->info->fixups && nor->info->fixups->post_get_map_id) { + ret = nor->info->fixups->post_get_map_id(nor, smpt, smpt_len); + if (ret) + *map_id = ret; + } + return; +} + 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 d36c0e072954..fe57d585f67c 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -446,6 +446,7 @@ struct spi_nor_fixups { const struct sfdp_bfpt *bfpt); int (*post_sfdp)(struct spi_nor *nor); int (*late_init)(struct spi_nor *nor); + int (*post_get_map_id)(struct spi_nor *nor, const u32 *smpt, u8 smpt_len); }; /** @@ -684,6 +685,9 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt); +void spi_nor_post_get_map_id_fixups(struct spi_nor *nor, const u32 *smpt, + u8 smpt_len, u8 *map_id); + 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 57713de32832..04eb53ea0464 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -771,6 +771,8 @@ 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); } + spi_nor_post_get_map_id_fixups(nor, smpt, smpt_len, &map_id); + /* * 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 020994374ea1..3ed5d741a9bd 100644 --- a/drivers/mtd/spi-nor/spansion.c +++ b/drivers/mtd/spi-nor/spansion.c @@ -25,6 +25,7 @@ #define SPINOR_REG_CYPRESS_STR1V \ (SPINOR_REG_CYPRESS_VREG + SPINOR_REG_CYPRESS_STR1) #define SPINOR_REG_CYPRESS_CFR1 0x2 +#define SPINOR_REG_CYPRESS_CFR1V 0x00800002 #define SPINOR_REG_CYPRESS_CFR1_QUAD_EN BIT(1) /* Quad Enable */ #define SPINOR_REG_CYPRESS_CFR2 0x3 #define SPINOR_REG_CYPRESS_CFR2V \ @@ -33,6 +34,7 @@ #define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb #define SPINOR_REG_CYPRESS_CFR2_ADRBYT BIT(7) #define SPINOR_REG_CYPRESS_CFR3 0x4 +#define SPINOR_REG_CYPRESS_CFR3V 0x00800004 #define SPINOR_REG_CYPRESS_CFR3_PGSZ BIT(4) /* Page size. */ #define SPINOR_REG_CYPRESS_CFR5 0x6 #define SPINOR_REG_CYPRESS_CFR5_BIT6 BIT(6) @@ -754,8 +756,54 @@ s25fs_s_nor_post_bfpt_fixups(struct spi_nor *nor, return 0; } +static int s25fs_s_nor_post_get_map_id(struct spi_nor *nor, const u32 *smpt, u8 smpt_len) +{ + + /* Read Configuration Register 3 Volatile (CR3V) */ + struct spi_mem_op op1 = + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1), + SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR3V, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1)); + + /* Read Configuration Register 1 Volatile (CR1V) */ + struct spi_mem_op op2 = + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1), + SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR1V, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1)); + + u8 reg_cr3v_val, reg_cr1v_val; + int ret; + + /* Read CR3V value from Configuration Register 3 Volatile */ + ret = spi_mem_exec_op(nor->spimem, &op1); + if (ret) + return ret; + reg_cr3v_val = nor->bouncebuf[0]; + + /* Read CR1V value from Configuration Register 1 Volatile */ + ret = spi_mem_exec_op(nor->spimem, &op2); + if (ret) + return ret; + reg_cr1v_val = nor->bouncebuf[0]; + + /* Determine the map ID based on CR3V[3] and CR1V[2] values */ + if ((!(reg_cr3v_val & BIT(3))) && (!(reg_cr1v_val & BIT(2)))) + return 1; /* CR3V[3] = 0, CR1V[2] = 0, map id = 1 */ + + if ((!(reg_cr3v_val & BIT(3))) && (reg_cr1v_val & BIT(2))) + return 3; /* CR3V[3] = 0, CR1V[2] = 1, map id = 3 */ + + if ((reg_cr3v_val & BIT(3)) && (!(reg_cr1v_val & BIT(2)))) + return 5; /* CR3V[3] = 1, CR1V[2] = 0, map id = 5 */ + + return 0; +} + static const struct spi_nor_fixups s25fs_s_nor_fixups = { .post_bfpt = s25fs_s_nor_post_bfpt_fixups, + .post_get_map_id = s25fs_s_nor_post_get_map_id, }; static const struct flash_info spansion_nor_parts[] = {