Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'spi-nor/for-6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux into mtd/next

SPI NOR changes for 6.19

Notable changes:

- Fix SMPT parsing for S25FS-S flash family. They report variable dummy
cycles for reads. This results in the default of 0 being used. This
works for other Infineon chips, but not for the S25FS-S family. They
need 8 dummy cycles. Add fixup hooks to specify that. Also add fixup
hooks to fix incorrect map ID data in SFDP.

- Add support for a bunch of Winbond flashes. Their block protection
information is not discoverable, so they need to have an entry in the
flash tables to describe that.

- Some cleanups for Micron flash support.

- Add support for Micron mt35xu01gbba.

- Some SPI controllers like the Intel one on the PCI bus do not support
the read CR opcode (0x35). Do not use the opcode if the controller
does not support it.

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQTlUWNzXGEo3bFmyIR4drqP028CQUCaSjP+QAKCRAR4drqP028
# CfGsAQC5Vj+FaeQHyY+yywqM5wxE+xj6mMCDNixd2FVYlf5b7wEA2/9bpiHjy3qi
# 4MZmFJNcE+XsxReWDTBTZ6VbrjDlqg0=
# =M+s4
# -----END PGP SIGNATURE-----
# gpg: Signature made jeu. 27 nov. 2025 23:26:01 CET
# gpg: using EDDSA key 1395458DCD7184A376C59B2211E1DAEA3F4DBC09
# gpg: Good signature from "Pratyush Yadav <p.yadav@ti.com>" [expired]
# gpg: aka "Pratyush Yadav <me@yadavpratyush.com>" [expired]
# gpg: p.yadav@ti.com: Verified 5 signatures in the past 3 years. Encrypted 0 messages.
# gpg: me@yadavpratyush.com: Verified 5 signatures in the past 3 years. Encrypted
# 0 messages.
# gpg: Note: This key has expired!
# Primary key fingerprint: 805C 3923 2FBE 108C 49E1 663C F650 3556 C11B 1CCD
# Subkey fingerprint: 1395 458D CD71 84A3 76C5 9B22 11E1 DAEA 3F4D BC09

