[PATCH 3/5] mtd: spi-nor: spansion: Add MCP support in octal_dtr_enable()

tkuw584924 at gmail.com tkuw584924 at gmail.com
Mon Jun 12 03:04:07 PDT 2023


From: Takahiro Kuwano <Takahiro.Kuwano at infineon.com>

S28HS02GT is multi-chip package (MCP) device that requires Octal DTR
configuraion for each die. We can access to configuration registers in each
die by using params->n_dice and params->vreg_offset[] populated from SFDP.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano at infineon.com>
---
 drivers/mtd/spi-nor/spansion.c | 71 +++++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 0daa3a357ae8..eda3731c17be 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -156,7 +156,7 @@ static int cypress_nor_sr_ready_and_clear(struct spi_nor *nor)
 	return 1;
 }
 
-static int cypress_nor_setup_memlat(struct spi_nor *nor)
+static int cypress_nor_setup_memlat(struct spi_nor *nor, u64 addr)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
@@ -164,8 +164,7 @@ static int cypress_nor_setup_memlat(struct spi_nor *nor)
 	u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
 
 	op = (struct spi_mem_op)
-		CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes,
-					  SPINOR_REG_CYPRESS_CFR2V, 0, buf);
+		CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, addr, 0, buf);
 
 	ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
 	if (ret)
@@ -175,13 +174,12 @@ static int cypress_nor_setup_memlat(struct spi_nor *nor)
 	*buf &= ~SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK;
 	*buf |= SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24;
 	op = (struct spi_mem_op)
-		CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
-					  SPINOR_REG_CYPRESS_CFR2V, 1, buf);
+		CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes, addr, 1, buf);
 
 	return spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
 }
 
-static int cypress_nor_setup_opiddr(struct spi_nor *nor, bool enable)
+static int cypress_nor_setup_opiddr(struct spi_nor *nor, u64 addr, bool enable)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
@@ -191,8 +189,7 @@ static int cypress_nor_setup_opiddr(struct spi_nor *nor, bool enable)
 		buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN;
 		op = (struct spi_mem_op)
 			CYPRESS_NOR_WR_ANY_REG_OP(nor->params->addr_mode_nbytes,
-						  SPINOR_REG_CYPRESS_CFR5V, 1,
-						  buf);
+						  addr, 1, buf);
 	} else {
 		/*
 		 * The register is 1-byte wide, but 1-byte transactions are not
@@ -203,8 +200,7 @@ static int cypress_nor_setup_opiddr(struct spi_nor *nor, bool enable)
 		buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_DS;
 		buf[1] = 0;
 		op = (struct spi_mem_op)
-			CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes,
-						  SPINOR_REG_CYPRESS_CFR5V, 2,
+			CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes, addr, 2,
 						  buf);
 	}
 
@@ -600,6 +596,49 @@ static struct spi_nor_fixups s25hx_t_fixups = {
 	.late_init = s25hx_t_late_init,
 };
 
+static int cypress_nor_octal_dtr_enable_single_chip(struct spi_nor *nor,
+						    bool enable)
+{
+	int ret;
+
+	if (enable) {
+		ret = cypress_nor_setup_memlat(nor, SPINOR_REG_CYPRESS_CFR2V);
+		if (ret)
+			return ret;
+
+		nor->read_dummy = 24;
+	}
+
+	return cypress_nor_setup_opiddr(nor, SPINOR_REG_CYPRESS_CFR5V, enable);
+}
+
+static int cypress_nor_octal_dtr_enable_mcp(struct spi_nor *nor, bool enable)
+{
+	struct spi_nor_flash_parameter *params = nor->params;
+	u64 addr;
+	u8 i;
+	int ret;
+
+	if (enable) {
+		for (i = 0; i < params->n_dice; i++) {
+			addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR2;
+			ret = cypress_nor_setup_memlat(nor, addr);
+			if (ret)
+				return ret;
+		}
+		nor->read_dummy = 24;
+	}
+
+	for (i = 0; i < params->n_dice; i++) {
+		addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR5;
+		ret = cypress_nor_setup_opiddr(nor, addr, enable);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 /**
  * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
  * @nor:		pointer to a 'struct spi_nor'
@@ -616,15 +655,11 @@ static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 	u8 naddr, ndummy;
 	enum spi_nor_protocol proto;
 
-	if (enable) {
-		ret = cypress_nor_setup_memlat(nor);
-		if (ret)
-			return ret;
-
-		nor->read_dummy = 24;
-	}
+	if (nor->params->n_dice)
+		ret = cypress_nor_octal_dtr_enable_mcp(nor, enable);
+	else
+		ret = cypress_nor_octal_dtr_enable_single_chip(nor, enable);
 
-	ret = cypress_nor_setup_opiddr(nor, enable);
 	if (ret)
 		return ret;
 
-- 
2.34.1




More information about the linux-mtd mailing list