[PATCH] [v5] mtd: spi-nor: gigadevice: Add support for GD25LQ255E & GD25LQ256H

Weimin Wu wuweimin at huaqin.corp-partner.google.com
Mon Jul 27 23:49:54 PDT 2026


Add support for the GD25LQ255E & GD25LQ256H (JEDEC ID c8 60 19),
a 256Mbit (32MB) SPI NOR flash chip which supports SFDP.

GD25LQ256H shares the same JEDEC ID (c8 60 19) with GD25LQ255E.
Since GD25LQ256H supports DTR (Double Transfer Rate) mode while
GD25LQ255E does not, use the post_bfpt hook to detect this capability
via SFDP and dynamically redirect the info pointer. This allows both
chips to be supported correctly without breaking write protection on
GD25LQ255E.

Without this patch, The WP status cannot be obtained using flashrom:
device:/ # flashrom --wp-status
...
linux_mtd_wp_read_cfg:
ioctl: Operation not supported on transport endpoint
Failed to get WP status: failed to read the current WP configuration

and with this patch:
device:/ # flashrom --wp-status
...
Protection range: start=0x00000000 length=0x00000000 (none)
Protection mode: disabled
SUCCESS

Link: https://download.gigadevice.com/Datasheet/DS-00562-GD25LQ255E-Rev1.2.pdf
Link: https://download.gigadevice.com/Datasheet/DS-01085-GD25LQ256H-Rev1.3.pdf

Signed-off-by: Weimin Wu <wuweimin at huaqin.corp-partner.google.com>

---
Changes in v5:
- Add a feature to distinguish between GD25LQ256H and GD25LQ255E by detecting whether DTR is supported.
- Link to v4: https://patchwork.ozlabs.org/project/linux-mtd/patch/20260527032823.771616-1-wuweimin@huaqin.corp-partner.google.com/
- Link to v3: https://patchwork.ozlabs.org/project/linux-mtd/patch/20260418084253.792395-1-wuweimin@huaqin.corp-partner.google.com/
- Link to v2: https://patchwork.ozlabs.org/project/linux-mtd/patch/20260313133806.2390946-1-wuweimin@huaqin.corp-partner.google.com/
- Link to v1: https://patchwork.ozlabs.org/project/linux-mtd/patch/20260213144133.1778932-1-wuweimin@huaqin.corp-partner.google.com/

Refer to the following documents:
https://docs.kernel.org/driver-api/mtd/spi-nor.html#minimum-testing-requirements

For GD25LQ256H
1. Specify the controller that you used to test the flash and specify the frequency at which the flash was operated:

This flash memory has been successfully tested at 100Mhz frequency on a Chromebook device running the Intel Patherlake platform, which is currently under development.

2. Dump the sysfs entries and print the md5/sha1/sha256 SFDP checksum:
root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/partname
gd25lq256h

root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id
c86019

root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer
gigadevice

root:/ # xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
53464450070102ff00070114300000ffc8000103900000ff84010102c000
00ffffffffffffffffffffffffffffffffffe520fbffffffff0f44eb086b
083b80bbfeffffffffff00ffffff42eb0c200f5210d800ffd4299dfe84d2
14c7ec6316337a757a7507b3d55c190614ff885018010000000000008800
00000000f6f5ffffffffffffffffffffffffffffffffffff002050169ff9
7764fc8bffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffff8e00fe215cdcff

root:/ # sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
09f61fe623df200d86b4ab47c48e3a13718fadbb450fcd430b3cdc49a902b1f6  /sys/bus/spi/devices/spi0.0/spi-nor/sfdp

3. Dump debugfs data:
root:/ # cat /sys/kernel/debug/spi-nor/spi0.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-2S
  opcode	0x3c
  mode cycles	0
  dummy cycles	8
 1S-2S-2S
  opcode	0xbc
  mode cycles	4
  dummy cycles	0
 1S-1S-4S
  opcode	0x6c
  mode cycles	0
  dummy cycles	8
 1S-4S-4S
  opcode	0xec
  mode cycles	2
  dummy cycles	4
 4S-4S-4S
  opcode	0xec
  mode cycles	2
  dummy cycles	2

Supported page program modes by the flash
 1S-1S-1S
  opcode	0x12
 1S-1S-4S
  opcode	0x34

root:/ # cat /sys/kernel/debug/spi-nor/spi0.0/params
name		(null)
id		c8 60 19 c8 60 19
size		32.0 MiB
write size	1
page size	256
address nbytes	4
flags		HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_16BIT_SR | NO_READ_CR | HAS_SR_TB_BIT6 | HAS_4BIT_BP | SOFT_RESET

opcodes
 read		0x0c
  dummy cycles	8
 erase		0xdc
 program	0x12
 8D extension	repeat

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

erase commands
 21 (4.00 KiB) [1]
 5c (32.0 KiB) [2]
 dc (64.0 KiB) [3]
 c7 (32.0 MiB)

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

4. Use mtd-utils and verify that erase, read and page program operations work fine:
Because Chromebooks lack the necessary mtd-utils directives, the corresponding data cannot be provided.

For GD25LQ255E
1. Specify the controller that you used to test the flash and specify the frequency at which the flash was operated:

This flash memory has been successfully tested at 100Mhz frequency on a Chromebook device running the Intel Patherlake platform, which is currently under development.

2. Dump the sysfs entries and print the md5/sha1/sha256 SFDP checksum:
root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/partname
gd25lq255e

root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id
c86019

root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer
gigadevice

root:/ # xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
53464450070102ff00070114300000ffc8000103900000ff84010102c000
00ffffffffffffffffffffffffffffffffffe520fbffffffff0f44eb086b
083b80bbfeffffffffff00ffffff42eb0c200f5210d800ffd4299dfe84d2
14c7ec6316337a757a7507b3d55c190614ff885018010000000000008800
00000000f6f5ffffffffffffffffffffffffffffffffffff002050169ff9
7764fc8bffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffff8e00fe215cdcff

root:/ # sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
09f61fe623df200d86b4ab47c48e3a13718fadbb450fcd430b3cdc49a902b1f6  /sys/bus/spi/devices/spi0.0/spi-nor/sfdp

3. Dump debugfs data:
root:/ # cat /sys/kernel/debug/spi-nor/spi0.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-2S
  opcode	0x3c
  mode cycles	0
  dummy cycles	8
 1S-2S-2S
  opcode	0xbc
  mode cycles	4
  dummy cycles	0
 1S-1S-4S
  opcode	0x6c
  mode cycles	0
  dummy cycles	8
 1S-4S-4S
  opcode	0xec
  mode cycles	2
  dummy cycles	4
 4S-4S-4S
  opcode	0xec
  mode cycles	2
  dummy cycles	2

Supported page program modes by the flash
 1S-1S-1S
  opcode	0x12
 1S-1S-4S
  opcode	0x34

root:/ # cat /sys/kernel/debug/spi-nor/spi0.0/params
name		(null)
id		c8 60 19 c8 60 19
size		32.0 MiB
write size	1
page size	256
address nbytes	4
flags		HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_16BIT_SR | NO_READ_CR | HAS_SR_TB_BIT6 | HAS_4BIT_BP | SOFT_RESET

opcodes
 read		0x0c
  dummy cycles	8
 erase		0xdc
 program	0x12
 8D extension	repeat

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

erase commands
 21 (4.00 KiB) [1]
 5c (32.0 KiB) [2]
 dc (64.0 KiB) [3]
 c7 (32.0 MiB)

sector map
 region (in hex)   | erase mask | overlaid
 ------------------+------------+----------
 00000000-01ffffff |     [   3] | no
root:/ # cat /sys/bus/spi/devices/spi0.0/
driver/                          mtd/                             statistics/                      uevent
driver_override                  power/                           subsystem/
modalias                         spi-nor/                         supplier:regulator:regulator.0/
root:/ # cat /sys/bus/spi/devices/spi0.0/s
spi-nor/                         statistics/                      subsystem/                       supplier:regulator:regulator.0/
root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/
jedec_id      manufacturer  sfdp
root:/ # cat /sys/bus/spi/devices/spi0.0/spi-nor/

4. Use mtd-utils and verify that erase, read and page program operations work fine:
Because Chromebooks lack the necessary mtd-utils directives, the corresponding data cannot be provided.
---
---
---
 drivers/mtd/spi-nor/gigadevice.c | 33 ++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
index ef1edd0add70..9fc97feb2849 100644
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -33,6 +33,34 @@ static const struct spi_nor_fixups gd25q256_fixups = {
 	.post_bfpt = gd25q256_post_bfpt,
 };
 
+static const struct flash_info gd25lq256h_info = {
+	.name = "gd25lq256h",
+	.id = SNOR_ID(0xc8, 0x60, 0x19),
+	.flags = SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6,
+};
+
+static int
+gd25lq255e_post_bfpt(struct spi_nor *nor,
+		     const struct sfdp_parameter_header *bfpt_header,
+		     const struct sfdp_bfpt *bfpt)
+{
+	/*
+	 * GD25LQ255E and GD25LQ256H share the same JEDEC ID (c8 60 19).
+	 * We can differentiate them by checking if the chip supports DTR
+	 * (Double Transfer Rate) mode, which is only supported by GD25LQ256H.
+	 *
+	 * SFDP parsing sets the DTR hwcaps if supported.
+	 */
+	if (bfpt->dwords[SFDP_DWORD(1)] & BFPT_DWORD1_DTR)
+		nor->info = &gd25lq256h_info;
+
+	return 0;
+}
+
+static const struct spi_nor_fixups gd25lq255e_fixups = {
+	.post_bfpt = gd25lq255e_post_bfpt,
+};
+
 static const struct flash_info gigadevice_nor_parts[] = {
 	{
 		.id = SNOR_ID(0xc8, 0x40, 0x15),
@@ -82,6 +110,11 @@ static const struct flash_info gigadevice_nor_parts[] = {
 		.size = SZ_16M,
 		.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
 		.no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+	}, {
+		.id = SNOR_ID(0xc8, 0x60, 0x19),
+		.name = "gd25lq255e",
+		.flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
+		.fixups = &gd25lq255e_fixups,
 	},
 };
 
-- 
2.43.0




More information about the linux-mtd mailing list