+164 -46
+1
.mailmap
··· 632 632 Peter Oruba <peter@oruba.de> 633 633 Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> <pierre-louis.bossart@linux.intel.com> 634 634 Pratyush Anand <pratyush.anand@gmail.com> <pratyush.anand@st.com> 635 + Pratyush Yadav <pratyush@kernel.org> <ptyadav@amazon.de> 635 636 Praveen BP <praveenbp@ti.com> 636 637 Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> <pradeepc@codeaurora.org> 637 638 Prasad Sodagudi <quic_psodagud@quicinc.com> <psodagud@codeaurora.org>
+10
drivers/mtd/spi-nor/core.c
··· 2459 2459 &params->page_programs[ppidx])) 2460 2460 *hwcaps &= ~BIT(cap); 2461 2461 } 2462 + 2463 + /* Some SPI controllers might not support CR read opcode. */ 2464 + if (!(nor->flags & SNOR_F_NO_READ_CR)) { 2465 + struct spi_mem_op op = SPI_NOR_RDCR_OP(nor->bouncebuf); 2466 + 2467 + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); 2468 + 2469 + if (spi_nor_spimem_check_op(nor, &op)) 2470 + nor->flags |= SNOR_F_NO_READ_CR; 2471 + } 2462 2472 } 2463 2473 2464 2474 /**
+6
drivers/mtd/spi-nor/core.h
··· 409 409 * flash parameters when information provided by the flash_info 410 410 * table is incomplete or wrong. 411 411 * @post_bfpt: called after the BFPT table has been parsed 412 + * @smpt_read_dummy: called during SMPT table is being parsed. Used to fix the 413 + * number of dummy cycles in read register ops. 414 + * @smpt_map_id: called after map ID in SMPT table has been determined for the 415 + * case the map ID is wrong and needs to be fixed. 412 416 * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs 413 417 * that do not support RDSFDP). Typically used to tweak various 414 418 * parameters that could not be extracted by other means (i.e. ··· 430 426 int (*post_bfpt)(struct spi_nor *nor, 431 427 const struct sfdp_parameter_header *bfpt_header, 432 428 const struct sfdp_bfpt *bfpt); 429 + void (*smpt_read_dummy)(const struct spi_nor *nor, u8 *read_dummy); 430 + void (*smpt_map_id)(const struct spi_nor *nor, u8 *map_id); 433 431 int (*post_sfdp)(struct spi_nor *nor); 434 432 int (*late_init)(struct spi_nor *nor); 435 433 };
+57 -44
drivers/mtd/spi-nor/micron-st.c
··· 127 127 micron_st_nor_octal_dtr_dis(nor); 128 128 } 129 129 130 - static void mt35xu512aba_default_init(struct spi_nor *nor) 130 + static int micron_st_nor_four_die_late_init(struct spi_nor *nor) 131 131 { 132 - nor->params->set_octal_dtr = micron_st_nor_set_octal_dtr; 132 + struct spi_nor_flash_parameter *params = nor->params; 133 + 134 + params->die_erase_opcode = SPINOR_OP_MT_DIE_ERASE; 135 + params->n_dice = 4; 136 + 137 + /* 138 + * Unfortunately the die erase opcode does not have a 4-byte opcode 139 + * correspondent for these flashes. The SFDP 4BAIT table fails to 140 + * consider the die erase too. We're forced to enter in the 4 byte 141 + * address mode in order to benefit of the die erase. 142 + */ 143 + return spi_nor_set_4byte_addr_mode(nor, true); 144 + } 145 + 146 + static int micron_st_nor_two_die_late_init(struct spi_nor *nor) 147 + { 148 + struct spi_nor_flash_parameter *params = nor->params; 149 + 150 + params->die_erase_opcode = SPINOR_OP_MT_DIE_ERASE; 151 + params->n_dice = 2; 152 + 153 + /* 154 + * Unfortunately the die erase opcode does not have a 4-byte opcode 155 + * correspondent for these flashes. The SFDP 4BAIT table fails to 156 + * consider the die erase too. We're forced to enter in the 4 byte 157 + * address mode in order to benefit of the die erase. 158 + */ 159 + return spi_nor_set_4byte_addr_mode(nor, true); 133 160 } 134 161 135 162 static int mt35xu512aba_post_sfdp_fixup(struct spi_nor *nor) ··· 182 155 } 183 156 184 157 static const struct spi_nor_fixups mt35xu512aba_fixups = { 185 - .default_init = mt35xu512aba_default_init, 186 158 .post_sfdp = mt35xu512aba_post_sfdp_fixup, 159 + }; 160 + 161 + static const struct spi_nor_fixups mt35xu01gbba_fixups = { 162 + .post_sfdp = mt35xu512aba_post_sfdp_fixup, 163 + .late_init = micron_st_nor_two_die_late_init, 187 164 }; 188 165 189 166 static const struct flash_info micron_nor_parts[] = { 190 167 { 168 + /* MT35XU512ABA */ 191 169 .id = SNOR_ID(0x2c, 0x5b, 0x1a), 192 - .name = "mt35xu512aba", 193 - .sector_size = SZ_128K, 194 - .size = SZ_64M, 195 - .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ | 196 - SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP, 197 170 .mfr_flags = USE_FSR, 198 - .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE, 171 + .fixup_flags = SPI_NOR_IO_MODE_EN_VOLATILE, 199 172 .fixups = &mt35xu512aba_fixups, 200 173 }, { 174 + /* MT35XU01GBBA */ 175 + .id = SNOR_ID(0x2c, 0x5b, 0x1b), 176 + .mfr_flags = USE_FSR, 177 + .fixup_flags = SPI_NOR_IO_MODE_EN_VOLATILE, 178 + .fixups = &mt35xu01gbba_fixups, 179 + }, { 180 + /* 181 + * The MT35XU02GCBA flash device does not support chip erase, 182 + * according to its datasheet. It supports die erase, which 183 + * means the current driver implementation will likely need to 184 + * be converted to use die erase. Furthermore, similar to the 185 + * MT35XU01GBBA, the SPI_NOR_IO_MODE_EN_VOLATILE flag probably 186 + * needs to be enabled. 187 + * 188 + * TODO: Fix these and test on real hardware. 189 + */ 201 190 .id = SNOR_ID(0x2c, 0x5b, 0x1c), 202 191 .name = "mt35xu02g", 203 192 .sector_size = SZ_128K, ··· 236 193 .post_bfpt = mt25qu512a_post_bfpt_fixup, 237 194 }; 238 195 239 - static int st_nor_four_die_late_init(struct spi_nor *nor) 240 - { 241 - struct spi_nor_flash_parameter *params = nor->params; 242 - 243 - params->die_erase_opcode = SPINOR_OP_MT_DIE_ERASE; 244 - params->n_dice = 4; 245 - 246 - /* 247 - * Unfortunately the die erase opcode does not have a 4-byte opcode 248 - * correspondent for these flashes. The SFDP 4BAIT table fails to 249 - * consider the die erase too. We're forced to enter in the 4 byte 250 - * address mode in order to benefit of the die erase. 251 - */ 252 - return spi_nor_set_4byte_addr_mode(nor, true); 253 - } 254 - 255 - static int st_nor_two_die_late_init(struct spi_nor *nor) 256 - { 257 - struct spi_nor_flash_parameter *params = nor->params; 258 - 259 - params->die_erase_opcode = SPINOR_OP_MT_DIE_ERASE; 260 - params->n_dice = 2; 261 - 262 - /* 263 - * Unfortunately the die erase opcode does not have a 4-byte opcode 264 - * correspondent for these flashes. The SFDP 4BAIT table fails to 265 - * consider the die erase too. We're forced to enter in the 4 byte 266 - * address mode in order to benefit of the die erase. 267 - */ 268 - return spi_nor_set_4byte_addr_mode(nor, true); 269 - } 270 - 271 196 static const struct spi_nor_fixups n25q00_fixups = { 272 - .late_init = st_nor_four_die_late_init, 197 + .late_init = micron_st_nor_four_die_late_init, 273 198 }; 274 199 275 200 static const struct spi_nor_fixups mt25q01_fixups = { 276 - .late_init = st_nor_two_die_late_init, 201 + .late_init = micron_st_nor_two_die_late_init, 277 202 }; 278 203 279 204 static const struct spi_nor_fixups mt25q02_fixups = { 280 - .late_init = st_nor_four_die_late_init, 205 + .late_init = micron_st_nor_four_die_late_init, 281 206 }; 282 207 283 208 static const struct flash_info st_nor_parts[] = { ··· 645 634 646 635 if (!params->set_4byte_addr_mode) 647 636 params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b; 637 + 638 + params->set_octal_dtr = micron_st_nor_set_octal_dtr; 648 639 649 640 return 0; 650 641 }
+28 -2
drivers/mtd/spi-nor/sfdp.c
··· 699 699 } 700 700 } 701 701 702 + static void spi_nor_smpt_read_dummy_fixups(const struct spi_nor *nor, 703 + u8 *read_dummy) 704 + { 705 + if (nor->manufacturer && nor->manufacturer->fixups && 706 + nor->manufacturer->fixups->smpt_read_dummy) 707 + nor->manufacturer->fixups->smpt_read_dummy(nor, read_dummy); 708 + 709 + if (nor->info->fixups && nor->info->fixups->smpt_read_dummy) 710 + nor->info->fixups->smpt_read_dummy(nor, read_dummy); 711 + } 712 + 702 713 /** 703 714 * spi_nor_smpt_read_dummy() - return the configuration detection command read 704 715 * latency, in clock cycles. ··· 722 711 { 723 712 u8 read_dummy = SMPT_CMD_READ_DUMMY(settings); 724 713 725 - if (read_dummy == SMPT_CMD_READ_DUMMY_IS_VARIABLE) 726 - return nor->read_dummy; 714 + if (read_dummy == SMPT_CMD_READ_DUMMY_IS_VARIABLE) { 715 + read_dummy = nor->read_dummy; 716 + spi_nor_smpt_read_dummy_fixups(nor, &read_dummy); 717 + } 718 + 727 719 return read_dummy; 720 + } 721 + 722 + static void spi_nor_smpt_map_id_fixups(const struct spi_nor *nor, u8 *map_id) 723 + { 724 + if (nor->manufacturer && nor->manufacturer->fixups && 725 + nor->manufacturer->fixups->smpt_map_id) 726 + nor->manufacturer->fixups->smpt_map_id(nor, map_id); 727 + 728 + if (nor->info->fixups && nor->info->fixups->smpt_map_id) 729 + nor->info->fixups->smpt_map_id(nor, map_id); 728 730 } 729 731 730 732 /** ··· 792 768 */ 793 769 map_id = map_id << 1 | !!(*buf & read_data_mask); 794 770 } 771 + 772 + spi_nor_smpt_map_id_fixups(nor, &map_id); 795 773 796 774 /* 797 775 * If command descriptors are provided, they always precede map
+38
drivers/mtd/spi-nor/spansion.c
··· 785 785 return 0; 786 786 } 787 787 788 + static void s25fs_s_nor_smpt_read_dummy(const struct spi_nor *nor, 789 + u8 *read_dummy) 790 + { 791 + /* 792 + * The configuration detection dwords in S25FS-S SMPT has 65h as 793 + * command instruction and 'variable' as configuration detection command 794 + * latency. Set 8 dummy cycles as it is factory default for 65h (read 795 + * any register) op. 796 + */ 797 + *read_dummy = 8; 798 + } 799 + 800 + static void s25fs_s_nor_smpt_map_id_dummy(const struct spi_nor *nor, u8 *map_id) 801 + { 802 + /* 803 + * The S25FS512S chip supports: 804 + * - Hybrid sector option which has physical set of eight 4-KB sectors 805 + * and one 224-KB sector at the top or bottom of address space with 806 + * all remaining sectors of 256-KB 807 + * - Uniform sector option which has uniform 256-KB sectors 808 + * 809 + * On the other hand, the datasheet rev.O Table 71 on page 153 JEDEC 810 + * Sector Map Parameter Dword-6 Config. Detect-3 does use CR3NV[1] to 811 + * discern 64-KB(CR3NV[1]=0) and 256-KB(CR3NV[1]=1) uniform sectors 812 + * device configuration. And in section 7.5.5.1 Configuration Register 3 813 + * Non-volatile (CR3NV) page 61, the CR3NV[1] is RFU Reserved for Future 814 + * Use and set to 0, which means 64-KB uniform. Since the device does 815 + * not support 64-KB uniform sectors in any configuration, parsing SMPT 816 + * table cannot find a valid sector map entry and fails. Fix this up by 817 + * setting SMPT by overwriting the CR3NV[1] value to 1, as the table 818 + * expects. 819 + */ 820 + if (nor->params->size == SZ_64M) 821 + *map_id |= BIT(0); 822 + } 823 + 788 824 static const struct spi_nor_fixups s25fs_s_nor_fixups = { 789 825 .post_bfpt = s25fs_s_nor_post_bfpt_fixups, 826 + .smpt_read_dummy = s25fs_s_nor_smpt_read_dummy, 827 + .smpt_map_id = s25fs_s_nor_smpt_map_id_dummy, 790 828 }; 791 829 792 830 static const struct flash_info spansion_nor_parts[] = {
+24
drivers/mtd/spi-nor/winbond.c
··· 343 343 .id = SNOR_ID(0xef, 0x80, 0x20), 344 344 .name = "w25q512nwm", 345 345 .otp = SNOR_OTP(256, 3, 0x1000, 0x1000), 346 + }, { 347 + /* W25Q01NWxxIQ */ 348 + .id = SNOR_ID(0xef, 0x60, 0x21), 349 + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 350 + }, { 351 + /* W25Q01NWxxIM */ 352 + .id = SNOR_ID(0xef, 0x80, 0x21), 353 + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 354 + }, { 355 + /* W25Q02NWxxIM */ 356 + .id = SNOR_ID(0xef, 0x80, 0x22), 357 + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 358 + }, { 359 + /* W25H512NWxxAM */ 360 + .id = SNOR_ID(0xef, 0xa0, 0x20), 361 + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 362 + }, { 363 + /* W25H01NWxxAM */ 364 + .id = SNOR_ID(0xef, 0xa0, 0x21), 365 + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 366 + }, { 367 + /* W25H02NWxxAM */ 368 + .id = SNOR_ID(0xef, 0xa0, 0x22), 369 + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 346 370 }, 347 371 }; 348 372