* [PATCH v2 1/8] mtd: spi-nor: spansion: use CLPEF as an alternative to CLSR
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
@ 2023-07-20 7:09 ` tkuw584924
2023-07-20 7:09 ` [PATCH v2 2/8] mtd: spi-nor: spansion: preserve CFR2V[7] when writing MEMLAT tkuw584924
` (7 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:09 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Infineon S28Hx (SEMPER Octal) and S25FS256T (SEMPER Nano) support Clear
Program and Erase Failure Flags (CLPEF, 82h) instead of CLSR(30h).
Introduce a new mfr_flag together with the infrastructure to allow
manufacturer private data in the core. With this we remove the need
to have if checks in the code at runtime and instead set the correct
opcodes at probe time. Rework spansion_nor_clear_sr() to add a way
to clear status in these devices. S25Hx (SEMPER QSPI) supports CLSR
but it may be disabled by CFR3x[2] while CLPEF is always available.
Therefore, the mfr_flag is also applied to S25Hx for safety.
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
drivers/mtd/spi-nor/atmel.c | 8 +++-
drivers/mtd/spi-nor/core.c | 23 +++++++----
drivers/mtd/spi-nor/core.h | 4 +-
drivers/mtd/spi-nor/issi.c | 4 +-
drivers/mtd/spi-nor/macronix.c | 4 +-
drivers/mtd/spi-nor/micron-st.c | 4 +-
drivers/mtd/spi-nor/spansion.c | 72 ++++++++++++++++++++++++++-------
drivers/mtd/spi-nor/sst.c | 8 +++-
drivers/mtd/spi-nor/winbond.c | 4 +-
drivers/mtd/spi-nor/xilinx.c | 4 +-
10 files changed, 103 insertions(+), 32 deletions(-)
diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c
index 656dd80a0be7..58968c1e7d2f 100644
--- a/drivers/mtd/spi-nor/atmel.c
+++ b/drivers/mtd/spi-nor/atmel.c
@@ -48,9 +48,11 @@ static const struct spi_nor_locking_ops at25fs_nor_locking_ops = {
.is_locked = at25fs_nor_is_locked,
};
-static void at25fs_nor_late_init(struct spi_nor *nor)
+static int at25fs_nor_late_init(struct spi_nor *nor)
{
nor->params->locking_ops = &at25fs_nor_locking_ops;
+
+ return 0;
}
static const struct spi_nor_fixups at25fs_nor_fixups = {
@@ -149,9 +151,11 @@ static const struct spi_nor_locking_ops atmel_nor_global_protection_ops = {
.is_locked = atmel_nor_is_global_protected,
};
-static void atmel_nor_global_protection_late_init(struct spi_nor *nor)
+static int atmel_nor_global_protection_late_init(struct spi_nor *nor)
{
nor->params->locking_ops = &atmel_nor_global_protection_ops;
+
+ return 0;
}
static const struct spi_nor_fixups atmel_nor_global_protection_fixups = {
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 273258f7e77f..614960c7d22c 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2900,16 +2900,23 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor)
* SFDP standard, or where SFDP tables are not defined at all.
* Will replace the spi_nor_manufacturer_init_params() method.
*/
-static void spi_nor_late_init_params(struct spi_nor *nor)
+static int spi_nor_late_init_params(struct spi_nor *nor)
{
struct spi_nor_flash_parameter *params = nor->params;
+ int ret;
if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->late_init)
- nor->manufacturer->fixups->late_init(nor);
+ nor->manufacturer->fixups->late_init) {
+ ret = nor->manufacturer->fixups->late_init(nor);
+ if (ret)
+ return ret;
+ }
- if (nor->info->fixups && nor->info->fixups->late_init)
- nor->info->fixups->late_init(nor);
+ if (nor->info->fixups && nor->info->fixups->late_init) {
+ ret = nor->info->fixups->late_init(nor);
+ if (ret)
+ return ret;
+ }
/* Default method kept for backward compatibility. */
if (!params->set_4byte_addr_mode)
@@ -2927,6 +2934,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
if (nor->info->n_banks > 1)
params->bank_size = div64_u64(params->size, nor->info->n_banks);
+
+ return 0;
}
/**
@@ -3085,9 +3094,7 @@ static int spi_nor_init_params(struct spi_nor *nor)
spi_nor_init_params_deprecated(nor);
}
- spi_nor_late_init_params(nor);
-
- return 0;
+ return spi_nor_late_init_params(nor);
}
/** spi_nor_set_octal_dtr() - enable or disable Octal DTR I/O.
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index f2fc2cf78e55..9217379b9cfe 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -378,6 +378,7 @@ struct spi_nor_otp {
* than reading the status register to indicate they
* are ready for a new command
* @locking_ops: SPI NOR locking methods.
+ * @priv: flash's private data.
*/
struct spi_nor_flash_parameter {
u64 bank_size;
@@ -406,6 +407,7 @@ struct spi_nor_flash_parameter {
int (*ready)(struct spi_nor *nor);
const struct spi_nor_locking_ops *locking_ops;
+ void *priv;
};
/**
@@ -432,7 +434,7 @@ struct spi_nor_fixups {
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt);
int (*post_sfdp)(struct spi_nor *nor);
- void (*late_init)(struct spi_nor *nor);
+ int (*late_init)(struct spi_nor *nor);
};
/**
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index 400e2b42f45a..accdf7aa2bfd 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -29,7 +29,7 @@ static const struct spi_nor_fixups is25lp256_fixups = {
.post_bfpt = is25lp256_post_bfpt_fixups,
};
-static void pm25lv_nor_late_init(struct spi_nor *nor)
+static int pm25lv_nor_late_init(struct spi_nor *nor)
{
struct spi_nor_erase_map *map = &nor->params->erase_map;
int i;
@@ -38,6 +38,8 @@ static void pm25lv_nor_late_init(struct spi_nor *nor)
for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
if (map->erase_type[i].size == 4096)
map->erase_type[i].opcode = SPINOR_OP_BE_4K_PMC;
+
+ return 0;
}
static const struct spi_nor_fixups pm25lv_nor_fixups = {
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index 04888258e891..eb149e517c1f 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -110,10 +110,12 @@ static void macronix_nor_default_init(struct spi_nor *nor)
nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
}
-static void macronix_nor_late_init(struct spi_nor *nor)
+static int macronix_nor_late_init(struct spi_nor *nor)
{
if (!nor->params->set_4byte_addr_mode)
nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
+
+ return 0;
}
static const struct spi_nor_fixups macronix_nor_fixups = {
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index f79e71d99124..6ad080c52ab5 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -429,7 +429,7 @@ static void micron_st_nor_default_init(struct spi_nor *nor)
nor->params->quad_enable = NULL;
}
-static void micron_st_nor_late_init(struct spi_nor *nor)
+static int micron_st_nor_late_init(struct spi_nor *nor)
{
struct spi_nor_flash_parameter *params = nor->params;
@@ -438,6 +438,8 @@ static void micron_st_nor_late_init(struct spi_nor *nor)
if (!params->set_4byte_addr_mode)
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b;
+
+ return 0;
}
static const struct spi_nor_fixups micron_st_nor_fixups = {
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 6d6466a3436e..f40d4ede4093 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -4,14 +4,17 @@
* Copyright (C) 2014, Freescale Semiconductor, Inc.
*/
+#include <linux/device.h>
#include <linux/mtd/spi-nor.h>
#include "core.h"
/* flash_info mfr_flag. Used to clear sticky prorietary SR bits. */
#define USE_CLSR BIT(0)
+#define USE_CLPEF BIT(1)
#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
+#define SPINOR_OP_CLPEF 0x82 /* Clear program/erase failure flags */
#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */
#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */
#define SPINOR_REG_CYPRESS_VREG 0x00800000
@@ -57,22 +60,32 @@
SPI_MEM_OP_DUMMY(ndummy, 0), \
SPI_MEM_OP_DATA_IN(1, buf, 0))
-#define SPANSION_CLSR_OP \
- SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0), \
+#define SPANSION_OP(opcode) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \
SPI_MEM_OP_NO_ADDR, \
SPI_MEM_OP_NO_DUMMY, \
SPI_MEM_OP_NO_DATA)
+/**
+ * struct spansion_nor_params - Spansion private parameters.
+ * @clsr: Clear Status Register or Clear Program and Erase Failure Flag
+ * opcode.
+ */
+struct spansion_nor_params {
+ u8 clsr;
+};
+
/**
* spansion_nor_clear_sr() - Clear the Status Register.
* @nor: pointer to 'struct spi_nor'.
*/
static void spansion_nor_clear_sr(struct spi_nor *nor)
{
+ const struct spansion_nor_params *priv_params = nor->params->priv;
int ret;
if (nor->spimem) {
- struct spi_mem_op op = SPANSION_CLSR_OP;
+ struct spi_mem_op op = SPANSION_OP(priv_params->clsr);
spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
@@ -528,9 +541,11 @@ static int s25fs256t_post_sfdp_fixup(struct spi_nor *nor)
return 0;
}
-static void s25fs256t_late_init(struct spi_nor *nor)
+static int s25fs256t_late_init(struct spi_nor *nor)
{
cypress_nor_ecc_init(nor);
+
+ return 0;
}
static struct spi_nor_fixups s25fs256t_fixups = {
@@ -586,7 +601,7 @@ static int s25hx_t_post_sfdp_fixup(struct spi_nor *nor)
return cypress_nor_get_page_size(nor);
}
-static void s25hx_t_late_init(struct spi_nor *nor)
+static int s25hx_t_late_init(struct spi_nor *nor)
{
struct spi_nor_flash_parameter *params = nor->params;
@@ -598,6 +613,8 @@ static void s25hx_t_late_init(struct spi_nor *nor)
/* Replace ready() with multi die version */
if (params->n_dice)
params->ready = cypress_nor_sr_ready_and_clear;
+
+ return 0;
}
static struct spi_nor_fixups s25hx_t_fixups = {
@@ -665,10 +682,12 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
return 0;
}
-static void s28hx_t_late_init(struct spi_nor *nor)
+static int s28hx_t_late_init(struct spi_nor *nor)
{
nor->params->set_octal_dtr = cypress_nor_set_octal_dtr;
cypress_nor_ecc_init(nor);
+
+ return 0;
}
static const struct spi_nor_fixups s28hx_t_fixups = {
@@ -792,47 +811,54 @@ static const struct flash_info spansion_nor_parts[] = {
FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
{ "s25fs256t", INFO6(0x342b19, 0x0f0890, 0, 0)
PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s25fs256t_fixups },
{ "s25hl512t", INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256)
PARSE_SFDP
- MFR_FLAGS(USE_CLSR)
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s25hx_t_fixups },
{ "s25hl01gt", INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512)
PARSE_SFDP
- MFR_FLAGS(USE_CLSR)
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s25hx_t_fixups },
{ "s25hl02gt", INFO6(0x342a1c, 0x0f0090, 0, 0)
PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
FLAGS(NO_CHIP_ERASE)
.fixups = &s25hx_t_fixups },
{ "s25hs512t", INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256)
PARSE_SFDP
- MFR_FLAGS(USE_CLSR)
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s25hx_t_fixups },
{ "s25hs01gt", INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512)
PARSE_SFDP
- MFR_FLAGS(USE_CLSR)
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s25hx_t_fixups },
{ "s25hs02gt", INFO6(0x342b1c, 0x0f0090, 0, 0)
PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
FLAGS(NO_CHIP_ERASE)
.fixups = &s25hx_t_fixups },
{ "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1)
FLAGS(SPI_NOR_NO_ERASE) },
{ "s28hl512t", INFO(0x345a1a, 0, 256 * 1024, 256)
PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s28hx_t_fixups,
},
{ "s28hl01gt", INFO(0x345a1b, 0, 256 * 1024, 512)
PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s28hx_t_fixups,
},
{ "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256)
PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s28hx_t_fixups,
},
{ "s28hs01gt", INFO(0x345b1b, 0, 256 * 1024, 512)
PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
.fixups = &s28hx_t_fixups,
},
};
@@ -876,17 +902,35 @@ static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor)
return !(nor->bouncebuf[0] & SR_WIP);
}
-static void spansion_nor_late_init(struct spi_nor *nor)
+static int spansion_nor_late_init(struct spi_nor *nor)
{
- if (nor->params->size > SZ_16M) {
+ struct spi_nor_flash_parameter *params = nor->params;
+ struct spansion_nor_params *priv_params;
+ u8 mfr_flags = nor->info->mfr_flags;
+
+ if (params->size > SZ_16M) {
nor->flags |= SNOR_F_4B_OPCODES;
/* No small sector erase for 4-byte command set */
nor->erase_opcode = SPINOR_OP_SE;
nor->mtd.erasesize = nor->info->sector_size;
}
- if (nor->info->mfr_flags & USE_CLSR)
- nor->params->ready = spansion_nor_sr_ready_and_clear;
+ if (mfr_flags & (USE_CLSR | USE_CLPEF)) {
+ priv_params = devm_kmalloc(nor->dev, sizeof(*priv_params),
+ GFP_KERNEL);
+ if (!priv_params)
+ return -ENOMEM;
+
+ if (mfr_flags & USE_CLSR)
+ priv_params->clsr = SPINOR_OP_CLSR;
+ else if (mfr_flags & USE_CLPEF)
+ priv_params->clsr = SPINOR_OP_CLPEF;
+
+ params->priv = priv_params;
+ params->ready = spansion_nor_sr_ready_and_clear;
+ }
+
+ return 0;
}
static const struct spi_nor_fixups spansion_nor_fixups = {
diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
index 688eb20c763e..09fdc7023e09 100644
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -49,9 +49,11 @@ static const struct spi_nor_locking_ops sst26vf_nor_locking_ops = {
.is_locked = sst26vf_nor_is_locked,
};
-static void sst26vf_nor_late_init(struct spi_nor *nor)
+static int sst26vf_nor_late_init(struct spi_nor *nor)
{
nor->params->locking_ops = &sst26vf_nor_locking_ops;
+
+ return 0;
}
static const struct spi_nor_fixups sst26vf_nor_fixups = {
@@ -203,10 +205,12 @@ static int sst_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
return ret;
}
-static void sst_nor_late_init(struct spi_nor *nor)
+static int sst_nor_late_init(struct spi_nor *nor)
{
if (nor->info->mfr_flags & SST_WRITE)
nor->mtd._write = sst_nor_write;
+
+ return 0;
}
static const struct spi_nor_fixups sst_nor_fixups = {
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index 63ba8e3a96f5..cd99c9a1c568 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -217,7 +217,7 @@ static const struct spi_nor_otp_ops winbond_nor_otp_ops = {
.is_locked = spi_nor_otp_is_locked_sr2,
};
-static void winbond_nor_late_init(struct spi_nor *nor)
+static int winbond_nor_late_init(struct spi_nor *nor)
{
struct spi_nor_flash_parameter *params = nor->params;
@@ -233,6 +233,8 @@ static void winbond_nor_late_init(struct spi_nor *nor)
* from BFPT, if any.
*/
params->set_4byte_addr_mode = winbond_nor_set_4byte_addr_mode;
+
+ return 0;
}
static const struct spi_nor_fixups winbond_nor_fixups = {
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
index 7175de8aa336..00d53eae5ee8 100644
--- a/drivers/mtd/spi-nor/xilinx.c
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -155,10 +155,12 @@ static int xilinx_nor_setup(struct spi_nor *nor,
return 0;
}
-static void xilinx_nor_late_init(struct spi_nor *nor)
+static int xilinx_nor_late_init(struct spi_nor *nor)
{
nor->params->setup = xilinx_nor_setup;
nor->params->ready = xilinx_nor_sr_ready;
+
+ return 0;
}
static const struct spi_nor_fixups xilinx_nor_fixups = {
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH v2 2/8] mtd: spi-nor: spansion: preserve CFR2V[7] when writing MEMLAT
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
2023-07-20 7:09 ` [PATCH v2 1/8] mtd: spi-nor: spansion: use CLPEF as an alternative to CLSR tkuw584924
@ 2023-07-20 7:09 ` tkuw584924
2023-07-20 7:09 ` [PATCH v2 3/8] mtd: spi-nor: spansion: prepare octal dtr methods for multi chip support tkuw584924
` (6 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:09 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano,
stable
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
CFR2V[7] is assigned to Flash's address mode (3- or 4-ybte) and must not
be changed when writing MEMLAT (CFR2V[3:0]). CFR2V shall be used in a read,
update, write back fashion.
Fixes: c3266af101f2 ("mtd: spi-nor: spansion: add support for Cypress Semper flash")
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Cc: stable@vger.kernel.org
---
drivers/mtd/spi-nor/spansion.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index f40d4ede4093..8515f7e56715 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -4,6 +4,7 @@
* Copyright (C) 2014, Freescale Semiconductor, Inc.
*/
+#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/mtd/spi-nor.h>
@@ -28,6 +29,7 @@
#define SPINOR_REG_CYPRESS_CFR2 0x3
#define SPINOR_REG_CYPRESS_CFR2V \
(SPINOR_REG_CYPRESS_VREG + SPINOR_REG_CYPRESS_CFR2)
+#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK GENMASK(3, 0)
#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb
#define SPINOR_REG_CYPRESS_CFR2_ADRBYT BIT(7)
#define SPINOR_REG_CYPRESS_CFR3 0x4
@@ -161,8 +163,18 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
int ret;
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);
+
+ ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
+ if (ret)
+ return ret;
+
/* Use 24 dummy cycles for memory array reads. */
- *buf = SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24;
+ *buf &= ~SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK;
+ *buf |= FIELD_PREP(SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK,
+ 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);
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH v2 3/8] mtd: spi-nor: spansion: prepare octal dtr methods for multi chip support
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
2023-07-20 7:09 ` [PATCH v2 1/8] mtd: spi-nor: spansion: use CLPEF as an alternative to CLSR tkuw584924
2023-07-20 7:09 ` [PATCH v2 2/8] mtd: spi-nor: spansion: preserve CFR2V[7] when writing MEMLAT tkuw584924
@ 2023-07-20 7:09 ` tkuw584924
2023-07-20 7:09 ` [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset tkuw584924
` (5 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:09 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Infineon's multi-chip package (MCP) devices require the octal DTR
configuration to be set for each die. Split common code in
dedicated methods to ease the octal DDR MCP support addition.
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
drivers/mtd/spi-nor/spansion.c | 50 +++++++++++++++++++++++++---------
1 file changed, 37 insertions(+), 13 deletions(-)
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 8515f7e56715..b99ed088b377 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_set_memlat(struct spi_nor *nor, u64 addr)
{
struct spi_mem_op op;
u8 *buf = nor->bouncebuf;
@@ -164,8 +164,7 @@ static int cypress_nor_octal_dtr_en(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)
@@ -176,8 +175,7 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
*buf |= FIELD_PREP(SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK,
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);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
if (ret)
@@ -185,13 +183,33 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
nor->read_dummy = 24;
+ return 0;
+}
+
+static int cypress_nor_set_octal_dtr_bits(struct spi_nor *nor, u64 addr)
+{
+ struct spi_mem_op op;
+ u8 *buf = nor->bouncebuf;
+
/* 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);
+ CYPRESS_NOR_WR_ANY_REG_OP(nor->params->addr_mode_nbytes,
+ addr, 1, buf);
- ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
+ return spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
+}
+
+static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
+{
+ u8 *buf = nor->bouncebuf;
+ int ret;
+
+ ret = cypress_nor_set_memlat(nor, SPINOR_REG_CYPRESS_CFR2V);
+ if (ret)
+ return ret;
+
+ ret = cypress_nor_set_octal_dtr_bits(nor, SPINOR_REG_CYPRESS_CFR5V);
if (ret)
return ret;
@@ -209,11 +227,10 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
return 0;
}
-static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
+static int cypress_nor_set_single_spi_bits(struct spi_nor *nor, u64 addr)
{
struct spi_mem_op op;
u8 *buf = nor->bouncebuf;
- int ret;
/*
* The register is 1-byte wide, but 1-byte transactions are not allowed
@@ -223,9 +240,16 @@ static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
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);
+ CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes, addr, 2, buf);
+ return spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
+}
+
+static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
+{
+ u8 *buf = nor->bouncebuf;
+ int ret;
+
+ ret = cypress_nor_set_single_spi_bits(nor, SPINOR_REG_CYPRESS_CFR5V);
if (ret)
return ret;
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
` (2 preceding siblings ...)
2023-07-20 7:09 ` [PATCH v2 3/8] mtd: spi-nor: spansion: prepare octal dtr methods for multi chip support tkuw584924
@ 2023-07-20 7:09 ` tkuw584924
2023-07-21 16:42 ` Tudor Ambarus
2023-07-20 7:10 ` [PATCH v2 5/8] mtd: spi-nor: spansion: switch h28hx's ready() " tkuw584924
` (4 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:09 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
All the Infineon flashes that currently support octal DTR mode
define the optional SCCR SFDP table, thus all retrieve vreg_offset.
Switch all the available octal DTR Infineon flashes to use the
volatile register offset to set the configuration registers. The goal
is to have a single pair of methods for both single/multi-chip package
devices.
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
drivers/mtd/spi-nor/spansion.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index b99ed088b377..9150840e748a 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -6,6 +6,7 @@
#include <linux/bitfield.h>
#include <linux/device.h>
+#include <linux/errno.h>
#include <linux/mtd/spi-nor.h>
#include "core.h"
@@ -202,14 +203,18 @@ static int cypress_nor_set_octal_dtr_bits(struct spi_nor *nor, u64 addr)
static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
{
+ const struct spi_nor_flash_parameter *params = nor->params;
u8 *buf = nor->bouncebuf;
+ u64 addr;
int ret;
- ret = cypress_nor_set_memlat(nor, SPINOR_REG_CYPRESS_CFR2V);
+ addr = params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR2;
+ ret = cypress_nor_set_memlat(nor, addr);
if (ret)
return ret;
- ret = cypress_nor_set_octal_dtr_bits(nor, SPINOR_REG_CYPRESS_CFR5V);
+ addr = params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR5;
+ ret = cypress_nor_set_octal_dtr_bits(nor, addr);
if (ret)
return ret;
@@ -247,9 +252,11 @@ static int cypress_nor_set_single_spi_bits(struct spi_nor *nor, u64 addr)
static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
{
u8 *buf = nor->bouncebuf;
+ u64 addr;
int ret;
- ret = cypress_nor_set_single_spi_bits(nor, SPINOR_REG_CYPRESS_CFR5V);
+ addr = nor->params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR5;
+ ret = cypress_nor_set_single_spi_bits(nor, addr);
if (ret)
return ret;
@@ -671,6 +678,11 @@ static struct spi_nor_fixups s25hx_t_fixups = {
*/
static int cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
{
+ if (!nor->params->vreg_offset) {
+ dev_err(nor->dev, "Can not set octal DTR. The volatile register offset could not be retrieved from SFDP\n");
+ return -EOPNOTSUPP;
+ }
+
return enable ? cypress_nor_octal_dtr_en(nor) :
cypress_nor_octal_dtr_dis(nor);
}
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset
2023-07-20 7:09 ` [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset tkuw584924
@ 2023-07-21 16:42 ` Tudor Ambarus
2023-07-21 16:49 ` Tudor Ambarus
0 siblings, 1 reply; 16+ messages in thread
From: Tudor Ambarus @ 2023-07-21 16:42 UTC (permalink / raw)
To: tkuw584924, linux-mtd
Cc: pratyush, michael, miquel.raynal, richard, vigneshr, d-gole,
Bacem.Daassi, Takahiro Kuwano
On 20.07.2023 10:09, tkuw584924@gmail.com wrote:
> From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>
> All the Infineon flashes that currently support octal DTR mode
> define the optional SCCR SFDP table, thus all retrieve vreg_offset.
> Switch all the available octal DTR Infineon flashes to use the
> volatile register offset to set the configuration registers. The goal
> is to have a single pair of methods for both single/multi-chip package
> devices.
>
> Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> ---
> drivers/mtd/spi-nor/spansion.c | 18 +++++++++++++++---
> 1 file changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> index b99ed088b377..9150840e748a 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -6,6 +6,7 @@
>
> #include <linux/bitfield.h>
> #include <linux/device.h>
> +#include <linux/errno.h>
> #include <linux/mtd/spi-nor.h>
>
> #include "core.h"
> @@ -202,14 +203,18 @@ static int cypress_nor_set_octal_dtr_bits(struct spi_nor *nor, u64 addr)
>
> static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
> {
> + const struct spi_nor_flash_parameter *params = nor->params;
> u8 *buf = nor->bouncebuf;
> + u64 addr;
> int ret;
>
> - ret = cypress_nor_set_memlat(nor, SPINOR_REG_CYPRESS_CFR2V);
> + addr = params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR2;
> + ret = cypress_nor_set_memlat(nor, addr);
> if (ret)
> return ret;
>
> - ret = cypress_nor_set_octal_dtr_bits(nor, SPINOR_REG_CYPRESS_CFR5V);
> + addr = params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR5;
> + ret = cypress_nor_set_octal_dtr_bits(nor, addr);
> if (ret)
> return ret;
>
> @@ -247,9 +252,11 @@ static int cypress_nor_set_single_spi_bits(struct spi_nor *nor, u64 addr)
> static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
> {
> u8 *buf = nor->bouncebuf;
> + u64 addr;
> int ret;
>
> - ret = cypress_nor_set_single_spi_bits(nor, SPINOR_REG_CYPRESS_CFR5V);
> + addr = nor->params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR5;
> + ret = cypress_nor_set_single_spi_bits(nor, addr);
> if (ret)
> return ret;
>
> @@ -671,6 +678,11 @@ static struct spi_nor_fixups s25hx_t_fixups = {
> */
> static int cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
> {
const struct spi_nor_flash_parameter *params = nor->params;
> + if (!nor->params->vreg_offset) {
wouldn't hurt to check for params->n_dice as well, even though one
implies the other. In the next patch you have a loop with n-dice being
the max number of elements. If n-dice becomes zero sometime, the loop is
skipped. Thus:
if (params->n_dice && !nor->params->vreg_offset)
> + dev_err(nor->dev, "Can not set octal DTR. The volatile register offset could not be retrieved from SFDP\n");
> + return -EOPNOTSUPP;
> + }
> +
> return enable ? cypress_nor_octal_dtr_en(nor) :
> cypress_nor_octal_dtr_dis(nor);
> }
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset
2023-07-21 16:42 ` Tudor Ambarus
@ 2023-07-21 16:49 ` Tudor Ambarus
2023-07-22 5:25 ` Tudor Ambarus
0 siblings, 1 reply; 16+ messages in thread
From: Tudor Ambarus @ 2023-07-21 16:49 UTC (permalink / raw)
To: tkuw584924, linux-mtd
Cc: pratyush, michael, miquel.raynal, richard, vigneshr, d-gole,
Bacem.Daassi, Takahiro Kuwano
>> static int cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
>> {
> const struct spi_nor_flash_parameter *params = nor->params;
>
>> + if (!nor->params->vreg_offset) {
>
> wouldn't hurt to check for params->n_dice as well, even though one
> implies the other. In the next patch you have a loop with n-dice being
> the max number of elements. If n-dice becomes zero sometime, the loop is
> skipped. Thus:
>
> if (params->n_dice && !nor->params->vreg_offset)
>
if (!params->n_dice || !params->vreg_offset)
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset
2023-07-21 16:49 ` Tudor Ambarus
@ 2023-07-22 5:25 ` Tudor Ambarus
2023-07-22 6:50 ` Tudor Ambarus
0 siblings, 1 reply; 16+ messages in thread
From: Tudor Ambarus @ 2023-07-22 5:25 UTC (permalink / raw)
To: tkuw584924, linux-mtd
Cc: pratyush, michael, miquel.raynal, richard, vigneshr, d-gole,
Bacem.Daassi, Takahiro Kuwano
On 21.07.2023 19:49, Tudor Ambarus wrote:
>
>>> static int cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
>>> {
>> const struct spi_nor_flash_parameter *params = nor->params;
>>
>>> + if (!nor->params->vreg_offset) {
>>
>> wouldn't hurt to check for params->n_dice as well, even though one
>> implies the other. In the next patch you have a loop with n-dice being
>> the max number of elements. If n-dice becomes zero sometime, the loop is
>> skipped. Thus:
>>
>> if (params->n_dice && !nor->params->vreg_offset)
>>
> if (!params->n_dice || !params->vreg_offset)
and this sanity check should be moved to s28hx_t_late_init(), this way
we do it once, as it's needed when setting
cypress_nor_sr_ready_and_clear() too.
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset
2023-07-22 5:25 ` Tudor Ambarus
@ 2023-07-22 6:50 ` Tudor Ambarus
0 siblings, 0 replies; 16+ messages in thread
From: Tudor Ambarus @ 2023-07-22 6:50 UTC (permalink / raw)
To: tkuw584924, linux-mtd
Cc: pratyush, michael, miquel.raynal, richard, vigneshr, d-gole,
Bacem.Daassi, Takahiro Kuwano
On 22.07.2023 08:25, Tudor Ambarus wrote:
>
>
> On 21.07.2023 19:49, Tudor Ambarus wrote:
>>
>>>> static int cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
>>>> {
>>> const struct spi_nor_flash_parameter *params = nor->params;
>>>
>>>> + if (!nor->params->vreg_offset) {
>>>
>>> wouldn't hurt to check for params->n_dice as well, even though one
>>> implies the other. In the next patch you have a loop with n-dice being
>>> the max number of elements. If n-dice becomes zero sometime, the loop is
>>> skipped. Thus:
>>>
>>> if (params->n_dice && !nor->params->vreg_offset)
>>>
>> if (!params->n_dice || !params->vreg_offset)
>
> and this sanity check should be moved to s28hx_t_late_init(), this way
> we do it once, as it's needed when setting
> cypress_nor_sr_ready_and_clear() too.
and we shall switch s25hx_t flashes to use vreg_offset as well,
something like:
commit 0830e89c312ff5941dc1a7e0d251eb608c51c729 (HEAD -> spi-nor/next)
Author: Tudor Ambarus <tudor.ambarus@linaro.org>
Date: Sat Jul 22 09:36:22 2023 +0300
mtd: spi-nor: spansion: switch s25hx_t to use vreg_offset
All s25hx_t flashes retrieve n_dice and vreg_offset from SFDP. Switch
s25hx_t to always use vreg_offset in order to use the same code base
for both single and multi chip package flashes.
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 413573cdb4fc..4027f0038ce5 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -350,10 +350,6 @@ static int cypress_nor_quad_enable_volatile(struct
spi_nor *nor)
u8 i;
int ret;
- if (!params->n_dice)
- return cypress_nor_quad_enable_volatile_reg(nor,
- SPINOR_REG_CYPRESS_CFR1V);
-
for (i = 0; i < params->n_dice; i++) {
addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR1;
ret = cypress_nor_quad_enable_volatile_reg(nor, addr);
@@ -659,15 +655,17 @@ static int s25hx_t_late_init(struct spi_nor *nor)
{
struct spi_nor_flash_parameter *params = nor->params;
+ if (!params->n_dice || !params->vreg_offset) {
+ dev_err(nor->dev, "%s failed. The volatile register
offset could not be retrieved from SFDP.\n",
+ __func__);
+ return -EOPNOTSUPP;
+ }
+
/* Fast Read 4B requires mode cycles */
params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8;
-
+ params->ready = cypress_nor_sr_ready_and_clear;
cypress_nor_ecc_init(nor);
- /* Replace ready() with multi die version */
- if (params->n_dice)
- params->ready = cypress_nor_sr_ready_and_clear;
-
return 0;
}
I'll send a v3 with all changes, it's easier this way.
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 5/8] mtd: spi-nor: spansion: switch h28hx's ready() to use vreg_offset
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
` (3 preceding siblings ...)
2023-07-20 7:09 ` [PATCH v2 4/8] mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset tkuw584924
@ 2023-07-20 7:10 ` tkuw584924
2023-07-21 16:50 ` Tudor Ambarus
2023-07-20 7:10 ` [PATCH v2 6/8] mtd: spi-nor: spansion: add MCP support in set_octal_dtr() tkuw584924
` (3 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:10 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
s28hx is the sole user of cypress_nor_set_octal_dtr, which already
uses vreg_offset to set octal DTR. Switch the ready method to use
vreg_offset as well. This is a preparation patch. The goal is to use
the same s28hx methods for the multi die version of the flash.
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
drivers/mtd/spi-nor/spansion.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 9150840e748a..00d8305e25f4 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -732,9 +732,15 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
static int s28hx_t_late_init(struct spi_nor *nor)
{
- nor->params->set_octal_dtr = cypress_nor_set_octal_dtr;
+ struct spi_nor_flash_parameter *params = nor->params;
+
+ params->set_octal_dtr = cypress_nor_set_octal_dtr;
cypress_nor_ecc_init(nor);
+ /* Replace ready() with multi die version. */
+ if (params->n_dice)
+ params->ready = cypress_nor_sr_ready_and_clear;
+
return 0;
}
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v2 5/8] mtd: spi-nor: spansion: switch h28hx's ready() to use vreg_offset
2023-07-20 7:10 ` [PATCH v2 5/8] mtd: spi-nor: spansion: switch h28hx's ready() " tkuw584924
@ 2023-07-21 16:50 ` Tudor Ambarus
0 siblings, 0 replies; 16+ messages in thread
From: Tudor Ambarus @ 2023-07-21 16:50 UTC (permalink / raw)
To: tkuw584924, linux-mtd
Cc: pratyush, michael, miquel.raynal, richard, vigneshr, d-gole,
Bacem.Daassi, Takahiro Kuwano
On 20.07.2023 10:10, tkuw584924@gmail.com wrote:
> From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>
> s28hx is the sole user of cypress_nor_set_octal_dtr, which already
> uses vreg_offset to set octal DTR. Switch the ready method to use
> vreg_offset as well. This is a preparation patch. The goal is to use
> the same s28hx methods for the multi die version of the flash.
>
> Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> ---
> drivers/mtd/spi-nor/spansion.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> index 9150840e748a..00d8305e25f4 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -732,9 +732,15 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
>
> static int s28hx_t_late_init(struct spi_nor *nor)
> {
> - nor->params->set_octal_dtr = cypress_nor_set_octal_dtr;
> + struct spi_nor_flash_parameter *params = nor->params;
> +
> + params->set_octal_dtr = cypress_nor_set_octal_dtr;
> cypress_nor_ecc_init(nor);
>
> + /* Replace ready() with multi die version. */
> + if (params->n_dice)
same explanation:
if (params->n_dice && params->vreg_offset)
> + params->ready = cypress_nor_sr_ready_and_clear;
> +
> return 0;
> }
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 6/8] mtd: spi-nor: spansion: add MCP support in set_octal_dtr()
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
` (4 preceding siblings ...)
2023-07-20 7:10 ` [PATCH v2 5/8] mtd: spi-nor: spansion: switch h28hx's ready() " tkuw584924
@ 2023-07-20 7:10 ` tkuw584924
2023-07-20 7:10 ` [PATCH v2 7/8] mtd: spi-nor: spansion: add octal DTR support in RD_ANY_REG_OP tkuw584924
` (2 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:10 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Infineon multi-chip package (MCP) devices require the Octal DTR
configuraion to be set on each die. We can access to configuration
registers in each die by using params->n_dice and params->vreg_offset[]
populated from SFDP. Add MCP support in set_octal_dtr().
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
drivers/mtd/spi-nor/spansion.c | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 00d8305e25f4..4e791f1b9044 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -206,17 +206,19 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
const struct spi_nor_flash_parameter *params = nor->params;
u8 *buf = nor->bouncebuf;
u64 addr;
- int ret;
+ int i, ret;
- addr = params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR2;
- ret = cypress_nor_set_memlat(nor, addr);
- if (ret)
- return ret;
+ for (i = 0; i < params->n_dice; i++) {
+ addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR2;
+ ret = cypress_nor_set_memlat(nor, addr);
+ if (ret)
+ return ret;
- addr = params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR5;
- ret = cypress_nor_set_octal_dtr_bits(nor, addr);
- if (ret)
- return ret;
+ addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR5;
+ ret = cypress_nor_set_octal_dtr_bits(nor, addr);
+ 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,
@@ -251,14 +253,17 @@ static int cypress_nor_set_single_spi_bits(struct spi_nor *nor, u64 addr)
static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
{
+ const struct spi_nor_flash_parameter *params = nor->params;
u8 *buf = nor->bouncebuf;
u64 addr;
- int ret;
+ int i, ret;
- addr = nor->params->vreg_offset[0] + SPINOR_REG_CYPRESS_CFR5;
- ret = cypress_nor_set_single_spi_bits(nor, addr);
- if (ret)
- return ret;
+ for (i = 0; i < params->n_dice; i++) {
+ addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR5;
+ ret = cypress_nor_set_single_spi_bits(nor, addr);
+ 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);
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH v2 7/8] mtd: spi-nor: spansion: add octal DTR support in RD_ANY_REG_OP
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
` (5 preceding siblings ...)
2023-07-20 7:10 ` [PATCH v2 6/8] mtd: spi-nor: spansion: add MCP support in set_octal_dtr() tkuw584924
@ 2023-07-20 7:10 ` tkuw584924
2023-07-20 7:10 ` [PATCH v2 8/8] mtd: spi-nor: spansion: add support for S28HS02GT tkuw584924
2023-07-20 7:54 ` [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT Takahiro Kuwano
8 siblings, 0 replies; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:10 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
S28HS02GT uses RD_ANY_REG_OP to read status of each die. In Octal DTR
mode, RD_ANY_REG_OP needs dummy cycles (same as params->rdsr_dummy) and
data length should be 2.
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
---
drivers/mtd/spi-nor/spansion.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 4e791f1b9044..dbf19580c3c3 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -104,11 +104,17 @@ static void spansion_nor_clear_sr(struct spi_nor *nor)
static int cypress_nor_sr_ready_and_clear_reg(struct spi_nor *nor, u64 addr)
{
+ struct spi_nor_flash_parameter *params = nor->params;
struct spi_mem_op op =
- CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes, addr,
+ CYPRESS_NOR_RD_ANY_REG_OP(params->addr_mode_nbytes, addr,
0, nor->bouncebuf);
int ret;
+ if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
+ op.dummy.nbytes = params->rdsr_dummy;
+ op.data.nbytes = 2;
+ }
+
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
if (ret)
return ret;
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH v2 8/8] mtd: spi-nor: spansion: add support for S28HS02GT
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
` (6 preceding siblings ...)
2023-07-20 7:10 ` [PATCH v2 7/8] mtd: spi-nor: spansion: add octal DTR support in RD_ANY_REG_OP tkuw584924
@ 2023-07-20 7:10 ` tkuw584924
2023-07-20 7:54 ` [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT Takahiro Kuwano
8 siblings, 0 replies; 16+ messages in thread
From: tkuw584924 @ 2023-07-20 7:10 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, tkuw584924, Bacem.Daassi, Takahiro Kuwano
From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Add support for S28HS02GT. Infineon S28HS02GT is a 2Gb,
multi-chip package, Octal SPI Flash.
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
---
drivers/mtd/spi-nor/spansion.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index dbf19580c3c3..ae8f9fd766f3 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -700,22 +700,23 @@ static int cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
static int s28hx_t_post_sfdp_fixup(struct spi_nor *nor)
{
+ struct spi_nor_flash_parameter *params = nor->params;
/*
* On older versions of the flash the xSPI Profile 1.0 table has the
* 8D-8D-8D Fast Read opcode as 0x00. But it actually should be 0xEE.
*/
- if (nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode == 0)
- nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode =
+ if (params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode == 0)
+ params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode =
SPINOR_OP_CYPRESS_RD_FAST;
/* This flash is also missing the 4-byte Page Program opcode bit. */
- spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP],
+ spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP],
SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1);
/*
* Since xSPI Page Program opcode is backward compatible with
* Legacy SPI, use Legacy SPI opcode there as well.
*/
- spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP_8_8_8_DTR],
+ spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8_8_8_DTR],
SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR);
/*
@@ -723,7 +724,11 @@ static int s28hx_t_post_sfdp_fixup(struct spi_nor *nor)
* address bytes needed for Read Status Register command as 0 but the
* actual value for that is 4.
*/
- nor->params->rdsr_addr_nbytes = 4;
+ params->rdsr_addr_nbytes = 4;
+
+ /* The 2 Gb parts duplicate info and advertise 4 dice instead of 2. */
+ if (params->size == SZ_256M)
+ params->n_dice = 2;
return cypress_nor_get_page_size(nor);
}
@@ -926,6 +931,11 @@ static const struct flash_info spansion_nor_parts[] = {
MFR_FLAGS(USE_CLPEF)
.fixups = &s28hx_t_fixups,
},
+ { "s28hs02gt", INFO(0x345b1c, 0, 0, 0)
+ PARSE_SFDP
+ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s28hx_t_fixups,
+ },
};
/**
--
2.34.1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT
2023-07-20 7:09 [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT tkuw584924
` (7 preceding siblings ...)
2023-07-20 7:10 ` [PATCH v2 8/8] mtd: spi-nor: spansion: add support for S28HS02GT tkuw584924
@ 2023-07-20 7:54 ` Takahiro Kuwano
2023-07-22 5:04 ` Tudor Ambarus
8 siblings, 1 reply; 16+ messages in thread
From: Takahiro Kuwano @ 2023-07-20 7:54 UTC (permalink / raw)
To: linux-mtd
Cc: tudor.ambarus, pratyush, michael, miquel.raynal, richard,
vigneshr, d-gole, Bacem.Daassi, Takahiro Kuwano
Hi,
I tested with the following devices, as this series updates the code used by
other SEMPER flash devices than S28HS02GT.
- S28HS02GT(Octal, multi-chip)
- S28HS01GT(Octal, single-chip)
- S25HS02GT(Quad, multi-chip)
- S25HS01GT(Quad, single-chip)
- S25FS256T(Quad, single-chip)
Thanks,
Takahiro
On 7/20/2023 4:09 PM, tkuw584924@gmail.com wrote:
> From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>
> Infineon S28HS02GT is 2Gbit, multi-chip package, Octal SPI NOR flash. This
> series reworks octal_dtr_enable part to support MCP and then adds ID and
> fixups for S28HS02GT.
>
> Tested on Zynq-7000 platform with Infineon SPI controller
>
> ID, SFDP, Test logs:
> ---
> zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname
> s28hs02gt
> zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id
> 345b1c
> zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer
> spansion
> zynq> xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
> 53464450080106fe00000114000100ff84000102500100ff050001055801
> 00ff8700011c6c0100ff88000106dc0100ff81000118040200ff0a000104
> f40100ffffffffffffffffffffffffffffffffffffffffffffffffffffff
> ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
> ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
> ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
> ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
> ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
> fffffffffffffffffffffffffffffffff7218affffffff7f000000000000
> 0000eeffffffffff0000ffff00000c2100ff00ff12dc23faff8b82e7ffec
> ec2319497ab07ab0f766805c000000fff910c0a0000000000000bc020000
> 0000ffff7e7e41120ffe21ffffdc00ee800b7171656500b0ff9600000000
> 0c551ca20000800000000000c0ccfffb88fbfffb00650090066500b10065
> 009600650095716503d0716503d0a46bfb0290a579a20040288e0000ff00
> 0000ff0071650690716506900000000000000000716506d1716506d17165
> 0691716506910000ff000000ff00716505d5716505d50000a01500008008
> 000000080000801000000010000080180000001800000601000000008000
> 710600030600fc65ff0804008000fc65ff0402008000fc65ff0804008008
> fd65ff0402008008fe0202fff1ff0100f8ff0100f8fffb0ffe0902fff8ff
> fb0ff8ff0100f1ff0100fe0104fff1ff0100f8ff0100f8fff70ff8ff0100
> f1ff0100ff0a00fff8ffff0f
> zynq> md5sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
> 6193b9729008b80b9a2b4bb3ce06a91d /sys/bus/spi/devices/spi0.0/spi-nor/sfdp
> zynq> test_qspi.sh
> 6+0 records in
> 6+0 records out
> 6291456 bytes (6.0MB) copied, 0.234679 seconds, 25.6MB/s
> Copied 6291456 bytes from qspi_test to address 0x00000000 in flash
> Erased 6291456 bytes from address 0x00000000 in flash
> Copied 6291456 bytes from address 0x00000000 in flash to qspi_read
> 0000000 ffff ffff ffff ffff ffff ffff ffff ffff
> *
> 0600000
> Copied 6291456 bytes from qspi_test to address 0x00000000 in flash
> Copied 6291456 bytes from address 0x00000000 in flash to qspi_read
> 3020d73d4d0e570449faacfbadf134e074ced30e qspi_test
> 3020d73d4d0e570449faacfbadf134e074ced30e qspi_read
> ---
>
> Takahiro Kuwano (8):
> mtd: spi-nor: spansion: use CLPEF as an alternative to CLSR
> mtd: spi-nor: spansion: preserve CFR2V[7] when writing MEMLAT
> mtd: spi-nor: spansion: prepare octal dtr methods for multi chip
> support
> mtd: spi-nor: spansion: switch set_octal_dtr method to use vreg_offset
> mtd: spi-nor: spansion: switch h28hx's ready() to use vreg_offset
> mtd: spi-nor: spansion: add MCP support in set_octal_dtr()
> mtd: spi-nor: spansion: add octal DTR support in RD_ANY_REG_OP
> mtd: spi-nor: spansion: add support for S28HS02GT
>
> drivers/mtd/spi-nor/atmel.c | 8 +-
> drivers/mtd/spi-nor/core.c | 23 ++--
> drivers/mtd/spi-nor/core.h | 4 +-
> drivers/mtd/spi-nor/issi.c | 4 +-
> drivers/mtd/spi-nor/macronix.c | 4 +-
> drivers/mtd/spi-nor/micron-st.c | 4 +-
> drivers/mtd/spi-nor/spansion.c | 193 ++++++++++++++++++++++++++------
> drivers/mtd/spi-nor/sst.c | 8 +-
> drivers/mtd/spi-nor/winbond.c | 4 +-
> drivers/mtd/spi-nor/xilinx.c | 4 +-
> 10 files changed, 201 insertions(+), 55 deletions(-)
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT
2023-07-20 7:54 ` [PATCH v2 0/8] mtd: spi-nor: spansion: Add support for Infineon S28HS02GT Takahiro Kuwano
@ 2023-07-22 5:04 ` Tudor Ambarus
0 siblings, 0 replies; 16+ messages in thread
From: Tudor Ambarus @ 2023-07-22 5:04 UTC (permalink / raw)
To: Takahiro Kuwano, linux-mtd
Cc: pratyush, michael, miquel.raynal, richard, vigneshr, d-gole,
Bacem.Daassi, Takahiro Kuwano
On 20.07.2023 10:54, Takahiro Kuwano wrote:
> I tested with the following devices, as this series updates the code used by
> other SEMPER flash devices than S28HS02GT.
> - S28HS02GT(Octal, multi-chip)
> - S28HS01GT(Octal, single-chip)
> - S25HS02GT(Quad, multi-chip)
> - S25HS01GT(Quad, single-chip)
> - S25FS256T(Quad, single-chip)
That's good effort, thanks! Now that you introduced CLPEF and you have
to test all the flashes, is a good time to let SFDP determine the flash
size and let the core select the erase size. Can you please test the
following patch? You'll have to make sure that the flash size and the
selected erase size are sane.
https://lore.kernel.org/linux-mtd/20230722045901.9872-1-tudor.ambarus@linaro.org/T/#u
Thanks,
ta
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 16+ messages in thread