[PATCH 2/5] mtd: spi-nor: spansion: Rework octal_dtr_enable()

tkuw584924 at gmail.com tkuw584924 at gmail.com
Mon Jun 12 03:04:06 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. As preparation for MCP support, this patch
replaces cypress_nor_octal_dtr_en/dis() with cypress_nor_setup_memlat()
and cypress_nor_setup_opiddr(). And the ID check part is moved to
cypress_nor_octal_dtr_enable().

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

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 7804be3a9f2a..0daa3a357ae8 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_octal_dtr_en(struct spi_nor *nor)
+static int cypress_nor_setup_memlat(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
@@ -178,67 +178,37 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
 		CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
 					  SPINOR_REG_CYPRESS_CFR2V, 1, buf);
 
-	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
-	if (ret)
-		return ret;
-
-	nor->read_dummy = 24;
-
-	/* Set the octal and DTR enable bits. */
-	buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN;
-	op = (struct spi_mem_op)
-		CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
-					  SPINOR_REG_CYPRESS_CFR5V, 1, buf);
-
-	ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
-	if (ret)
-		return ret;
-
-	/* Read flash ID to make sure the switch was successful. */
-	ret = spi_nor_read_id(nor, nor->addr_nbytes, 3, buf,
-			      SNOR_PROTO_8_8_8_DTR);
-	if (ret) {
-		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
-		return ret;
-	}
-
-	if (memcmp(buf, nor->info->id, nor->info->id_len))
-		return -EINVAL;
-
-	return 0;
+	return spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
 }
 
-static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
+static int cypress_nor_setup_opiddr(struct spi_nor *nor, bool enable)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
-	int ret;
-
-	/*
-	 * The register is 1-byte wide, but 1-byte transactions are not allowed
-	 * in 8D-8D-8D mode. Since there is no register at the next location,
-	 * just initialize the value to 0 and let the transaction go on.
-	 */
-	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, buf);
-	ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
-	if (ret)
-		return ret;
 
-	/* Read flash ID to make sure the switch was successful. */
-	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
-	if (ret) {
-		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
-		return ret;
+	if (enable) {
+		/* Set the octal and DTR enable bits. */
+		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);
+	} else {
+		/*
+		 * The register is 1-byte wide, but 1-byte transactions are not
+		 * allowed in 8D-8D-8D mode. Since there is no register at the
+		 * next location, just initialize the value to 0 and let the
+		 * transaction go on.
+		 */
+		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,
+						  buf);
 	}
 
-	if (memcmp(buf, nor->info->id, nor->info->id_len))
-		return -EINVAL;
-
-	return 0;
+	return spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
 }
 
 static int cypress_nor_quad_enable_volatile_reg(struct spi_nor *nor, u64 addr)
@@ -642,8 +612,44 @@ static struct spi_nor_fixups s25hx_t_fixups = {
  */
 static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 {
-	return enable ? cypress_nor_octal_dtr_en(nor) :
-			cypress_nor_octal_dtr_dis(nor);
+	int ret;
+	u8 naddr, ndummy;
+	enum spi_nor_protocol proto;
+
+	if (enable) {
+		ret = cypress_nor_setup_memlat(nor);
+		if (ret)
+			return ret;
+
+		nor->read_dummy = 24;
+	}
+
+	ret = cypress_nor_setup_opiddr(nor, enable);
+	if (ret)
+		return ret;
+
+	/* Read flash ID to make sure the switch was successful. */
+	if (enable) {
+		naddr = nor->addr_nbytes;
+		ndummy = 3;
+		proto = SNOR_PROTO_8_8_8_DTR;
+	} else {
+		naddr = 0;
+		ndummy = 0;
+		proto = SNOR_PROTO_1_1_1;
+	}
+
+	ret = spi_nor_read_id(nor, naddr, ndummy, nor->bouncebuf, proto);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after %s 8D-8D-8D mode\n",
+			ret, enable ? "enabling" : "disabling");
+		return ret;
+	}
+
+	if (memcmp(nor->bouncebuf, nor->info->id, nor->info->id_len))
+		return -EINVAL;
+
+	return 0;
 }
 
 static int s28hx_t_post_sfdp_fixup(struct spi_nor *nor)
-- 
2.34.1




More information about the linux-mtd mailing list