NVIDIA: SAUCE: s25fs: Add post-get-map-id fixup
BugLink: https://bugs.launchpad.net/bugs/2080908 Add a post-get-map-id fixup for S25FS512S flash devices. The fixup reads the values of the CR3V and CR1V registers and determines the map ID based on those values. The fixup also checks for invalid combinations of CR3V and CR1V values and returns 0 in those cases. This fixup is necessary to workaround an issue with the SFDP Address Map for S25FS512S flash devices. The SFDP Address Map for these devices incorrectly reports that the map ID is 0 when it should be 1. This issue can cause problems when trying to erase sectors on the flash device. The fixup in this commit will force the flash device to use the first sector address map, which is the correct map for S25FS512S flash devices. http://nvbugs/4218915 Signed-off-by: Vishwaroop A <va@nvidia.com> Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com> Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Acked-by: Noah Wager <noah.wager@canonical.com> Acked-by: Jacob Martin <jacob.martin@canonical.com> Signed-off-by: Noah Wager <noah.wager@canonical.com>
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
Reference in New Issue
Block a user