[PATCH] mtd: spi-nor: Add support for MX25L12833F and MX25L12845G

From: Cheng Ming Lin

Date: Thu May 28 2026 - 01:25:25 EST


From: Cheng Ming Lin <chengminglin@xxxxxxxxxxx>

Add support for Macronix MX25L12833F and MX25L12845G.

The SFDP tables for these flashes only declare 1-4-4 Page Program
support in 4-byte address mode. However, since these parts operate
in 3-byte address mode, the standard SFDP parsing does not automatically
enable this capability. To address this, this patch introduces
macronix_4pp3b_late_init_fixups() to explicitly enable the 1-4-4
Page Program.

Signed-off-by: Cheng Ming Lin <chengminglin@xxxxxxxxxxx>
---
- mx25l12833f

zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id
c22018

zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer
macronix

zynq> xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
53464450060102ff00060110300000ffc2000104100100ff84000102c000
00ffffffffffffffffffffffffffffffffffe520f1ffffffff0744eb086b
083b04bbfeffffffffff00ffffff44eb0c200f5210d800ff8241bd0081e5
7bc64403673830b030b0f7bdd55c4abe29ffe1d0ffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffff003600279df9c06485cbffffffffffff

zynq> sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
c7c4287a584fa23f4f5037a90ab0ee6ddc6ff3f0cee89889e54465e86542c85e /sys/bus/spi/devices/spi0.0/spi-nor/sfdp

zynq> cat /sys/kernel/debug/spi-nor/spi0.0/capabilities
Supported read modes by the flash
1S-1S-1S
opcode 0x03
mode cycles 0
dummy cycles 0
1S-1S-2S
opcode 0x3b
mode cycles 0
dummy cycles 8
1S-2S-2S
opcode 0xbb
mode cycles 0
dummy cycles 4
1S-1S-4S
opcode 0x6b
mode cycles 0
dummy cycles 8
1S-4S-4S
opcode 0xeb
mode cycles 2
dummy cycles 4
4S-4S-4S
opcode 0xeb
mode cycles 2
dummy cycles 4

Supported page program modes by the flash
1S-1S-1S
opcode 0x02
1S-4S-4S
opcode 0x38

zynq> cat /sys/kernel/debug/spi-nor/spi0.0/params
name (null)
id c2 20 18 c2 20 18
size 16.0 MiB
write size 1
page size 256
address nbytes 3
flags HAS_LOCK | HAS_4BIT_BP | SOFT_RESET

opcodes
read 0xeb
dummy cycles 6
erase 0xd8
program 0x38
8D extension none

protocols
read 1S-4S-4S
write 1S-4S-4S
register 1S-1S-1S

erase commands
20 (4.00 KiB) [1]
52 (32.0 KiB) [2]
d8 (64.0 KiB) [3]
c7 (16.0 MiB)

sector map
region (in hex) | erase mask | overlaid
------------------+------------+----------
00000000-00ffffff | [ 3] | no

zynq> dd if=/dev/urandom of=/tmp/spi_test bs=1M count=2
2+0 records in
2+0 records out
2097152 bytes (2.0MB) copied, 0.085447 seconds, 23.4MB/s

zynq> mtd_debug erase /dev/mtd0 0 2097152
Erased 2097152 bytes from address 0x00000000 in flash

zynq> mtd_debug read /dev/mtd0 0 2097152 /tmp/spi_read
Copied 2097152 bytes from address 0x00000000 in flash to /tmp/spi_read

zynq> hexdump /tmp/spi_read
0000000 ffff ffff ffff ffff ffff ffff ffff ffff
*
0200000

zynq> sha256sum /tmp/spi_read
4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 /tmp/spi_read

zynq> mtd_debug write /dev/mtd0 0 2097152 /tmp/spi_test
Copied 2097152 bytes from /tmp/spi_test to address 0x00000000 in flash

zynq> mtd_debug read /dev/mtd0 0 2097152 /tmp/spi_read
Copied 2097152 bytes from address 0x00000000 in flash to /tmp/spi_read

zynq> sha256sum /tmp/spi*
847f8009f10c04d3664098f210f5eb5a54cf9e08bd24dbdb1a983c56e3f89256 /tmp/spi_read
847f8009f10c04d3664098f210f5eb5a54cf9e08bd24dbdb1a983c56e3f89256 /tmp/spi_test

zynq> mtd_debug erase /dev/mtd0 0 2097152
Erased 2097152 bytes from address 0x00000000 in flash

zynq> mtd_debug read /dev/mtd0 0 2097152 /tmp/spi_read
Copied 2097152 bytes from address 0x00000000 in flash to /tmp/spi_read

zynq> sha256sum /tmp/spi*
4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 /tmp/spi_read
847f8009f10c04d3664098f210f5eb5a54cf9e08bd24dbdb1a983c56e3f89256 /tmp/spi_test

zynq> mtd_debug info /dev/mtd0
mtd.type = MTD_NORFLASH
mtd.flags = MTD_CAP_NORFLASH
mtd.size = 16777216 (16M)
mtd.erasesize = 65536 (64K)
mtd.writesize = 1
mtd.oobsize = 0
regions = 0

- mx25l12845g

zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id
c22018

zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer
macronix

zynq> xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
53464450060102ff00060110300000ffc2000104100100ff84000102c000
00ffffffffffffffffffffffffffffffffffe520f9ffffffff0744eb086b
083b04bbfeffffffffff00ffffff44eb0c200f5210d800ffd659dd00829f
03cd4403673830b030b0f7bdd55c4abe29fff0d0ffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffff003600279df9c06485cbffffffffffff

