Merge tag 'spi-nor/for-7.1' into mtd/next

SPI NOR changes for 7.1

There is only a collection of bugfixes this time around, with no notable
changes to the core. Some of the more noteworthy bugfixes listed below.

- Enable die erase on MT35XU02GCBA. We knew this flash needed this fixup
since 7f77c561e2 ("mtd: spi-nor: micron-st: add TODO for fixing
mt35xu02gcba") but did not add it due to lack of hardware to test on.

- Fix locking on some Winbond w25q series flashes.

- Fix Auto Address Increment (AAI) writes on SST that flashes that start
  on odd address. The write enable latch needs to be set again after the
  single byte program.
This commit is contained in:
Miquel Raynal
2026-04-17 21:50:54 +02:00
6 changed files with 35 additions and 17 deletions

View File

@@ -2393,7 +2393,7 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor,
/* convert the dummy cycles to the number of bytes */
op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) *
op.dummy.buswidth / 8;
if (spi_nor_protocol_is_dtr(nor->read_proto))
if (spi_nor_protocol_is_dtr(read->proto))
op.dummy.nbytes *= 2;
return spi_nor_spimem_check_op(nor, &op);

View File

@@ -413,7 +413,7 @@ struct spi_nor_flash_parameter {
* number of dummy cycles in read register ops.
* @smpt_map_id: called after map ID in SMPT table has been determined for the
* case the map ID is wrong and needs to be fixed.
* @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
* @post_sfdp: called after SFDP has been parsed (is not called for SPI NORs
* that do not support RDSFDP). Typically used to tweak various
* parameters that could not be extracted by other means (i.e.
* when information provided by the SFDP/flash_info tables are

View File

@@ -167,6 +167,16 @@ static int mt35xu512aba_post_sfdp_fixup(struct spi_nor *nor)
0, 20, SPINOR_OP_MT_DTR_RD,
SNOR_PROTO_8_8_8_DTR);
/*
* Some batches of mt35xu512aba do not contain the OCT DTR command
* information, but do support OCT DTR mode. Add the settings for
* SNOR_CMD_PP_8_8_8_DTR here. This also makes sure the flash can switch
* to OCT DTR mode.
*/
nor->params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP_8_8_8_DTR],
SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR);
nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
nor->params->rdsr_dummy = 8;
nor->params->rdsr_addr_nbytes = 0;
@@ -185,7 +195,7 @@ static const struct spi_nor_fixups mt35xu512aba_fixups = {
.post_sfdp = mt35xu512aba_post_sfdp_fixup,
};
static const struct spi_nor_fixups mt35xu01gbba_fixups = {
static const struct spi_nor_fixups mt35_two_die_fixups = {
.post_sfdp = mt35xu512aba_post_sfdp_fixup,
.late_init = micron_st_nor_two_die_late_init,
};
@@ -202,25 +212,16 @@ static const struct flash_info micron_nor_parts[] = {
.id = SNOR_ID(0x2c, 0x5b, 0x1b),
.mfr_flags = USE_FSR,
.fixup_flags = SPI_NOR_IO_MODE_EN_VOLATILE,
.fixups = &mt35xu01gbba_fixups,
.fixups = &mt35_two_die_fixups,
}, {
/*
* The MT35XU02GCBA flash device does not support chip erase,
* according to its datasheet. It supports die erase, which
* means the current driver implementation will likely need to
* be converted to use die erase. Furthermore, similar to the
* MT35XU01GBBA, the SPI_NOR_IO_MODE_EN_VOLATILE flag probably
* needs to be enabled.
*
* TODO: Fix these and test on real hardware.
*/
.id = SNOR_ID(0x2c, 0x5b, 0x1c),
.name = "mt35xu02g",
.sector_size = SZ_128K,
.size = SZ_256M,
.no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ,
.mfr_flags = USE_FSR,
.fixup_flags = SPI_NOR_4B_OPCODES,
.fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
.fixups = &mt35_two_die_fixups,
},
};

View File

@@ -203,6 +203,8 @@ static int sst_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
/* Start write from odd address. */
if (to % 2) {
bool needs_write_enable = (len > 1);
/* write one byte. */
ret = sst_nor_write_data(nor, to, 1, buf);
if (ret < 0)
@@ -210,6 +212,17 @@ static int sst_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
to++;
actual++;
/*
* Byte program clears the write enable latch. If more
* data needs to be written using the AAI sequence,
* re-enable writes.
*/
if (needs_write_enable) {
ret = spi_nor_write_enable(nor);
if (ret)
goto out;
}
}
/* Write out most of the data here. */

View File

@@ -28,8 +28,10 @@ static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor)
{
if (nor->flags & SNOR_F_HAS_SR_TB_BIT6)
return SR_TB_BIT6;
else
else if (nor->flags & SNOR_F_HAS_SR_TB)
return SR_TB_BIT5;
else
return 0;
}
static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor)

View File

@@ -274,6 +274,7 @@ static const struct flash_info winbond_nor_parts[] = {
.id = SNOR_ID(0xef, 0x60, 0x19),
.name = "w25q256jw",
.size = SZ_32M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP,
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
}, {
.id = SNOR_ID(0xef, 0x60, 0x20),
@@ -295,6 +296,7 @@ static const struct flash_info winbond_nor_parts[] = {
.id = SNOR_ID(0xef, 0x70, 0x17),
.name = "w25q64jvm",
.size = SZ_8M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
.no_sfdp_flags = SECT_4K,
}, {
.id = SNOR_ID(0xef, 0x70, 0x18),
@@ -337,7 +339,7 @@ static const struct flash_info winbond_nor_parts[] = {
.id = SNOR_ID(0xef, 0x80, 0x19),
.name = "w25q256jwm",
.size = SZ_32M,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP,
.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
}, {
.id = SNOR_ID(0xef, 0x80, 0x20),