diff mbox series

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

Message ID 381f7f66c68136a2de1d768b44fb6bcf9eebbebe.1686557139.git.Takahiro.Kuwano@infineon.com
State Changes Requested
Delegated to: Ambarus Tudor
Headers show
Series mtd: spi-nor: spansion: Add support for Infineon S28HS02GT | expand

Commit Message

Takahiro Kuwano June 12, 2023, 10:04 a.m. UTC
From: Takahiro Kuwano <Takahiro.Kuwano@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@infineon.com>
---
 drivers/mtd/spi-nor/spansion.c | 118 +++++++++++++++++----------------
 1 file changed, 62 insertions(+), 56 deletions(-)

Comments

Tudor Ambarus June 12, 2023, 12:05 p.m. UTC | #1
On 6/12/23 11:04, tkuw584924@gmail.com wrote:
> From: Takahiro Kuwano <Takahiro.Kuwano@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@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)

cypress_nor_set_memlat?

Be kind and introduce a description for the method so that we don't
cross check the datasheet each time. I see that for memlat we use a
hardcoded value, whereas it should have been dynamically determined
based on the flash freq. Something to improve in the future if you care.


>  {
>  	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)

what does opiddr stand for? Let's rename it to something humans can
understand.

>  {
>  	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)

what a terrible name

>  {
> -	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) {

so we have cypress_nor_octal_dtr_enable and now we check for enable,
yuck. I know it comes from the SPI NOR core, we shall update the core, I
wouldn't continue like this.

> +		ret = cypress_nor_setup_memlat(nor);
> +		if (ret)
> +			return ret;
> +
> +		nor->read_dummy = 24;

shouldn't this be set in cypress_nor_set_memlat?
> +	}
> +
> +	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;
> +	}

I don't like all the if conditions in the octal_dtr_enable methods, I
find the method hard to read and I feel we are butchering the code just
to make it work.
> +
> +	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)
diff mbox series

Patch

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)