diff mbox series

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

Message ID cac44f4d9ed06e250c2fa8aa900d8de3de4c4337.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. 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@infineon.com>
---
 drivers/mtd/spi-nor/spansion.c | 71 +++++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 18 deletions(-)

Comments

Tudor Ambarus June 12, 2023, 12:13 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. We can access to configuration registers in each
> die by using params->n_dice and params->vreg_offset[] populated from SFDP.

I wonder if we really need to differentiate between the MCP and single
chip package flashes. Do the single chip flashes that are currently
supported in spansion.c and support Octal DDR define the params->n_dice
and params->vreg_offset[]? Do they have the necessary SFDP tables?
Michael Walle July 17, 2023, 10:49 p.m. UTC | #2
Hi Takahiro, Hi Miquel,

> 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.

I'm looking into cleaning up the flash db and come across the n_banks
and n_dice parameter. Which sounds like they seem to be similar, maybe
identical? Unfortunately, there is no public datasheet for the macronix
flash.. IIRC there is one for the Semperflashes but I'm not sure if 
there
is one for the MCP parts.
Could we somehow clarify if these are the same properties? I've looked 
at
the SFDP tables of the macronix flash and they don't have the SCCR map 
for
multi chip devices :/

-michael
Takahiro Kuwano July 18, 2023, 7:06 a.m. UTC | #3
Hi Michael,

On 7/18/2023 7:49 AM, Michael Walle wrote:
> Hi Takahiro, Hi Miquel,
> 
>> 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.
> 
> I'm looking into cleaning up the flash db and come across the n_banks
> and n_dice parameter. Which sounds like they seem to be similar, maybe
> identical? Unfortunately, there is no public datasheet for the macronix
> flash.. IIRC there is one for the Semperflashes but I'm not sure if there
> is one for the MCP parts.
> Could we somehow clarify if these are the same properties? I've looked at
> the SFDP tables of the macronix flash and they don't have the SCCR map for
> multi chip devices :/
> 
> -michael

The n_banks and n_dice are different properties. One die can contain multiple
banks. Infineon does not have multi-bank parts that support RWW. The SEMPER
MCP parts do not support RWW on different die.

Thanks,
Takahiro
Michael Walle July 18, 2023, 7:30 a.m. UTC | #4
Hi,

>>> 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.
>> 
>> I'm looking into cleaning up the flash db and come across the n_banks
>> and n_dice parameter. Which sounds like they seem to be similar, maybe
>> identical? Unfortunately, there is no public datasheet for the 
>> macronix
>> flash.. IIRC there is one for the Semperflashes but I'm not sure if 
>> there
>> is one for the MCP parts.
>> Could we somehow clarify if these are the same properties? I've looked 
>> at
>> the SFDP tables of the macronix flash and they don't have the SCCR map 
>> for
>> multi chip devices :/
>> 
>> -michael
> 
> The n_banks and n_dice are different properties. One die can contain 
> multiple
> banks. Infineon does not have multi-bank parts that support RWW. The 
> SEMPER
> MCP parts do not support RWW on different die.

Ok. thanks for the quick answer!

-michael
diff mbox series

Patch

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;