[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