diff options
| author | Miquel Raynal <miquel.raynal@bootlin.com> | 2026-04-17 21:50:54 +0200 |
|---|---|---|
| committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2026-04-17 21:50:54 +0200 |
| commit | 357e460a3099702a904f8b164a13305c34d4385d (patch) | |
| tree | 4a22fb9edd6fb1dc800d909e25d7ca41878f7170 /drivers/mtd | |
| parent | b800359a4dfacae983cd01f8c3f1cbb6f4c9f816 (diff) | |
| parent | cf6788aed0cd911c2e7dded6f28214996dfabc30 (diff) | |
| download | linux-next-357e460a3099702a904f8b164a13305c34d4385d.tar.gz linux-next-357e460a3099702a904f8b164a13305c34d4385d.zip | |
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 7f77c561e227 ("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.
Diffstat (limited to 'drivers/mtd')
| -rw-r--r-- | drivers/mtd/spi-nor/core.c | 2 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/core.h | 2 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/micron-st.c | 27 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/sst.c | 13 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/swp.c | 4 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/winbond.c | 4 |
6 files changed, 35 insertions, 17 deletions
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 8ffeb41c3e08..e6c1fda61f57 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -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); diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 16b382d4f04f..e838c40a2589 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -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 diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c index 88033384a71e..c75b0a1cd567 100644 --- a/drivers/mtd/spi-nor/micron-st.c +++ b/drivers/mtd/spi-nor/micron-st.c @@ -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, }, }; diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c index 175211fe6a5e..db02c14ba16f 100644 --- a/drivers/mtd/spi-nor/sst.c +++ b/drivers/mtd/spi-nor/sst.c @@ -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. */ diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c index 9b07f83aeac7..e67a81dbb6bf 100644 --- a/drivers/mtd/spi-nor/swp.c +++ b/drivers/mtd/spi-nor/swp.c @@ -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) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index fb855fe44733..eaa547d36aad 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -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), |
