* [PATCH v2 0/2] mtd: spi-nor: issi: add support for the IS25WX01G octal flash
@ 2026-09-14 13:42 Nuno Sá
2026-09-14 13:42 ` [PATCH v2 1/2] mtd: spi-nor: sfdp: get the 1-1-8 and 1-8-8 page programs from 4BAIT Nuno Sá
2026-09-14 13:42 ` [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g Nuno Sá
0 siblings, 2 replies; 8+ messages in thread
From: Nuno Sá @ 2026-09-14 13:42 UTC (permalink / raw)
To: linux-mtd, linux-kernel
Cc: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal,
Richard Weinberger, Vignesh Raghavendra
This series adds support for the ISSI IS25WX01G, a 1 Gbit (128 MiB) octal
NOR flash.
The part is fully described by SFDP, so patch 2 only needs the flash ID
plus a small post_bfpt fixup:
- The flash has no Status Register 2 and does not implement the 35h Read
Configuration Register command, so the core's default assumption of a
16-bit Write Status command does not hold and SNOR_F_HAS_16BIT_SR has
to be cleared.
- Its BFPT Quad Enable Requirement field carries a reserved value, which
makes spi_nor_parse_bfpt() keep the manufacturer default quad enable
method. As this is an octal-only part with no quad mode at all, the
quad_enable hook is cleared.
Patch 1 is a prerequisite: the 4BAIT parser did not pick up the 1-1-8 and
1-8-8 page program opcodes, which we need since the IS25WX01G is beyond the
3-byte address range.
Changes in v2:
- Patch 2:
* Adapt the code from 6.18 to spi-nor/next;
* Drop .name;
* Add support for flash lock/unlock.
- Link to v1: https://patch.msgid.link/20260911-mtd-spi-nor-new-issi-chip-v1-0-c54615f8c30f@analog.com
---
Nuno Sá (2):
mtd: spi-nor: sfdp: get the 1-1-8 and 1-8-8 page programs from 4BAIT
mtd: spi-nor: issi: Add support for is25wx01g
drivers/mtd/spi-nor/issi.c | 25 +++++++++++++++++++++++++
drivers/mtd/spi-nor/sfdp.c | 10 ++++++++++
2 files changed, 35 insertions(+)
---
base-commit: 700bf34058ca7cd792236b1ba5caad3770d66208
change-id: 20260911-mtd-spi-nor-new-issi-chip-ef3881bab60e
--
Thanks!
- Nuno Sá
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 1/2] mtd: spi-nor: sfdp: get the 1-1-8 and 1-8-8 page programs from 4BAIT 2026-09-14 13:42 [PATCH v2 0/2] mtd: spi-nor: issi: add support for the IS25WX01G octal flash Nuno Sá @ 2026-09-14 13:42 ` Nuno Sá 2026-09-14 13:42 ` [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g Nuno Sá 1 sibling, 0 replies; 8+ messages in thread From: Nuno Sá @ 2026-09-14 13:42 UTC (permalink / raw) To: linux-mtd, linux-kernel Cc: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra Commit af2792abd455 ("mtd: spi-nor: sfdp: get the 1-1-8 and 1-8-8 protocol from SFDP") taught the core to discover octal read support from BFPT, but the 4-Byte Address Instruction Table parser was never extended accordingly. Parse the 1-1-8 and 1-8-8 page program bits of 4BAIT DWORD1 and set the corresponding 4-byte opcodes, so that octal writes stay available once the flash switches to the 4-byte address instruction set. This is in preparation of adding support for the ISSI IS25WX01G, a 1 Gbit octal flash which is beyond the 3-byte address range and advertises 4-byte 1-1-8 and 1-8-8 page program instructions. Signed-off-by: Nuno Sá <nuno.sa@analog.com> --- drivers/mtd/spi-nor/sfdp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index c21a6953db96..8e3989184435 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -1081,6 +1081,8 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, { SNOR_HWCAPS_PP, BIT(6) }, { SNOR_HWCAPS_PP_1_1_4, BIT(7) }, { SNOR_HWCAPS_PP_1_4_4, BIT(8) }, + { SNOR_HWCAPS_PP_1_1_8, BIT(23) }, + { SNOR_HWCAPS_PP_1_8_8, BIT(24) }, }; static const struct sfdp_4bait erases[SNOR_ERASE_TYPE_MAX] = { { 0u /* not used */, BIT(9) }, @@ -1207,6 +1209,14 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, spi_nor_set_pp_settings(¶ms_pp[SNOR_CMD_PP_1_4_4], SPINOR_OP_PP_1_4_4_4B, SNOR_PROTO_1_4_4); + if (pp_hwcaps & SNOR_HWCAPS_PP_1_1_8) + spi_nor_set_pp_settings(¶ms_pp[SNOR_CMD_PP_1_1_8], + SPINOR_OP_PP_1_1_8_4B, + SNOR_PROTO_1_1_8); + if (pp_hwcaps & SNOR_HWCAPS_PP_1_8_8) + spi_nor_set_pp_settings(¶ms_pp[SNOR_CMD_PP_1_8_8], + SPINOR_OP_PP_1_8_8_4B, + SNOR_PROTO_1_8_8); for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { if (erase_mask & BIT(i)) -- 2.55.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g 2026-09-14 13:42 [PATCH v2 0/2] mtd: spi-nor: issi: add support for the IS25WX01G octal flash Nuno Sá 2026-09-14 13:42 ` [PATCH v2 1/2] mtd: spi-nor: sfdp: get the 1-1-8 and 1-8-8 page programs from 4BAIT Nuno Sá @ 2026-09-14 13:42 ` Nuno Sá 2026-09-14 14:04 ` Michael Walle 2026-09-14 14:18 ` sashiko-bot 1 sibling, 2 replies; 8+ messages in thread From: Nuno Sá @ 2026-09-14 13:42 UTC (permalink / raw) To: linux-mtd, linux-kernel Cc: Pratyush Yadav, Michael Walle, Takahiro Kuwano, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra Add support for the ISSI IS25WX01G, a 1 Gbit (128 MiB) octal NOR flash. The part is fully described by SFDP, so only the flash ID and a small post_bfpt fixup are needed. WRITE STATUS REGISTER (01h) takes a single data byte and only affects status register bits 7:2, so the default 16-bit Write Status assumption does not hold. Clear write_sr1_and_sr2 so that the single byte write_sr1 path is taken; write_sr1 is already set to 01h by the BFPT parsing. The flash also has no Status Register 2. Configuration registers are read with B5h/85h and written with B1h/81h, and the 35h Read Configuration Register command does not exist, so clear read_sr2 as well. Software write protection is done through the block protect bits in the status register: BP0-BP2 at bits 4:2, BP3 at bit 6 and a Top/Bottom bit at bit 5, which is exactly what SPI_NOR_HAS_LOCK, SPI_NOR_4BIT_BP, SPI_NOR_BP3_SR_BIT6 and SPI_NOR_HAS_TB describe, so set those flags to get the generic locking support. No quad enable handling is needed: this is an octal part with no quad mode, its BFPT Quad Enable Requirement field carries a reserved value, and spi_nor_parse_bfpt() therefore leaves both quad enable masks zeroed. Signed-off-by: Nuno Sá <nuno.sa@analog.com> --- This flash is populated on the sc846 board and was tested at 125MHz using the cadence xspi (cdns,xspi-nor) SPI controller. (Note that in fact the controller also needs some patches and a new sc846 compatible to integrate) cat /sys/bus/spi/devices/spi6.0/spi-nor/jedec_id 9d5b1b cat /sys/bus/spi/devices/spi6.0/spi-nor/manufacturer issi xxd -p /sys/bus/spi/devices/spi6.0/spi-nor/sfdp 53464450090103ff00070114300000ff84000102a00000ff05000105b000 00ff0a000108d00000ffffffffffffffffffe5208affffffff3f00000000 00000000eeffffffffff00ffffff00000c2011d80f5200ff4462990087ce 04e22801273d7a757a75ffbdd55c000070ff8170f8a12fcb278b00008401 0082080000000088ffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffff430effff21dc5cffffffffffffffffff000b801e b181b58500f0ff9f500a000028d55a8cffffffffffffffffffffffff0000 060100000000000081050000e70000000601000000000000810600e70000 sha256sum /sys/bus/spi/devices/spi6.0/spi-nor/sfdp a1fa0cab6324b45a17e6bd7fc7e581496517d558d8c7684cc85e57a5dfe5d87b /sys/bus/spi/devices/spi6.0/spi-nor/sfdp cat /sys/kernel/debug/spi-nor/spi6.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-1S (fast read) opcode 0x0c mode cycles 0 dummy cycles 8 1S-1S-8S opcode 0x7c mode cycles 1 dummy cycles 7 1S-8S-8S opcode 0xcc mode cycles 1 dummy cycles 15 8D-8D-8D opcode 0x0b mode cycles 0 dummy cycles 20 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-8S opcode 0x84 1S-8S-8S opcode 0x8e 8D-8D-8D opcode 0x12 cat /sys/kernel/debug/spi-nor/spi6.0/params name (null) id 9d 5b 1b 10 01 00 size 128 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_4BIT_BP | HAS_SR_BP3_BIT6 | SOFT_RESET | NO_WP opcodes read 0xcc dummy cycles 16 erase 0xdc program 0x8e 8D extension repeat protocols read 1S-8S-8S write 1S-8S-8S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] 5c (32.0 KiB) [2] dc (128 KiB) [3] c7 (128 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-07ffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | unlocked | 1024 dd if=/dev/urandom of=./spi_test bs=1M count=2 2+0 records in 2+0 records out mtd_debug erase /dev/mtd4 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash mtd_debug read /dev/mtd4 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read mtd_debug write /dev/mtd4 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash mtd_debug read /dev/mtd4 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read sha256sum spi* a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_read a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_test mtd_debug erase /dev/mtd4 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash mtd_debug read /dev/mtd4 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read sha256sum spi* 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_test mtd_debug info /dev/mtd4 mtd.type = MTD_NORFLASH mtd.flags = MTD_CAP_NORFLASH mtd.size = 134217728 (128M) mtd.erasesize = 131072 (128K) mtd.writesize = 1 mtd.oobsize = 0 regions = 0 flash_lock -u /dev/mtd4 flash_lock -i /dev/mtd4 Device: /dev/mtd4 Start: 0 Len: 0x8000000 Lock status: unlocked Return code: 0 mtd_debug erase /dev/mtd4 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash mtd_debug write /dev/mtd4 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash mtd_debug read /dev/mtd4 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read sha256sum spi* a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_read a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_test show_sectors locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | unlocked | 1024 flash_lock -l /dev/mtd4 flash_lock -i /dev/mtd4 Device: /dev/mtd4 Start: 0 Len: 0x8000000 Lock status: locked Return code: 1 mtd_debug erase /dev/mtd4 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash mtd_debug read /dev/mtd4 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read sha256sum spi* a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_read a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_test dd if=/dev/urandom of=./spi_test2 bs=1M count=2 2+0 records in 2+0 records out mtd_debug write /dev/mtd4 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash mtd_debug read /dev/mtd4 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 sha256sum spi* a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_read a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_read2 a1230061123719295de1df8c401601e7ba2c6b163ab2d324d5d254d83ca71108 spi_test 03781ea58ffe95ed666f174f7804b84999f525516595c1ba0f99ee83eb8af22b spi_test2 show_sectors locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | locked | 1024 flash_lock -u /dev/mtd4 (*) flash_lock -l /dev/mtd4 $(($size - (2 * $ss))) $((2 * $bps)) show_sectors locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07fbffff | unlocked | 1022 07fc0000-07ffffff | locked | 2 flash_lock -u /dev/mtd4 $(($size - (2 * $ss))) $((1 * $bps)) show_sectors locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07fdffff | unlocked | 1023 07fe0000-07ffffff | locked | 1 flash_lock -u /dev/mtd4 flash_lock -l /dev/mtd4 $(($size - (2**7 * $ss))) $((2**7 * $bps)) show_sectors locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-06ffffff | unlocked | 896 07000000-07ffffff | locked | 128 (*): I should note that the command actually failed with -EIO but it actually unlocked the chip! And the reason is because the flash as the same FSR register than the micron-st flash. So WEL is set to 1 but can only be cleared when clearing the FSR register. AFAICT, we should do something similar as micron so the writing to an actual protected region fails rather than being silently discarded with that status bit set. The question would be how to do it? The code is pretty much identical to [1]. The masks, the opcoded... So should we somehow handle this in the core (by having some common helper) that could be set in .late_init() under a common MFR_FSR flag? Or just keep both implementations separate for now? [1]: https://elixir.bootlin.com/linux/v7.2.5/source/drivers/mtd/spi-nor/micron-st.c#L585 --- drivers/mtd/spi-nor/issi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c index 2f057d731df2..a0b46c298d53 100644 --- a/drivers/mtd/spi-nor/issi.c +++ b/drivers/mtd/spi-nor/issi.c @@ -29,6 +29,24 @@ static const struct spi_nor_fixups is25lp256_fixups = { .post_bfpt = is25lp256_post_bfpt_fixups, }; +static int is25wx01g_post_bfpt_fixups(struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header, + const struct sfdp_bfpt *bfpt) +{ + /* + * There is no Status Register 2 and no 35h command. And WRITE STATUS + * REGISTER takes a single data byte. + */ + nor->params->opcodes.write_sr1_and_sr2 = 0; + nor->params->opcodes.read_sr2 = 0; + + return 0; +} + +static const struct spi_nor_fixups is25wx01g_fixups = { + .post_bfpt = is25wx01g_post_bfpt_fixups, +}; + static int pm25lv_nor_late_init(struct spi_nor *nor) { struct spi_nor_erase_map *map = &nor->params->erase_map; @@ -120,6 +138,12 @@ static const struct flash_info issi_nor_parts[] = { .id = SNOR_ID(0x9d, 0x70, 0x19), .name = "is25wp256", .flags = SPI_NOR_QUAD_PP, + }, { + /* is25wx01g */ + .id = SNOR_ID(0x9d, 0x5b, 0x1b), + .sector_size = SZ_128K, + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | + SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6, } }; @@ -148,6 +172,7 @@ static const struct spi_nor_fixup issi_fixup_list[] = { .fixup_flags = SPI_NOR_4B_OPCODES }, { .id = SNOR_ID(0x9d, 0x70, 0x19), .fixups = &is25lp256_fixups, .fixup_flags = SPI_NOR_4B_OPCODES }, + { .id = SNOR_ID(0x9d, 0x5b, 0x1b), .fixups = &is25wx01g_fixups }, }; const struct spi_nor_manufacturer spi_nor_issi = { -- 2.55.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g 2026-09-14 13:42 ` [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g Nuno Sá @ 2026-09-14 14:04 ` Michael Walle 2026-09-14 15:31 ` Nuno Sá 2026-09-14 14:18 ` sashiko-bot 1 sibling, 1 reply; 8+ messages in thread From: Michael Walle @ 2026-09-14 14:04 UTC (permalink / raw) To: Nuno Sá, linux-mtd, linux-kernel Cc: Pratyush Yadav, Takahiro Kuwano, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra [-- Attachment #1: Type: text/plain, Size: 1287 bytes --] Hi, On Mon Sep 14, 2026 at 3:42 PM CEST, Nuno Sá wrote: > (*): I should note that the command actually failed with -EIO but it > actually unlocked the chip! And the reason is because the flash as the same > FSR register than the micron-st flash. So WEL is set to 1 but can only > be cleared when clearing the FSR register. Why doesn't this affect only the locking operation? WEL polling is used also during write and erase. > AFAICT, we should do something similar as micron so the writing to an > actual protected region fails rather than being silently discarded with > that status bit set. The question would be how to do it? The code is > pretty much identical to [1]. The masks, the opcoded... So should we > somehow handle this in the core (by having some common helper) that > could be set in .late_init() under a common MFR_FSR flag? Or just keep > both implementations separate for now? I'd like to keep that out of the core.c, but also like to avoid any code duplication esp. because there is already handling for the intel spi controller in there. So maybe move it it into a new common.c. Apart from that, this patch set looks good to go. -michael > [1]: https://elixir.bootlin.com/linux/v7.2.5/source/drivers/mtd/spi-nor/micron-st.c#L585 [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 297 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g 2026-09-14 14:04 ` Michael Walle @ 2026-09-14 15:31 ` Nuno Sá 2026-09-16 7:14 ` Michael Walle 0 siblings, 1 reply; 8+ messages in thread From: Nuno Sá @ 2026-09-14 15:31 UTC (permalink / raw) To: Michael Walle Cc: linux-mtd, linux-kernel, Pratyush Yadav, Takahiro Kuwano, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra On Mon, Sep 14, 2026 at 04:04:40PM +0200, Michael Walle wrote: > Hi, > > On Mon Sep 14, 2026 at 3:42 PM CEST, Nuno Sá wrote: > > (*): I should note that the command actually failed with -EIO but it > > actually unlocked the chip! And the reason is because the flash as the same > > FSR register than the micron-st flash. So WEL is set to 1 but can only > > be cleared when clearing the FSR register. > > Why doesn't this affect only the locking operation? WEL polling is > used also during write and erase. Not sure if I fully understand. But AFAICT, the reason why erase and write is silent is because the default spi_nor_sr_ready() only looks at SR_WIP [1]: OTOH, on the unlock path we do spi_nor_write_sr1_and_sr2_and_check() and give no special handling to WEL so I imagine that we try to set it as 0 but read it as 1 (given that it clears only with FSR) and hence I got the -EIO in [2]. [1]: https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git/tree/drivers/mtd/spi-nor/core.c?h=spi-nor/next#n558 [2]: https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git/tree/drivers/mtd/spi-nor/core.c?h=spi-nor/next#n970 > > > AFAICT, we should do something similar as micron so the writing to an > > actual protected region fails rather than being silently discarded with > > that status bit set. The question would be how to do it? The code is > > pretty much identical to [1]. The masks, the opcoded... So should we > > somehow handle this in the core (by having some common helper) that > > could be set in .late_init() under a common MFR_FSR flag? Or just keep > > both implementations separate for now? > > I'd like to keep that out of the core.c, but also like to avoid any > code duplication esp. because there is already handling for the > intel spi controller in there. So maybe move it it into a new > common.c. Also don't like the dup tbh. Could that be a follow up or should it be v3. From the top of my head I could think on a mfr_common.c kind of thing. Don't thing this FSR register is standard? Thx! - Nuno Sá > > Apart from that, this patch set looks good to go. > > -michael > > > [1]: https://elixir.bootlin.com/linux/v7.2.5/source/drivers/mtd/spi-nor/micron-st.c#L585 > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g 2026-09-14 15:31 ` Nuno Sá @ 2026-09-16 7:14 ` Michael Walle 2026-09-16 8:44 ` Nuno Sá 0 siblings, 1 reply; 8+ messages in thread From: Michael Walle @ 2026-09-16 7:14 UTC (permalink / raw) To: Nuno Sá Cc: linux-mtd, linux-kernel, Pratyush Yadav, Takahiro Kuwano, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra Hi, On Mon Sep 14, 2026 at 5:31 PM CEST, Nuno Sá wrote: > On Mon, Sep 14, 2026 at 04:04:40PM +0200, Michael Walle wrote: >> On Mon Sep 14, 2026 at 3:42 PM CEST, Nuno Sá wrote: >> > (*): I should note that the command actually failed with -EIO but it >> > actually unlocked the chip! And the reason is because the flash as the same >> > FSR register than the micron-st flash. So WEL is set to 1 but can only >> > be cleared when clearing the FSR register. >> >> Why doesn't this affect only the locking operation? WEL polling is >> used also during write and erase. Sorry I meant WIP. > Not sure if I fully understand. But AFAICT, the reason why erase and > write is silent is because the default spi_nor_sr_ready() only looks at > SR_WIP [1]: So usually, the WEL is cleared automatically by whatever needs the WEL in the first place, i.e. program or erase, write (status) register. That should also be the case for this flash. Now for this flash (as well as the st/micron ones), there is one peculiarity. Whenever there is an error bit set in the FSR, the WEL cannot be cleared by a write disable command. Which we shouldn't need anyway because it should be cleared automatically if nothing goes wrong. Also the write status register won't set the error bits if i read the datasheet correctly and it will always disable the WEL, see Table 29 ("WRITE REGISTER Operations") in the MT35XU512ABA datasheet and Table 8,8 ("WRITE REGISTER Operstaions") in the IS25WX01G datasheet. > OTOH, on the unlock path we do spi_nor_write_sr1_and_sr2_and_check() and > give no special handling to WEL so I imagine that we try to set it as 0 > but read it as 1 (given that it clears only with FSR) and hence I got > the -EIO in [2]. We do a RMW, so my guess is that it's the other way around. We read it as 1, but then after writing the SR, it's 0 (see above). That actually assumes, that if the WEL and any error bit in the FSR is set, a write status register will clear the WEL anyways. Could you debug that so we are sure, this is what actually happens? But the question is who is setting the error bit in the first place. And I guess it's the testing sequence for the locking when you try to write to a locked range. So you could also actually test the locking/unlocking without writing any data to the flash just to see if that is the case. >> > AFAICT, we should do something similar as micron so the writing to an >> > actual protected region fails rather than being silently discarded with >> > that status bit set. The question would be how to do it? The code is >> > pretty much identical to [1]. The masks, the opcoded... So should we >> > somehow handle this in the core (by having some common helper) that >> > could be set in .late_init() under a common MFR_FSR flag? Or just keep >> > both implementations separate for now? >> >> I'd like to keep that out of the core.c, but also like to avoid any >> code duplication esp. because there is already handling for the >> intel spi controller in there. So maybe move it it into a new >> common.c. > > Also don't like the dup tbh. Could that be a follow up or should it be > v3. From the top of my head I could think on a mfr_common.c kind of thing. > Don't thing this FSR register is standard? Not really. But (at least) parts of the datasheets are actually copied verbatim between micron and issi, I wonder if we shouldn't just put the ISSI part in micron-st.c. (Yes vendor will be wrong, but I plan on deprecating that sysfs property anyway). -michael ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g 2026-09-16 7:14 ` Michael Walle @ 2026-09-16 8:44 ` Nuno Sá 0 siblings, 0 replies; 8+ messages in thread From: Nuno Sá @ 2026-09-16 8:44 UTC (permalink / raw) To: Michael Walle Cc: linux-mtd, linux-kernel, Pratyush Yadav, Takahiro Kuwano, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra On Wed, Sep 16, 2026 at 09:14:52AM +0200, Michael Walle wrote: > Hi, > > On Mon Sep 14, 2026 at 5:31 PM CEST, Nuno Sá wrote: > > On Mon, Sep 14, 2026 at 04:04:40PM +0200, Michael Walle wrote: > >> On Mon Sep 14, 2026 at 3:42 PM CEST, Nuno Sá wrote: > >> > (*): I should note that the command actually failed with -EIO but it > >> > actually unlocked the chip! And the reason is because the flash as the same > >> > FSR register than the micron-st flash. So WEL is set to 1 but can only > >> > be cleared when clearing the FSR register. > >> > >> Why doesn't this affect only the locking operation? WEL polling is > >> used also during write and erase. > > Sorry I meant WIP. > > > Not sure if I fully understand. But AFAICT, the reason why erase and > > write is silent is because the default spi_nor_sr_ready() only looks at > > SR_WIP [1]: > > So usually, the WEL is cleared automatically by whatever needs the > WEL in the first place, i.e. program or erase, write (status) > register. That should also be the case for this flash. > > Now for this flash (as well as the st/micron ones), there is one > peculiarity. Whenever there is an error bit set in the FSR, the WEL > cannot be cleared by a write disable command. Which we shouldn't > need anyway because it should be cleared automatically if nothing > goes wrong. > > Also the write status register won't set the error bits if i read > the datasheet correctly and it will always disable the WEL, see > Table 29 ("WRITE REGISTER Operations") in the MT35XU512ABA datasheet > and Table 8,8 ("WRITE REGISTER Operstaions") in the IS25WX01G > datasheet. > > > OTOH, on the unlock path we do spi_nor_write_sr1_and_sr2_and_check() and > > give no special handling to WEL so I imagine that we try to set it as 0 > > but read it as 1 (given that it clears only with FSR) and hence I got > > the -EIO in [2]. > > We do a RMW, so my guess is that it's the other way around. We read > it as 1, but then after writing the SR, it's 0 (see above). That > actually assumes, that if the WEL and any error bit in the FSR is > set, a write status register will clear the WEL anyways. Could you > debug that so we are sure, this is what actually happens? Sure I'll do some debugging on the unlock path. The DS seems a bit unclear. It also states (for the WRITE DISABLE) "...In case of a protection error, WRITE DISABLE will not clear the bit. Instead, a CLEAR FLAG STATUS REGISTER command must be issued to clear both flags. " But the truth is that the second unlock I did came without an error. > > But the question is who is setting the error bit in the first place. > And I guess it's the testing sequence for the locking when you try > to write to a locked range. So you could also actually test the > locking/unlocking without writing any data to the flash just to see > if that is the case. Pretty sure the above is the case! If you look at other tests after "Once we trust the debugfs output we can use it to test various situations. Check top locking/unlocking (end of the device):" Everything worked nicely given we were just doing lock/unlock. The DS is also clear about this (table 8.11): "...When a command is applied to a protected sector, the command is not executed, the write enable latch bit remains set to 1, and flag status register bits 1 and 4 are set. If the operation " I also did tested with basically the same code as in micron-st and then ERASE and PROGRAM commands just return -EIO. > > >> > AFAICT, we should do something similar as micron so the writing to an > >> > actual protected region fails rather than being silently discarded with > >> > that status bit set. The question would be how to do it? The code is > >> > pretty much identical to [1]. The masks, the opcoded... So should we > >> > somehow handle this in the core (by having some common helper) that > >> > could be set in .late_init() under a common MFR_FSR flag? Or just keep > >> > both implementations separate for now? > >> > >> I'd like to keep that out of the core.c, but also like to avoid any > >> code duplication esp. because there is already handling for the > >> intel spi controller in there. So maybe move it it into a new > >> common.c. > > > > Also don't like the dup tbh. Could that be a follow up or should it be > > v3. From the top of my head I could think on a mfr_common.c kind of thing. > > Don't thing this FSR register is standard? > > Not really. > > But (at least) parts of the datasheets are actually copied verbatim > between micron and issi, I wonder if we shouldn't just put the ISSI > part in micron-st.c. (Yes vendor will be wrong, but I plan on > deprecating that sysfs property anyway). Also works for me. Say the word and I can send v3 with this in micron-st.c. - Nuno Sá > > -michael ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g 2026-09-14 13:42 ` [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g Nuno Sá 2026-09-14 14:04 ` Michael Walle @ 2026-09-14 14:18 ` sashiko-bot 1 sibling, 0 replies; 8+ messages in thread From: sashiko-bot @ 2026-09-14 14:18 UTC (permalink / raw) To: Nuno Sá, linux-mtd, linux-kernel Cc: Pratyush Yadav, Takahiro Kuwano, Miquel Raynal, Vignesh Raghavendra, Michael Walle, Richard Weinberger Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Locking operations (spi_nor_sr_lock/unlock) unconditionally fail with -EINVAL because read_sr2 is set to 0. - [High] Missing Flag Status Register (FSR) handling leaves the WEL bit set, causing lock operations to fail with spurious -EIO errors. -- commit e7f55264e73008ad9ab4912b2a3228b2d1b7b7bd Author: Nuno Sá <nuno.sa@analog.com> mtd: spi-nor: issi: Add support for is25wx01g Add support for the ISSI IS25WX01G, a 1 Gbit (128 MiB) octal NOR flash. The part is fully described by SFDP, so only the flash ID and a small post_bfpt fixup are needed. > diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c > index 2f057d731df2a..a0b46c298d53c 100644 > --- a/drivers/mtd/spi-nor/issi.c > +++ b/drivers/mtd/spi-nor/issi.c > @@ -29,6 +29,24 @@ static const struct spi_nor_fixups is25lp256_fixups = { > .post_bfpt = is25lp256_post_bfpt_fixups, > }; > > +static int is25wx01g_post_bfpt_fixups(struct spi_nor *nor, > + const struct sfdp_parameter_header *bfpt_header, > + const struct sfdp_bfpt *bfpt) > +{ > + /* > + * There is no Status Register 2 and no 35h command. And WRITE STATUS > + * REGISTER takes a single data byte. > + */ > + nor->params->opcodes.write_sr1_and_sr2 = 0; > + nor->params->opcodes.read_sr2 = 0; [Severity: High] Does explicitly zeroing read_sr2 break the generic locking support? When locking or unlocking the flash, the core calls spi_nor_write_sr1_and_sr2_and_check(), which delegates to spi_nor_read_sr1_and_sr2() to verify the lock bits. This helper unconditionally calls spi_nor_read_sr2(). If read_sr2 is 0, spi_nor_read_sr2() immediately returns -EINVAL, causing any attempt to lock or unlock the flash to unconditionally fail. > + > + return 0; > +} > + > +static const struct spi_nor_fixups is25wx01g_fixups = { > + .post_bfpt = is25wx01g_post_bfpt_fixups, > +}; > + [ ... ] > @@ -120,6 +138,12 @@ static const struct flash_info issi_nor_parts[] = { > .id = SNOR_ID(0x9d, 0x70, 0x19), > .name = "is25wp256", > .flags = SPI_NOR_QUAD_PP, > + }, { > + /* is25wx01g */ > + .id = SNOR_ID(0x9d, 0x5b, 0x1b), > + .sector_size = SZ_128K, > + .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | > + SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6, [Severity: High] Does enabling locking support without a Flag Status Register (FSR) clearing mechanism cause spurious -EIO errors? Because the driver enables SPI_NOR_HAS_LOCK without adding a custom late_init or ready hook to clear the FSR (unlike the Micron implementations), the Write Enable Latch (WEL) bit can remain stuck at 1 in the hardware register. When spi_nor_write_sr1_and_sr2_and_check() reads back the status register to verify the lock bits, it reads WEL=1 while the intended buffer has WEL=0. This strict verification fails and returns -EIO, masking actual hardware status errors. For reference, the strict check in spi_nor_write_sr1_and_sr2_and_check() looks like this: if (sr[0] != tmp[0] || sr[1] != tmp[1]) return -EIO; -- Sashiko AI review · https://sashiko.dev/#/patchset/20260914-mtd-spi-nor-new-issi-chip-v2-0-3cd4d7e434b2@analog.com?part=2 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-16 8:44 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-14 13:42 [PATCH v2 0/2] mtd: spi-nor: issi: add support for the IS25WX01G octal flash Nuno Sá 2026-09-14 13:42 ` [PATCH v2 1/2] mtd: spi-nor: sfdp: get the 1-1-8 and 1-8-8 page programs from 4BAIT Nuno Sá 2026-09-14 13:42 ` [PATCH v2 2/2] mtd: spi-nor: issi: Add support for is25wx01g Nuno Sá 2026-09-14 14:04 ` Michael Walle 2026-09-14 15:31 ` Nuno Sá 2026-09-16 7:14 ` Michael Walle 2026-09-16 8:44 ` Nuno Sá 2026-09-14 14:18 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®