[PATCH] Add JEDEC ID table entries for additional ISSI SPI-NOR devices. Additionally added several structs to support ISSI octal flash functionality. (Octal SPI 2026 revised)
From: Jeffrey Yu
Date: Mon Jun 22 2026 - 18:13:46 EST
Add JEDEC ID table entries for additional ISSI SPI-NOR
devices. Additionally added several structs to support ISSI octal flash
functionality. (Octal SPI 2026 revised)
These parts previously not yet supported.
With these entries, Linux software can match the device by JEDEC ID
and use the existing ISSI SPI-NOR device handling.
Newly added devices include:
- IS25WX256 (JEDEC 0x9d5b19)
https://www.issi.com/WW/pdf/25LX-WX256-128.pdf
- IS25LX256 (JEDEC 0x9d5a19)
https://www.issi.com/WW/pdf/25LX-WX256-128.pdf
- IS25WX512M (JEDEC 0x9d5b1a)
https://www.issi.com/WW/pdf/25LX-WX512M.pdf
- IS25LX512M (JEDEC 0x9d5a1a)
https://www.issi.com/WW/pdf/25LX-WX512M.pdf
- IS25WX01G (JEDEC 0x9d5b1b)
https://www.issi.com/WW/pdf/25LX-WX01G.pdf
- IS25LX01G (JEDEC 0x9d5a1b)
https://www.issi.com/WW/pdf/25LX-WX01G.pdf
Signed-off-by: Jeffrey Y <jeyu@xxxxxxxx>
---
drivers/mtd/spi-nor/issi.c | 242 +++++++++++++++++++++++++++++++++++++
1 file changed, 242 insertions(+)
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index 18d9a00aa22e..61597e9e962c 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -8,6 +8,182 @@
#include "core.h"
+
+static int spi_nor_issi_phy_enable(struct spi_nor *nor)
+{
+ struct spi_mem_op op;
+ u8 *buf = nor->bouncebuf;
+ int ret;
+
+ ret = spi_nor_write_enable(nor);
+ if (ret)
+ goto ret;
+
+ buf[0] = SPINOR_IS_EXSPI;
+
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_IS_WR_ANY_REG, 1),
+ SPI_MEM_OP_ADDR(4, SPINOR_REG_IS_CFR0V, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, buf, 1));
+
+ spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_1_1_1);
+
+ ret = spi_mem_exec_op(nor->spimem, &op);
+ if (ret)
+ goto ret;
+
+ nor->spimem->spi->controller->flags |= SPI_CONTROLLER_SDR_PHY;
+ /* Read flash ID to make sure the switch was successful. */
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
+ SPI_MEM_OP_NO_ADDR,
+ SPI_MEM_OP_DUMMY(0, 1),
+ SPI_MEM_OP_DATA_IN(nor->info->id->len, buf, 1));
+
+ spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_1_1_1);
+
+ ret = spi_mem_exec_op(nor->spimem, &op);
+ if (ret)
+ goto ret;
+
+ if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
+ goto ret;
+
+ return 0;
+ret:
+ nor->spimem->spi->controller->flags &= ~SPI_CONTROLLER_SDR_PHY;
+ return 0;
+}
+
+static int spi_nor_issi_octal_dtr_enable(struct spi_nor *nor, bool enable)
+{
+ struct spi_mem_op op;
+ u8 *buf = nor->bouncebuf;
+ int ret;
+
+ if (enable) {
+ /* Use 20 dummy cycles for memory array reads. */
+ ret = spi_nor_write_enable(nor);
+ if (ret)
+ return ret;
+
+ *buf = 20;
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_IS_WR_ANY_REG, 1),
+ SPI_MEM_OP_ADDR(3, SPINOR_REG_IS_CFR1V, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, buf, 1));
+
+ ret = spi_mem_exec_op(nor->spimem, &op);
+ if (ret)
+ return ret;
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ return ret;
+ }
+
+ ret = spi_nor_write_enable(nor);
+ if (ret)
+ return ret;
+
+ if (enable)
+ *buf = SPINOR_IS_OCT_DTR;
+ else
+ *buf = SPINOR_IS_EXSPI;
+
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_IS_WR_ANY_REG, 1),
+ SPI_MEM_OP_ADDR(enable ? 3 : 4,
+ SPINOR_REG_IS_CFR0V, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, buf, 1));
+
+ if (!enable)
+ spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+ ret = spi_mem_exec_op(nor->spimem, &op);
+ if (ret)
+ return ret;
+
+ if ((nor->flags & SNOR_F_HAS_STACKED) && nor->spimem->spi->cs_index_mask == 1)
+ return 0;
+
+ /* Read flash ID to make sure the switch was successful. */
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
+ SPI_MEM_OP_NO_ADDR,
+ SPI_MEM_OP_DUMMY(enable ? 8 : 0, 1),
+ SPI_MEM_OP_DATA_IN(round_up(nor->info->id->len, 2),
+ buf, 1));
+
+ if (enable)
+ spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+ ret = spi_mem_exec_op(nor->spimem, &op);
+ if (ret)
+ return ret;
+
+ if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int is25wx256_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
+{
+ int ret;
+
+ ret = spi_nor_write_enable(nor);
+ if (ret)
+ return ret;
+
+ ret = spi_nor_set_4byte_addr_mode(nor, enable);
+ if (ret)
+ return ret;
+
+ return spi_nor_write_disable(nor);
+}
+
+static void is25wx256_default_init(struct spi_nor *nor)
+{
+ struct spi_nor_flash_parameter *params = spi_nor_get_params(nor, 0);
+
+ params->set_octal_dtr = spi_nor_issi_octal_dtr_enable;
+ params->set_4byte_addr_mode = is25wx256_set_4byte_addr_mode;
+ params->phy_enable = spi_nor_issi_phy_enable;
+}
+
+static int is25wx256_post_sfdp_fixup(struct spi_nor *nor)
+{
+ struct spi_nor_flash_parameter *params = spi_nor_get_params(nor, 0);
+
+ /* Set the Fast Read settings. */
+ params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
+ spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8_8_8_DTR],
+ 0, 20, SPINOR_OP_IS_DTR_RD,
+ SNOR_PROTO_8_8_8_DTR);
+
+ nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+ params->rdsr_dummy = 8;
+ params->rdsr_addr_nbytes = 0;
+
+ /*
+ * The BFPT quad enable field is set to a reserved value so the quad
+ * enable function is ignored by spi_nor_parse_bfpt(). Make sure we
+ * disable it.
+ */
+ params->quad_enable = NULL;
+
+ return 0;
+}
+
+static struct spi_nor_fixups is25wx256_fixups = {
+ .default_init = is25wx256_default_init,
+ .post_sfdp = is25wx256_post_sfdp_fixup,
+};
+
static int
is25lp256_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
@@ -126,6 +302,72 @@ static const struct flash_info issi_nor_parts[] = {
.flags = SPI_NOR_QUAD_PP,
.fixups = &is25lp256_fixups,
.fixup_flags = SPI_NOR_4B_OPCODES,
+ }, {
+ .id = SNOR_ID(0x9d, 0x5b, 0x19),
+ .name = "is25wx256",
+ .size = SZ_256M,
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
+ SPI_NOR_BP3_SR_BIT6,
+ .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ |
+ SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
+ .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
+ .mfr_flags = USE_FSR,
+ .fixups = &is25wx256_fixups,
+ }, {
+ .id = SNOR_ID(0x9d, 0x5a, 0x19),
+ .name = "is25lx256",
+ .size = SZ_256M,
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
+ SPI_NOR_BP3_SR_BIT6,
+ .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ |
+ SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
+ .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
+ .mfr_flags = USE_FSR,
+ .fixups = &is25wx256_fixups,
+ }, {
+ .id = SNOR_ID(0x9d, 0x5b, 0x1a),
+ .name = "is25wx512m",
+ .size = SZ_512M,
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
+ SPI_NOR_BP3_SR_BIT6,
+ .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ |
+ SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
+ .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
+ .mfr_flags = USE_FSR,
+ .fixups = &is25wx256_fixups,
+ }, {
+ .id = SNOR_ID(0x9d, 0x5a, 0x1a),
+ .name = "is25lx512m",
+ .size = SZ_512M,
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
+ SPI_NOR_BP3_SR_BIT6,
+ .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ |
+ SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
+ .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
+ .mfr_flags = USE_FSR,
+ .fixups = &is25wx256_fixups,
+ }, {
+ .id = SNOR_ID(0x9d, 0x5b, 0x1b),
+ .name = "is25wx01g",
+ .size = SZ_1G,
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
+ SPI_NOR_BP3_SR_BIT6,
+ .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ |
+ SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
+ .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
+ .mfr_flags = USE_FSR,
+ .fixups = &is25wx256_fixups,
+ }, {
+ .id = SNOR_ID(0x9d, 0x5a, 0x1b),
+ .name = "is25lx01g",
+ .size = SZ_1G,
+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP |
+ SPI_NOR_BP3_SR_BIT6,
+ .no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_READ |
+ SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
+ .fixup_flags = SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE,
+ .mfr_flags = USE_FSR,
+ .fixups = &is25wx256_fixups,
}
};
--
2.43.0