[PATCH 19/19] mtd: spi-nor: Enable DDR mode functionality with Macronix flash

Tejas Bhumkar tejas.arvind.bhumkar at amd.com
Mon Mar 11 18:22:49 CET 2024


Added SFDP fixups for Macronix octal flash, with the requirement
of the Invert Dual-byte opcode in Octal DDR mode.

Reference: linux-xlnx at 08cf794

Signed-off-by: Tejas Bhumkar <tejas.arvind.bhumkar at amd.com>
---
 drivers/mtd/spi/spi-nor-core.c | 49 +++++++++++++++++++++++++++++-----
 drivers/mtd/spi/spi-nor-ids.c  |  2 ++
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 6b396ce681..9c2d70585a 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -4089,18 +4089,18 @@ static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
 	int ret;
-	u8 buf;
+	u8 *buf = nor->cmd_buf;
 
 	ret = write_enable(nor);
 	if (ret)
 		return ret;
 
-	buf = SPINOR_REG_MXIC_DC_20;
+	*buf = SPINOR_REG_MXIC_DC_20;
 	op = (struct spi_mem_op)
 		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1),
 			   SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_DC, 1),
 			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+			   SPI_MEM_OP_DATA_OUT(1, buf, 1));
 
 	ret = spi_mem_exec_op(nor->spi, &op);
 	if (ret)
@@ -4115,18 +4115,33 @@ static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor)
 	if (ret)
 		return ret;
 
-	buf = SPINOR_REG_MXIC_OPI_DTR_EN;
+	nor->spi->flags |= SPI_XFER_SET_DDR;
+	*buf = SPINOR_REG_MXIC_OPI_DTR_EN;
 	op = (struct spi_mem_op)
 		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1),
 			   SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_MODE, 1),
 			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+			   SPI_MEM_OP_DATA_OUT(1, buf, 1));
 
 	ret = spi_mem_exec_op(nor->spi, &op);
 	if (ret) {
 		dev_err(nor->dev, "Failed to enable octal DTR mode\n");
 		return ret;
 	}
+
+	/* 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_ADDR(4, 0, 1),
+			   SPI_MEM_OP_DUMMY(4, 1),
+			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2), buf, 1));
+
+	spi_nor_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+	ret = spi_mem_exec_op(nor->spi, &op);
+	if (ret)
+		return ret;
+
 	nor->reg_proto = SNOR_PROTO_8_8_8_DTR;
 
 	return 0;
@@ -4134,6 +4149,20 @@ static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor)
 
 static void macronix_octal_default_init(struct spi_nor *nor)
 {
+	u8 id_byte1, id_byte2;
+	/*
+	 * Macronix Read Id bytes are always output in STR mode. Since tuning
+	 * is based on Read Id command, adjust the Read Id bytes that will
+	 * match the Read Id output in DTR mode.
+	 */
+	id_byte1 = nor->spi->device_id[1];
+	id_byte2 = nor->spi->device_id[2];
+	nor->spi->device_id[1] = nor->spi->device_id[0];
+	nor->spi->device_id[2] = id_byte1;
+	nor->spi->device_id[3] = id_byte1;
+	nor->spi->device_id[4] = id_byte2;
+	nor->spi->device_id[5] = id_byte2;
+
 	nor->octal_dtr_enable = spi_nor_macronix_octal_dtr_enable;
 }
 
@@ -4144,8 +4173,16 @@ static void macronix_octal_post_sfdp_fixup(struct spi_nor *nor,
 	 * Adding SNOR_HWCAPS_PP_8_8_8_DTR in hwcaps.mask when
 	 * SPI_NOR_OCTAL_DTR_READ flag exists.
 	 */
-	if (params->hwcaps.mask & SNOR_HWCAPS_READ_8_8_8_DTR)
+	if (params->hwcaps.mask & SNOR_HWCAPS_READ_8_8_8_DTR) {
 		params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8_DTR],
+					  0, 20, SPINOR_OP_MXIC_DTR_RD,
+					  SNOR_PROTO_8_8_8_DTR);
+		nor->cmd_ext_type = SPI_NOR_EXT_INVERT;
+		nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
+		params->rdsr_dummy = 8;
+		params->rdsr_addr_nbytes = 0;
+	}
 }
 
 static struct spi_nor_fixups macronix_octal_fixups = {
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 34fba49592..cd3fcda70c 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -275,6 +275,8 @@ const struct flash_info spi_nor_ids[] = {
 	{ INFO("mx66l2g45g",  0xc2201c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("mx25l1633e", 0xc22415, 0, 64 * 1024,   32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) },
 	{ INFO("mx25r6435f", 0xc22817, 0, 64 * 1024,   128,  SECT_4K) },
+	{ INFO("mx25um51345g",   0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP) },
+	{ INFO("mx66um2g45g",    0xc2803c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP) },
 	{ INFO("mx66uw2g345gx0", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("mx66lm1g45g",    0xc2853b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("mx25lm51245g",   0xc2853a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
-- 
2.27.0



More information about the U-Boot mailing list