zynq> sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
b8b7ec394194bb45effdfa2cd4de23f6a7d05a16ff44a23f86e6d10bc9a83375 /sys/bus/spi/devices/spi0.0/spi-nor/sfdp

zynq> cat /sys/kernel/debug/spi-nor/spi0.0/capabilities
Supported read modes by the flash
1S-1S-1S
opcode 0x03
mode cycles 0
dummy cycles 0
1S-1S-2S
opcode 0x3b
mode cycles 0
dummy cycles 8
1S-2S-2S
opcode 0xbb
mode cycles 0
dummy cycles 4
1S-1S-4S
opcode 0x6b
mode cycles 0
dummy cycles 8
1S-4S-4S
opcode 0xeb
mode cycles 2
dummy cycles 4
4S-4S-4S
opcode 0xeb
mode cycles 2
dummy cycles 4

Supported page program modes by the flash
1S-1S-1S
opcode 0x02
1S-4S-4S
opcode 0x38

zynq> cat /sys/kernel/debug/spi-nor/spi0.0/params
name (null)
id c2 20 18 c2 20 18
size 16.0 MiB
write size 1
page size 256
address nbytes 3
flags HAS_LOCK | HAS_4BIT_BP | SOFT_RESET

opcodes
read 0xeb
dummy cycles 6
erase 0xd8
program 0x38
8D extension none

protocols
read 1S-4S-4S
write 1S-4S-4S
register 1S-1S-1S

erase commands
20 (4.00 KiB) [1]
52 (32.0 KiB) [2]
d8 (64.0 KiB) [3]
c7 (16.0 MiB)

sector map
region (in hex) | erase mask | overlaid
------------------+------------+----------
00000000-00ffffff | [ 3] | no

zynq> dd if=/dev/urandom of=/tmp/spi_test bs=1M count=2
2+0 records in
2+0 records out
2097152 bytes (2.0MB) copied, 0.083618 seconds, 23.9MB/s

zynq> mtd_debug erase /dev/mtd0 0 2097152
Erased 2097152 bytes from address 0x00000000 in flash

zynq> mtd_debug read /dev/mtd0 0 2097152 /tmp/spi_read
Copied 2097152 bytes from address 0x00000000 in flash to /tmp/spi_read

zynq> hexdump /tmp/spi_read
0000000 ffff ffff ffff ffff ffff ffff ffff ffff
*
0200000

zynq> sha256sum /tmp/spi_read
4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 /tmp/spi_read

zynq> mtd_debug write /dev/mtd0 0 2097152 /tmp/spi_test
Copied 2097152 bytes from /tmp/spi_test to address 0x00000000 in flash

zynq> mtd_debug read /dev/mtd0 0 2097152 /tmp/spi_read
Copied 2097152 bytes from address 0x00000000 in flash to /tmp/spi_read

zynq> sha256sum /tmp/spi*
ec344b7d2b0022ee54bf94de71b889e5fd3087a5487dcee789e0a0b056bfc6ae /tmp/spi_read
ec344b7d2b0022ee54bf94de71b889e5fd3087a5487dcee789e0a0b056bfc6ae /tmp/spi_test

zynq> mtd_debug erase /dev/mtd0 0 2097152
Erased 2097152 bytes from address 0x00000000 in flash

zynq> mtd_debug read /dev/mtd0 0 2097152 /tmp/spi_read
Copied 2097152 bytes from address 0x00000000 in flash to /tmp/spi_read

zynq> sha256sum /tmp/spi*
4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 /tmp/spi_read
ec344b7d2b0022ee54bf94de71b889e5fd3087a5487dcee789e0a0b056bfc6ae /tmp/spi_test

zynq> mtd_debug info /dev/mtd0
mtd.type = MTD_NORFLASH
mtd.flags = MTD_CAP_NORFLASH
mtd.size = 16777216 (16M)
mtd.erasesize = 65536 (64K)
mtd.writesize = 1
mtd.oobsize = 0
regions = 0

drivers/mtd/spi-nor/macronix.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index e97f5cbd9..e91808ad1 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -83,6 +83,18 @@ mx25l3255e_late_init_fixups(struct spi_nor *nor)
return 0;
}

+static int
+macronix_4pp3b_late_init_fixups(struct spi_nor *nor)
+{
+ struct spi_nor_flash_parameter *params = nor->params;
+
+ params->hwcaps.mask |= SNOR_HWCAPS_PP_1_4_4;
+ spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_1_4_4],
+ SPINOR_OP_PP_1_4_4, SNOR_PROTO_1_4_4);
+
+ return 0;
+}
+
static const struct spi_nor_fixups mx25l25635_fixups = {
.post_bfpt = mx25l25635_post_bfpt_fixups,
.post_sfdp = macronix_qpp4b_post_sfdp_fixups,
@@ -96,6 +108,10 @@ static const struct spi_nor_fixups mx25l3255e_fixups = {
.late_init = mx25l3255e_late_init_fixups,
};

+static const struct spi_nor_fixups macronix_4pp3b_fixups = {
+ .late_init = macronix_4pp3b_late_init_fixups,
+};
+
static const struct flash_info macronix_nor_parts[] = {
{
.id = SNOR_ID(0xc2, 0x20, 0x10),
@@ -130,9 +146,10 @@ static const struct flash_info macronix_nor_parts[] = {
.size = SZ_8M,
.no_sfdp_flags = SECT_4K,
}, {
- /* MX25L12805D */
+ /* MX25L12805D, MX25L12833F, MX25L12845G */
.id = SNOR_ID(0xc2, 0x20, 0x18),
.flags = SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP,
+ .fixups = &macronix_4pp3b_fixups,
}, {
/* MX25L25635E, MX25L25645G */
.id = SNOR_ID(0xc2, 0x20, 0x19),
--
2.25.1