2020-03-02 18:09:07

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core

From: Tudor Ambarus <[email protected]>

Hello,

This patch series is an attempt at getting all manufacturer specific
quirks/code out of the core to make the core logic more readable and
thus ease maintainance.

This is a respin of the last chunk of Boris's work from
https://patchwork.ozlabs.org/cover/1009290/.

Tested an erase-write-read-compare with a 1MB file on the following
flashes: mx25l25635e, w25q128, n25q256a, is25lp256, s25fl256s0,
gd25q256.

Boris Brezillon (21):
mtd: spi-nor: Stop prefixing generic functions with a manufacturer
name
mtd: spi-nor: Prepare core / manufacturer code split
mtd: spi-nor: Expose stuctures and functions to manufacturer drivers
mtd: spi-nor: Add the concept of SPI NOR manufacturer driver
mtd: spi-nor: Move Atmel bits out of core.c
mtd: spi-nor: Move Eon bits out of core.c
mtd: spi-nor: Move ESMT bits out of core.c
mtd: spi-nor: Move Everspin bits out of core.c
mtd: spi-nor: Move Fujitsu bits out of core.c
mtd: spi-nor: Move GigaDevice bits out of core.c
mtd: spi-nor: Move Intel bits out of core.c
mtd: spi-nor: Move ISSI bits out of core.c
mtd: spi-nor: Move Macronix bits out of core.c
mtd: spi-nor: Move Micron/ST bits out of core.c
mtd: spi-nor: Move Spansion bits out of core.c
mtd: spi-nor: Move SST bits out of core.c
mtd: spi-nor: Move Winbond bits out of core.c
mtd: spi-nor: Move Catalyst bits out of core.c
mtd: spi-nor: Move Xilinx bits out of core.c
mtd: spi-nor: Move XMC bits out of core.c
mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table

Tudor Ambarus (2):
mtd: spi-nor: Move SFDP logic out of the core
mtd: spi-nor: Trim what is exposed in spi-nor.h

drivers/mtd/spi-nor/Kconfig | 83 +-
drivers/mtd/spi-nor/Makefile | 26 +-
drivers/mtd/spi-nor/atmel.c | 46 +
drivers/mtd/spi-nor/catalyst.c | 29 +
drivers/mtd/spi-nor/controllers/Kconfig | 83 +
drivers/mtd/spi-nor/controllers/Makefile | 9 +
.../spi-nor/{ => controllers}/aspeed-smc.c | 0
.../{ => controllers}/cadence-quadspi.c | 0
.../mtd/spi-nor/{ => controllers}/hisi-sfc.c | 0
.../spi-nor/{ => controllers}/intel-spi-pci.c | 0
.../{ => controllers}/intel-spi-platform.c | 0
.../mtd/spi-nor/{ => controllers}/intel-spi.c | 0
.../mtd/spi-nor/{ => controllers}/intel-spi.h | 0
.../spi-nor/{ => controllers}/mtk-quadspi.c | 0
.../mtd/spi-nor/{ => controllers}/nxp-spifi.c | 0
drivers/mtd/spi-nor/{spi-nor.c => core.c} | 2503 ++---------------
drivers/mtd/spi-nor/core.h | 432 +++
drivers/mtd/spi-nor/eon.c | 34 +
drivers/mtd/spi-nor/esmt.c | 25 +
drivers/mtd/spi-nor/everspin.c | 27 +
drivers/mtd/spi-nor/fujitsu.c | 20 +
drivers/mtd/spi-nor/gigadevice.c | 59 +
drivers/mtd/spi-nor/intel.c | 32 +
drivers/mtd/spi-nor/issi.c | 83 +
drivers/mtd/spi-nor/macronix.c | 98 +
drivers/mtd/spi-nor/micron-st.c | 129 +
drivers/mtd/spi-nor/sfdp.c | 1206 ++++++++
drivers/mtd/spi-nor/sfdp.h | 98 +
drivers/mtd/spi-nor/spansion.c | 95 +
drivers/mtd/spi-nor/sst.c | 151 +
drivers/mtd/spi-nor/winbond.c | 113 +
drivers/mtd/spi-nor/xilinx.c | 94 +
drivers/mtd/spi-nor/xmc.c | 23 +
include/linux/mtd/spi-nor.h | 257 +-
34 files changed, 3121 insertions(+), 2634 deletions(-)
create mode 100644 drivers/mtd/spi-nor/atmel.c
create mode 100644 drivers/mtd/spi-nor/catalyst.c
create mode 100644 drivers/mtd/spi-nor/controllers/Kconfig
create mode 100644 drivers/mtd/spi-nor/controllers/Makefile
rename drivers/mtd/spi-nor/{ => controllers}/aspeed-smc.c (100%)
rename drivers/mtd/spi-nor/{ => controllers}/cadence-quadspi.c (100%)
rename drivers/mtd/spi-nor/{ => controllers}/hisi-sfc.c (100%)
rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-pci.c (100%)
rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-platform.c (100%)
rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.c (100%)
rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.h (100%)
rename drivers/mtd/spi-nor/{ => controllers}/mtk-quadspi.c (100%)
rename drivers/mtd/spi-nor/{ => controllers}/nxp-spifi.c (100%)
rename drivers/mtd/spi-nor/{spi-nor.c => core.c} (52%)
create mode 100644 drivers/mtd/spi-nor/core.h
create mode 100644 drivers/mtd/spi-nor/eon.c
create mode 100644 drivers/mtd/spi-nor/esmt.c
create mode 100644 drivers/mtd/spi-nor/everspin.c
create mode 100644 drivers/mtd/spi-nor/fujitsu.c
create mode 100644 drivers/mtd/spi-nor/gigadevice.c
create mode 100644 drivers/mtd/spi-nor/intel.c
create mode 100644 drivers/mtd/spi-nor/issi.c
create mode 100644 drivers/mtd/spi-nor/macronix.c
create mode 100644 drivers/mtd/spi-nor/micron-st.c
create mode 100644 drivers/mtd/spi-nor/sfdp.c
create mode 100644 drivers/mtd/spi-nor/sfdp.h
create mode 100644 drivers/mtd/spi-nor/spansion.c
create mode 100644 drivers/mtd/spi-nor/sst.c
create mode 100644 drivers/mtd/spi-nor/winbond.c
create mode 100644 drivers/mtd/spi-nor/xilinx.c
create mode 100644 drivers/mtd/spi-nor/xmc.c

--
2.23.0


2020-03-02 18:09:26

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 13/23] mtd: spi-nor: Move ISSI bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for ISSI chips, and move the
ISSI definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 66 +---------------------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/issi.c | 83 ++++++++++++++++++++++++++++++++++++
4 files changed, 86 insertions(+), 65 deletions(-)
create mode 100644 drivers/mtd/spi-nor/issi.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 8eb741a27fa7..5c849f104cc4 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -8,4 +8,5 @@ spi-nor-objs += everspin.o
spi-nor-objs += fujitsu.o
spi-nor-objs += gigadevice.o
spi-nor-objs += intel.o
+spi-nor-objs += issi.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 2f47852a3a01..d781cb9af182 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2005,28 +2005,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
return 0;
}

-static int
-is25lp256_post_bfpt_fixups(struct spi_nor *nor,
- const struct sfdp_parameter_header *bfpt_header,
- const struct sfdp_bfpt *bfpt,
- struct spi_nor_flash_parameter *params)
-{
- /*
- * IS25LP256 supports 4B opcodes, but the BFPT advertises a
- * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width.
- * Overwrite the address width advertised by the BFPT.
- */
- if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
- BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
- nor->addr_width = 4;
-
- return 0;
-}
-
-static struct spi_nor_fixups is25lp256_fixups = {
- .post_bfpt = is25lp256_post_bfpt_fixups,
-};
-
static int
mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
@@ -2064,35 +2042,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* ISSI */
- { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) },
- { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "is25lp016d", INFO(0x9d6015, 0, 64 * 1024, 32,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "is25lp080d", INFO(0x9d6014, 0, 64 * 1024, 16,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "is25lp032", INFO(0x9d6016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ) },
- { "is25lp064", INFO(0x9d6017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ) },
- { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ) },
- { "is25lp256", INFO(0x9d6019, 0, 64 * 1024, 512,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_4B_OPCODES)
- .fixups = &is25lp256_fixups },
- { "is25wp032", INFO(0x9d7016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "is25wp064", INFO(0x9d7017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_4B_OPCODES)
- .fixups = &is25lp256_fixups },
-
/* Macronix */
{ "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) },
{ "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
@@ -2173,11 +2122,6 @@ static const struct flash_info spi_nor_ids[] = {
SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
SPI_NOR_4B_OPCODES) },

- /* PMC */
- { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
- { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
- { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
-
/* Spansion/Cypress -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
@@ -2366,6 +2310,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_fujitsu,
&spi_nor_gigadevice,
&spi_nor_intel,
+ &spi_nor_issi,
};

static const struct flash_info *
@@ -3145,11 +3090,6 @@ static int spi_nor_setup(struct spi_nor *nor,
return nor->params.setup(nor, hwcaps);
}

-static void issi_set_default_init(struct spi_nor *nor)
-{
- nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
-}
-
static void macronix_set_default_init(struct spi_nor *nor)
{
nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
@@ -3183,10 +3123,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
/* Init flash parameters based on MFR */
switch (JEDEC_MFR(nor->info)) {
- case SNOR_MFR_ISSI:
- issi_set_default_init(nor);
- break;
-
case SNOR_MFR_MACRONIX:
macronix_set_default_init(nor);
break;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index c4c23efaa68b..b4ed9acbef63 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -174,6 +174,7 @@ extern const struct spi_nor_manufacturer spi_nor_everspin;
extern const struct spi_nor_manufacturer spi_nor_fujitsu;
extern const struct spi_nor_manufacturer spi_nor_gigadevice;
extern const struct spi_nor_manufacturer spi_nor_intel;
+extern const struct spi_nor_manufacturer spi_nor_issi;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
new file mode 100644
index 000000000000..3a1c34c41388
--- /dev/null
+++ b/drivers/mtd/spi-nor/issi.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static int
+is25lp256_post_bfpt_fixups(struct spi_nor *nor,
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params)
+{
+ /*
+ * IS25LP256 supports 4B opcodes, but the BFPT advertises a
+ * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width.
+ * Overwrite the address width advertised by the BFPT.
+ */
+ if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
+ BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
+ nor->addr_width = 4;
+
+ return 0;
+}
+
+static struct spi_nor_fixups is25lp256_fixups = {
+ .post_bfpt = is25lp256_post_bfpt_fixups,
+};
+
+static const struct flash_info issi_parts[] = {
+ /* ISSI */
+ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) },
+ { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "is25lp016d", INFO(0x9d6015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "is25lp080d", INFO(0x9d6014, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "is25lp032", INFO(0x9d6016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "is25lp064", INFO(0x9d6017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "is25lp256", INFO(0x9d6019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES)
+ .fixups = &is25lp256_fixups },
+ { "is25wp032", INFO(0x9d7016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "is25wp064", INFO(0x9d7017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES)
+ .fixups = &is25lp256_fixups },
+
+ /* PMC */
+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
+};
+
+static void issi_default_init(struct spi_nor *nor)
+{
+ nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+}
+
+static const struct spi_nor_fixups issi_fixups = {
+ .default_init = issi_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_issi = {
+ .name = "issi",
+ .parts = issi_parts,
+ .nparts = ARRAY_SIZE(issi_parts),
+ .fixups = &issi_fixups,
+};
--
2.23.0

2020-03-02 18:09:46

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 07/23] mtd: spi-nor: Move Eon bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Eon chips, and move the
Eon definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 18 +-----------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/eon.c | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 37 insertions(+), 17 deletions(-)
create mode 100644 drivers/mtd/spi-nor/eon.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 0a243592e416..e1bc8ccfe14d 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -2,4 +2,5 @@

spi-nor-objs := core.o sfdp.o
spi-nor-objs += atmel.o
+spi-nor-objs += eon.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 45d370229e0a..67a3493939f6 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2079,23 +2079,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* EON -- en25xxx */
- { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
- { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
- { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
- { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
- { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
- { "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16,
- SECT_4K | SPI_NOR_DUAL_READ) },
- { "en25qh16", INFO(0x1c7015, 0, 64 * 1024, 32,
- SECT_4K | SPI_NOR_DUAL_READ) },
- { "en25qh32", INFO(0x1c7016, 0, 64 * 1024, 64, 0) },
- { "en25qh64", INFO(0x1c7017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ) },
- { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
- { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
- { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) },
-
/* ESMT */
{ "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
{ "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
@@ -2455,6 +2438,7 @@ static const struct flash_info spi_nor_ids[] = {

static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_atmel,
+ &spi_nor_eon,
};

static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 505e580add68..1ac226c456e1 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -168,6 +168,7 @@ struct spi_nor_manufacturer {

/* Manufacturer drivers. */
extern const struct spi_nor_manufacturer spi_nor_atmel;
+extern const struct spi_nor_manufacturer spi_nor_eon;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/eon.c b/drivers/mtd/spi-nor/eon.c
new file mode 100644
index 000000000000..ddb8e3650835
--- /dev/null
+++ b/drivers/mtd/spi-nor/eon.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info eon_parts[] = {
+ /* EON -- en25xxx */
+ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
+ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
+ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25q80a", INFO(0x1c3014, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "en25qh16", INFO(0x1c7015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "en25qh32", INFO(0x1c7016, 0, 64 * 1024, 64, 0) },
+ { "en25qh64", INFO(0x1c7017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
+ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) },
+};
+
+const struct spi_nor_manufacturer spi_nor_eon = {
+ .name = "eon",
+ .parts = eon_parts,
+ .nparts = ARRAY_SIZE(eon_parts),
+};
--
2.23.0

2020-03-02 18:10:11

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 16/23] mtd: spi-nor: Move Spansion bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Spansion chips, and move the
Spansion definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 59 +--------------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/spansion.c | 95 ++++++++++++++++++++++++++++++++++
4 files changed, 98 insertions(+), 58 deletions(-)
create mode 100644 drivers/mtd/spi-nor/spansion.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index c7e5fb908bec..cb06ee50bf68 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -11,4 +11,5 @@ spi-nor-objs += intel.o
spi-nor-objs += issi.o
spi-nor-objs += macronix.o
spi-nor-objs += micron-st.o
+spi-nor-objs += spansion.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8d54dfe33cdc..448717543d1e 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2017,44 +2017,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* Spansion/Cypress -- single (large) sector size only, at least
- * for the chips listed here (without boot sectors).
- */
- { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64,
- SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
- { "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
- SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
- { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
- { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
- { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
- SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | USE_CLSR) },
- { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
- { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
- { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
- { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
- { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
- { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
- { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
- { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
- { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
- { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
- { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) },
- { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) },
- { "s25fl064l", INFO(0x016017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-
/* SST -- large erase sizes are "overlays", "sectors" are 4K */
{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
@@ -2173,6 +2135,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_macronix,
&spi_nor_micron,
&spi_nor_st,
+ &spi_nor_spansion,
};

static const struct flash_info *
@@ -3106,17 +3069,6 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
}

-static void spansion_post_sfdp_fixups(struct spi_nor *nor)
-{
- if (nor->params.size <= SZ_16M)
- return;
-
- 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;
-}
-
static void s3an_post_sfdp_fixups(struct spi_nor *nor)
{
nor->params.setup = s3an_nor_setup;
@@ -3134,15 +3086,6 @@ static void s3an_post_sfdp_fixups(struct spi_nor *nor)
*/
static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
{
- switch (JEDEC_MFR(nor->info)) {
- case SNOR_MFR_SPANSION:
- spansion_post_sfdp_fixups(nor);
- break;
-
- default:
- break;
- }
-
if (nor->info->flags & SPI_S3AN)
s3an_post_sfdp_fixups(nor);

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7e3ec8e4ef34..8e45617578f3 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -178,6 +178,7 @@ extern const struct spi_nor_manufacturer spi_nor_issi;
extern const struct spi_nor_manufacturer spi_nor_macronix;
extern const struct spi_nor_manufacturer spi_nor_micron;
extern const struct spi_nor_manufacturer spi_nor_st;
+extern const struct spi_nor_manufacturer spi_nor_spansion;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
new file mode 100644
index 000000000000..16683983a20e
--- /dev/null
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info spansion_parts[] = {
+ /* Spansion/Cypress -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
+ */
+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ USE_CLSR) },
+ { "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ USE_CLSR) },
+ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ USE_CLSR) },
+ { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | USE_CLSR) },
+ { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ USE_CLSR) },
+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
+ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
+ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
+ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ USE_CLSR) },
+ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ USE_CLSR) },
+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
+ { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+ { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
+ { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) },
+ { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "s25fl064l", INFO(0x016017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES) },
+ { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES) },
+ { "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES) },
+};
+
+static void spansion_post_sfdp_fixups(struct spi_nor *nor)
+{
+ if (nor->params.size <= SZ_16M)
+ return;
+
+ 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;
+}
+
+static const struct spi_nor_fixups spansion_fixups = {
+ .post_sfdp = spansion_post_sfdp_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_spansion = {
+ .name = "spansion",
+ .parts = spansion_parts,
+ .nparts = ARRAY_SIZE(spansion_parts),
+ .fixups = &spansion_fixups,
+};
--
2.23.0

2020-03-02 18:10:17

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 18/23] mtd: spi-nor: Move Winbond bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Winbond chips, and move the
Winbond definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 115 +---------------------------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/winbond.c | 113 +++++++++++++++++++++++++++++++++
4 files changed, 116 insertions(+), 114 deletions(-)
create mode 100644 drivers/mtd/spi-nor/winbond.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index ef7afc654a15..33b6f834a14f 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -13,4 +13,5 @@ spi-nor-objs += macronix.o
spi-nor-objs += micron-st.o
spi-nor-objs += spansion.o
spi-nor-objs += sst.o
+spi-nor-objs += winbond.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 9ff0b09887b4..c99f063b0781 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -487,38 +487,6 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
return ret;
}

-/**
- * winbond_set_4byte() - Set 4-byte address mode for Winbond flashes.
- * @nor: pointer to 'struct spi_nor'.
- * @enable: true to enter the 4-byte address mode, false to exit the 4-byte
- * address mode.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int winbond_set_4byte(struct spi_nor *nor, bool enable)
-{
- int ret;
-
- ret = spi_nor_en4_ex4_set_4byte(nor, enable);
- if (ret || enable)
- return ret;
-
- /*
- * On Winbond W25Q256FV, leaving 4byte mode causes the Extended Address
- * Register to be set to 1, so all 3-byte-address reads come from the
- * second 16M. We must clear the register to enable normal behavior.
- */
- ret = spi_nor_write_enable(nor);
- if (ret)
- return ret;
-
- ret = spi_nor_write_ear(nor, 0);
- if (ret)
- return ret;
-
- return spi_nor_write_disable(nor);
-}
-
/**
* spi_nor_xread_sr() - Read the Status Register on S3AN flashes.
* @nor: pointer to 'struct spi_nor'.
@@ -2017,73 +1985,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
- { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
- { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
- { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
- { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
- { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
- {
- "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
- {
- "w25q16jv-im/jm", INFO(0xef7015, 0, 64 * 1024, 32,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) },
- { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) },
- { "w25q20ew", INFO(0xef6012, 0, 64 * 1024, 4, SECT_4K) },
- { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
- {
- "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "w25q32jv", INFO(0xef7016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "w25q32jwm", INFO(0xef8016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
- { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- {
- "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "w25q128jv", INFO(0xef7018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_4B_OPCODES) },
- { "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
- SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) },
-
/* Catalyst / On Semiconductor -- non-JEDEC */
{ "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
{ "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
@@ -2118,6 +2019,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_st,
&spi_nor_spansion,
&spi_nor_sst,
+ &spi_nor_winbond,
};

static const struct flash_info *
@@ -2811,11 +2713,6 @@ static int spi_nor_setup(struct spi_nor *nor,
return nor->params.setup(nor, hwcaps);
}

-static void winbond_set_default_init(struct spi_nor *nor)
-{
- nor->params.set_4byte = winbond_set_4byte;
-}
-
/**
* spi_nor_manufacturer_init_params() - Initialize the flash's parameters and
* settings based on MFR register and ->default_init() hook.
@@ -2823,16 +2720,6 @@ static void winbond_set_default_init(struct spi_nor *nor)
*/
static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
- /* Init flash parameters based on MFR */
- switch (JEDEC_MFR(nor->info)) {
- case SNOR_MFR_WINBOND:
- winbond_set_default_init(nor);
- break;
-
- default:
- break;
- }
-
if (nor->manufacturer && nor->manufacturer->fixups &&
nor->manufacturer->fixups->default_init)
nor->manufacturer->fixups->default_init(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7bc0f6a15b36..01e0b8e2b191 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -180,6 +180,7 @@ extern const struct spi_nor_manufacturer spi_nor_micron;
extern const struct spi_nor_manufacturer spi_nor_st;
extern const struct spi_nor_manufacturer spi_nor_spansion;
extern const struct spi_nor_manufacturer spi_nor_sst;
+extern const struct spi_nor_manufacturer spi_nor_winbond;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
new file mode 100644
index 000000000000..1e77dffbf729
--- /dev/null
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info winbond_parts[] = {
+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+ { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
+ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
+ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
+ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
+ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
+ { "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
+ { "w25q16jv-im/jm", INFO(0xef7015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+ SPI_NOR_HAS_TB) },
+ { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) },
+ { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) },
+ { "w25q20ew", INFO(0xef6012, 0, 64 * 1024, 4, SECT_4K) },
+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
+ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "w25q32jv", INFO(0xef7016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
+ { "w25q32jwm", INFO(0xef8016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+ { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "w25q128jv", INFO(0xef7018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
+ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES) },
+ { "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) },
+};
+
+/**
+ * winbond_set_4byte() - Set 4-byte address mode for Winbond flashes.
+ * @nor: pointer to 'struct spi_nor'.
+ * @enable: true to enter the 4-byte address mode, false to exit the 4-byte
+ * address mode.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int winbond_set_4byte(struct spi_nor *nor, bool enable)
+{
+ int ret;
+
+ ret = spi_nor_en4_ex4_set_4byte(nor, enable);
+ if (ret || enable)
+ return ret;
+
+ /*
+ * On Winbond W25Q256FV, leaving 4byte mode causes the Extended Address
+ * Register to be set to 1, so all 3-byte-address reads come from the
+ * second 16M. We must clear the register to enable normal behavior.
+ */
+ ret = spi_nor_write_enable(nor);
+ if (ret)
+ return ret;
+
+ ret = spi_nor_write_ear(nor, 0);
+ if (ret)
+ return ret;
+
+ return spi_nor_write_disable(nor);
+}
+
+static void winbond_default_init(struct spi_nor *nor)
+{
+ nor->params.set_4byte = winbond_set_4byte;
+}
+
+static const struct spi_nor_fixups winbond_fixups = {
+ .default_init = winbond_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_winbond = {
+ .name = "winbond",
+ .parts = winbond_parts,
+ .nparts = ARRAY_SIZE(winbond_parts),
+ .fixups = &winbond_fixups,
+};
+
--
2.23.0

2020-03-02 18:10:24

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 11/23] mtd: spi-nor: Move GigaDevice bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for GigaDevice chips, and move the
GigaDevice definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 60 +-------------------------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/gigadevice.c | 59 +++++++++++++++++++++++++++++++
4 files changed, 62 insertions(+), 59 deletions(-)
create mode 100644 drivers/mtd/spi-nor/gigadevice.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index ca6222d98b0f..38f704be4b03 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -6,4 +6,5 @@ spi-nor-objs += eon.o
spi-nor-objs += esmt.o
spi-nor-objs += everspin.o
spi-nor-objs += fujitsu.o
+spi-nor-objs += gigadevice.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 3f3955bbbb70..8520423b1104 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2052,21 +2052,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
.post_bfpt = mx25l25635_post_bfpt_fixups,
};

-static void gd25q256_default_init(struct spi_nor *nor)
-{
- /*
- * Some manufacturer like GigaDevice may use different
- * bit to set QE on different memories, so the MFR can't
- * indicate the quad_enable method for this case, we need
- * to set it in the default_init fixup hook.
- */
- nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
-}
-
-static struct spi_nor_fixups gd25q256_fixups = {
- .default_init = gd25q256_default_init,
-};
-
/* NOTE: double check command sets and memory organization when you add
* more nor chips. This current list focusses on newer chips, which
* have been converging on command sets which including JEDEC ID.
@@ -2079,50 +2064,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* GigaDevice */
- {
- "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25lq128d", INFO(0xc86018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
- SPI_NOR_TB_SR_BIT6)
- .fixups = &gd25q256_fixups,
- },
-
/* Intel/Numonyx -- xxxs33b */
{ "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
{ "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
@@ -2428,6 +2369,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_esmt,
&spi_nor_everspin,
&spi_nor_fujitsu,
+ &spi_nor_gigadevice,
};

static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 1b9f7402e5ff..c44802a05532 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -172,6 +172,7 @@ extern const struct spi_nor_manufacturer spi_nor_eon;
extern const struct spi_nor_manufacturer spi_nor_esmt;
extern const struct spi_nor_manufacturer spi_nor_everspin;
extern const struct spi_nor_manufacturer spi_nor_fujitsu;
+extern const struct spi_nor_manufacturer spi_nor_gigadevice;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
new file mode 100644
index 000000000000..7930e4490dab
--- /dev/null
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static void gd25q256_default_init(struct spi_nor *nor)
+{
+ /*
+ * Some manufacturer like GigaDevice may use different
+ * bit to set QE on different memories, so the MFR can't
+ * indicate the quad_enable method for this case, we need
+ * to set it in the default_init fixup hook.
+ */
+ nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+}
+
+static struct spi_nor_fixups gd25q256_fixups = {
+ .default_init = gd25q256_default_init,
+};
+
+static const struct flash_info gigadevice_parts[] = {
+ { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "gd25lq128d", INFO(0xc86018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+ { "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK |
+ SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6)
+ .fixups = &gd25q256_fixups },
+};
+
+const struct spi_nor_manufacturer spi_nor_gigadevice = {
+ .name = "gigadevice",
+ .parts = gigadevice_parts,
+ .nparts = ARRAY_SIZE(gigadevice_parts),
+};
--
2.23.0

2020-03-02 18:10:33

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 12/23] mtd: spi-nor: Move Intel bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Intel chips, and move the
Intel definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 15 +--------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/intel.c | 32 ++++++++++++++++++++++++++++++++
4 files changed, 35 insertions(+), 14 deletions(-)
create mode 100644 drivers/mtd/spi-nor/intel.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 38f704be4b03..8eb741a27fa7 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -7,4 +7,5 @@ spi-nor-objs += esmt.o
spi-nor-objs += everspin.o
spi-nor-objs += fujitsu.o
spi-nor-objs += gigadevice.o
+spi-nor-objs += intel.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8520423b1104..2f47852a3a01 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2064,11 +2064,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* Intel/Numonyx -- xxxs33b */
- { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
- { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
- { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
-
/* ISSI */
{ "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) },
{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8,
@@ -2370,6 +2365,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_everspin,
&spi_nor_fujitsu,
&spi_nor_gigadevice,
+ &spi_nor_intel,
};

static const struct flash_info *
@@ -3149,11 +3145,6 @@ static int spi_nor_setup(struct spi_nor *nor,
return nor->params.setup(nor, hwcaps);
}

-static void intel_set_default_init(struct spi_nor *nor)
-{
- nor->flags |= SNOR_F_HAS_LOCK;
-}
-
static void issi_set_default_init(struct spi_nor *nor)
{
nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
@@ -3192,10 +3183,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
/* Init flash parameters based on MFR */
switch (JEDEC_MFR(nor->info)) {
- case SNOR_MFR_INTEL:
- intel_set_default_init(nor);
- break;
-
case SNOR_MFR_ISSI:
issi_set_default_init(nor);
break;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index c44802a05532..c4c23efaa68b 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -173,6 +173,7 @@ extern const struct spi_nor_manufacturer spi_nor_esmt;
extern const struct spi_nor_manufacturer spi_nor_everspin;
extern const struct spi_nor_manufacturer spi_nor_fujitsu;
extern const struct spi_nor_manufacturer spi_nor_gigadevice;
+extern const struct spi_nor_manufacturer spi_nor_intel;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/intel.c b/drivers/mtd/spi-nor/intel.c
new file mode 100644
index 000000000000..d8196f101368
--- /dev/null
+++ b/drivers/mtd/spi-nor/intel.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info intel_parts[] = {
+ /* Intel/Numonyx -- xxxs33b */
+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
+};
+
+static void intel_default_init(struct spi_nor *nor)
+{
+ nor->flags |= SNOR_F_HAS_LOCK;
+}
+
+static const struct spi_nor_fixups intel_fixups = {
+ .default_init = intel_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_intel = {
+ .name = "intel",
+ .parts = intel_parts,
+ .nparts = ARRAY_SIZE(intel_parts),
+ .fixups = &intel_fixups,
+};
--
2.23.0

2020-03-02 18:10:37

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 17/23] mtd: spi-nor: Move SST bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for SST chips, and move the
SST definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 123 +---------------------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/sst.c | 151 +++++++++++++++++++++++++++++++++++
4 files changed, 156 insertions(+), 120 deletions(-)
create mode 100644 drivers/mtd/spi-nor/sst.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index cb06ee50bf68..ef7afc654a15 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -12,4 +12,5 @@ spi-nor-objs += issi.o
spi-nor-objs += macronix.o
spi-nor-objs += micron-st.o
spi-nor-objs += spansion.o
+spi-nor-objs += sst.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 448717543d1e..9ff0b09887b4 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2017,25 +2017,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* SST -- large erase sizes are "overlays", "sectors" are 4K */
- { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
- { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
- { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) },
- { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) },
- { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) },
- { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) },
- { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) },
- { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) },
- { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) },
- { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
- { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
- { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
- { "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K |
- SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32, SECT_4K |
- SPI_NOR_DUAL_READ) },
- { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-
/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
{ "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
{ "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
@@ -2136,6 +2117,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_micron,
&spi_nor_st,
&spi_nor_spansion,
+ &spi_nor_sst,
};

static const struct flash_info *
@@ -2236,92 +2218,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
return ret;
}

-static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
-{
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- size_t actual = 0;
- int ret;
-
- dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
-
- ret = spi_nor_lock_and_prep(nor);
- if (ret)
- return ret;
-
- ret = spi_nor_write_enable(nor);
- if (ret)
- goto out;
-
- nor->sst_write_second = false;
-
- /* Start write from odd address. */
- if (to % 2) {
- nor->program_opcode = SPINOR_OP_BP;
-
- /* write one byte. */
- ret = spi_nor_write_data(nor, to, 1, buf);
- if (ret < 0)
- goto out;
- WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- goto out;
-
- to++;
- actual++;
- }
-
- /* Write out most of the data here. */
- for (; actual < len - 1; actual += 2) {
- nor->program_opcode = SPINOR_OP_AAI_WP;
-
- /* write two bytes. */
- ret = spi_nor_write_data(nor, to, 2, buf + actual);
- if (ret < 0)
- goto out;
- WARN(ret != 2, "While writing 2 bytes written %i bytes\n", ret);
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- goto out;
- to += 2;
- nor->sst_write_second = true;
- }
- nor->sst_write_second = false;
-
- ret = spi_nor_write_disable(nor);
- if (ret)
- goto out;
-
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- goto out;
-
- /* Write out trailing byte if it exists. */
- if (actual != len) {
- ret = spi_nor_write_enable(nor);
- if (ret)
- goto out;
-
- nor->program_opcode = SPINOR_OP_BP;
- ret = spi_nor_write_data(nor, to, 1, buf + actual);
- if (ret < 0)
- goto out;
- WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- goto out;
-
- actual += 1;
-
- ret = spi_nor_write_disable(nor);
- }
-out:
- *retlen += actual;
- spi_nor_unlock_and_unprep(nor);
- return ret;
-}
-
/*
* Write an address range to the nor chip. Data must be written in
* FLASH_PAGESIZE chunks. The address range may be any size provided
@@ -2915,11 +2811,6 @@ static int spi_nor_setup(struct spi_nor *nor,
return nor->params.setup(nor, hwcaps);
}

-static void sst_set_default_init(struct spi_nor *nor)
-{
- nor->flags |= SNOR_F_HAS_LOCK;
-}
-
static void winbond_set_default_init(struct spi_nor *nor)
{
nor->params.set_4byte = winbond_set_4byte;
@@ -2934,10 +2825,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
/* Init flash parameters based on MFR */
switch (JEDEC_MFR(nor->info)) {
- case SNOR_MFR_SST:
- sst_set_default_init(nor);
- break;
-
case SNOR_MFR_WINBOND:
winbond_set_default_init(nor);
break;
@@ -3409,6 +3296,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
if (info->flags & SPI_NOR_HAS_LOCK)
nor->flags |= SNOR_F_HAS_LOCK;

+ mtd->_write = spi_nor_write;
+
/* Init flash parameters based on flash_info struct and SFDP */
spi_nor_init_params(nor);

@@ -3429,12 +3318,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
mtd->_is_locked = spi_nor_is_locked;
}

- /* sst nor chips use AAI word program */
- if (info->flags & SST_WRITE)
- mtd->_write = sst_write;
- else
- mtd->_write = spi_nor_write;
-
if (info->flags & USE_FSR)
nor->flags |= SNOR_F_USE_FSR;
if (info->flags & SPI_NOR_HAS_TB) {
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 8e45617578f3..7bc0f6a15b36 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -179,6 +179,7 @@ extern const struct spi_nor_manufacturer spi_nor_macronix;
extern const struct spi_nor_manufacturer spi_nor_micron;
extern const struct spi_nor_manufacturer spi_nor_st;
extern const struct spi_nor_manufacturer spi_nor_spansion;
+extern const struct spi_nor_manufacturer spi_nor_sst;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
new file mode 100644
index 000000000000..e0af6d25d573
--- /dev/null
+++ b/drivers/mtd/spi-nor/sst.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info sst_parts[] = {
+ /* SST -- large erase sizes are "overlays", "sectors" are 4K */
+ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8,
+ SECT_4K | SST_WRITE) },
+ { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16,
+ SECT_4K | SST_WRITE) },
+ { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32,
+ SECT_4K | SST_WRITE) },
+ { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64,
+ SECT_4K | SST_WRITE) },
+ { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) },
+ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1,
+ SECT_4K | SST_WRITE) },
+ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2,
+ SECT_4K | SST_WRITE) },
+ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4,
+ SECT_4K | SST_WRITE) },
+ { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) },
+ { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
+ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8,
+ SECT_4K | SST_WRITE) },
+ { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16,
+ SECT_4K | SST_WRITE) },
+ { "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+ { "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ) },
+ { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+};
+
+static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ size_t actual = 0;
+ int ret;
+
+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+
+ ret = spi_nor_lock_and_prep(nor);
+ if (ret)
+ return ret;
+
+ ret = spi_nor_write_enable(nor);
+ if (ret)
+ goto out;
+
+ nor->sst_write_second = false;
+
+ /* Start write from odd address. */
+ if (to % 2) {
+ nor->program_opcode = SPINOR_OP_BP;
+
+ /* write one byte. */
+ ret = spi_nor_write_data(nor, to, 1, buf);
+ if (ret < 0)
+ goto out;
+ WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto out;
+
+ to++;
+ actual++;
+ }
+
+ /* Write out most of the data here. */
+ for (; actual < len - 1; actual += 2) {
+ nor->program_opcode = SPINOR_OP_AAI_WP;
+
+ /* write two bytes. */
+ ret = spi_nor_write_data(nor, to, 2, buf + actual);
+ if (ret < 0)
+ goto out;
+ WARN(ret != 2, "While writing 2 bytes written %i bytes\n", ret);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto out;
+ to += 2;
+ nor->sst_write_second = true;
+ }
+ nor->sst_write_second = false;
+
+ ret = spi_nor_write_disable(nor);
+ if (ret)
+ goto out;
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto out;
+
+ /* Write out trailing byte if it exists. */
+ if (actual != len) {
+ ret = spi_nor_write_enable(nor);
+ if (ret)
+ goto out;
+
+ nor->program_opcode = SPINOR_OP_BP;
+ ret = spi_nor_write_data(nor, to, 1, buf + actual);
+ if (ret < 0)
+ goto out;
+ WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto out;
+
+ actual += 1;
+
+ ret = spi_nor_write_disable(nor);
+ }
+out:
+ *retlen += actual;
+ spi_nor_unlock_and_unprep(nor);
+ return ret;
+}
+
+static void sst_default_init(struct spi_nor *nor)
+{
+ nor->flags |= SNOR_F_HAS_LOCK;
+}
+
+static void sst_post_sfdp_fixups(struct spi_nor *nor)
+{
+ if (nor->info->flags & SST_WRITE)
+ nor->mtd._write = sst_write;
+}
+
+static const struct spi_nor_fixups sst_fixups = {
+ .default_init = sst_default_init,
+ .post_sfdp = sst_post_sfdp_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_sst = {
+ .name = "sst",
+ .parts = sst_parts,
+ .nparts = ARRAY_SIZE(sst_parts),
+ .fixups = &sst_fixups,
+};
--
2.23.0

2020-03-02 18:23:34

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 22/23] mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table

From: Boris Brezillon <[email protected]>

All entries have been moved to manufacturer drivers. Get rid of this
empty table.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/core.c | 25 -------------------------
1 file changed, 25 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index f4178cd65c45..a2e1917b608d 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1953,21 +1953,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
return 0;
}

-/* NOTE: double check command sets and memory organization when you add
- * more nor chips. This current list focusses on newer chips, which
- * have been converging on command sets which including JEDEC ID.
- *
- * All newly added entries should describe *hardware* and should use SECT_4K
- * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage
- * scenarios excluding small sectors there is config option that can be
- * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS.
- * For historical (and compatibility) reasons (before we got above config) some
- * old entries may be missing 4K flag.
- */
-static const struct flash_info spi_nor_ids[] = {
- { },
-};
-
static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_atmel,
&spi_nor_catalyst,
@@ -2037,11 +2022,6 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
}
}

- info = spi_nor_search_part_by_id(spi_nor_ids,
- ARRAY_SIZE(spi_nor_ids) - 1, id);
- if (info)
- return info;
-
dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
SPI_NOR_MAX_ID_LEN, id);
return ERR_PTR(-ENODEV);
@@ -2952,11 +2932,6 @@ static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
{
unsigned int i, j;

- for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) {
- if (!strcmp(name, spi_nor_ids[i].name))
- return &spi_nor_ids[i];
- }
-
for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
for (j = 0; j < manufacturers[i]->nparts; j++) {
if (!strcmp(name, manufacturers[i]->parts[j].name)) {
--
2.23.0

2020-03-02 18:23:53

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 19/23] mtd: spi-nor: Move Catalyst bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Catalyst chips, and move the
Catalyst definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/catalyst.c | 29 +++++++++++++++++++++++++++++
drivers/mtd/spi-nor/core.c | 8 +-------
drivers/mtd/spi-nor/core.h | 1 +
4 files changed, 32 insertions(+), 7 deletions(-)
create mode 100644 drivers/mtd/spi-nor/catalyst.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 33b6f834a14f..cd8d95b727c9 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -2,6 +2,7 @@

spi-nor-objs := core.o sfdp.o
spi-nor-objs += atmel.o
+spi-nor-objs += catalyst.o
spi-nor-objs += eon.o
spi-nor-objs += esmt.o
spi-nor-objs += everspin.o
diff --git a/drivers/mtd/spi-nor/catalyst.c b/drivers/mtd/spi-nor/catalyst.c
new file mode 100644
index 000000000000..011b83e99e95
--- /dev/null
+++ b/drivers/mtd/spi-nor/catalyst.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info catalyst_parts[] = {
+ /* Catalyst / On Semiconductor -- non-JEDEC */
+ { "cat25c11", CAT25_INFO(16, 8, 16, 1,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c03", CAT25_INFO(32, 8, 16, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c09", CAT25_INFO(128, 8, 32, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c17", CAT25_INFO(256, 8, 32, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25128", CAT25_INFO(2048, 8, 64, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+};
+
+const struct spi_nor_manufacturer spi_nor_catalyst = {
+ .name = "catalyst",
+ .parts = catalyst_parts,
+ .nparts = ARRAY_SIZE(catalyst_parts),
+};
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index c99f063b0781..1776fb8eb66b 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1985,13 +1985,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* Catalyst / On Semiconductor -- non-JEDEC */
- { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-
/* Xilinx S3AN Internal Flash */
{ "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
{ "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
@@ -2007,6 +2000,7 @@ static const struct flash_info spi_nor_ids[] = {

static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_atmel,
+ &spi_nor_catalyst,
&spi_nor_eon,
&spi_nor_esmt,
&spi_nor_everspin,
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 01e0b8e2b191..9eb46900bc72 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -168,6 +168,7 @@ struct spi_nor_manufacturer {

/* Manufacturer drivers. */
extern const struct spi_nor_manufacturer spi_nor_atmel;
+extern const struct spi_nor_manufacturer spi_nor_catalyst;
extern const struct spi_nor_manufacturer spi_nor_eon;
extern const struct spi_nor_manufacturer spi_nor_esmt;
extern const struct spi_nor_manufacturer spi_nor_everspin;
--
2.23.0

2020-03-02 18:24:14

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 21/23] mtd: spi-nor: Move XMC bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for XMC chips, and move the
XMC definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 4 +---
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/xmc.c | 23 +++++++++++++++++++++++
4 files changed, 26 insertions(+), 3 deletions(-)
create mode 100644 drivers/mtd/spi-nor/xmc.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index fa03513dd160..7ddb742de1fe 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -16,4 +16,5 @@ spi-nor-objs += spansion.o
spi-nor-objs += sst.o
spi-nor-objs += winbond.o
spi-nor-objs += xilinx.o
+spi-nor-objs += xmc.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 3e9f6bafa01b..f4178cd65c45 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1965,9 +1965,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */
- { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ },
};

@@ -1988,6 +1985,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_sst,
&spi_nor_winbond,
&spi_nor_xilinx,
+ &spi_nor_xmc,
};

static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index abd5332afaf5..3541a84c03d8 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -173,6 +173,7 @@ extern const struct spi_nor_manufacturer spi_nor_spansion;
extern const struct spi_nor_manufacturer spi_nor_sst;
extern const struct spi_nor_manufacturer spi_nor_winbond;
extern const struct spi_nor_manufacturer spi_nor_xilinx;
+extern const struct spi_nor_manufacturer spi_nor_xmc;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/xmc.c b/drivers/mtd/spi-nor/xmc.c
new file mode 100644
index 000000000000..2c7773b68993
--- /dev/null
+++ b/drivers/mtd/spi-nor/xmc.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info xmc_parts[] = {
+ /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */
+ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+};
+
+const struct spi_nor_manufacturer spi_nor_xmc = {
+ .name = "xmc",
+ .parts = xmc_parts,
+ .nparts = ARRAY_SIZE(xmc_parts),
+};
--
2.23.0

2020-03-02 18:24:15

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 20/23] mtd: spi-nor: Move Xilinx bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Xilinx chips, and move the
Xilinx definitions outside of core.c.

While at it, remove the SPI_S3AN flag which is now useless.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 76 +----------------------------
drivers/mtd/spi-nor/core.h | 13 +----
drivers/mtd/spi-nor/xilinx.c | 94 ++++++++++++++++++++++++++++++++++++
4 files changed, 98 insertions(+), 86 deletions(-)
create mode 100644 drivers/mtd/spi-nor/xilinx.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index cd8d95b727c9..fa03513dd160 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -15,4 +15,5 @@ spi-nor-objs += micron-st.o
spi-nor-objs += spansion.o
spi-nor-objs += sst.o
spi-nor-objs += winbond.o
+spi-nor-objs += xilinx.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 1776fb8eb66b..3e9f6bafa01b 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1117,26 +1117,6 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)
mutex_unlock(&nor->lock);
}

-/*
- * This code converts an address to the Default Address Mode, that has non
- * power of two page sizes. We must support this mode because it is the default
- * mode supported by Xilinx tools, it can access the whole flash area and
- * changing over to the Power-of-two mode is irreversible and corrupts the
- * original data.
- * Addr can safely be unsigned int, the biggest S3AN device is smaller than
- * 4 MiB.
- */
-static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr)
-{
- u32 offset, page;
-
- offset = addr % nor->page_size;
- page = addr / nor->page_size;
- page <<= (nor->page_size > 512) ? 10 : 9;
-
- return page | offset;
-}
-
static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
{
if (!nor->params.convert_addr)
@@ -1985,13 +1965,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* Xilinx S3AN Internal Flash */
- { "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
- { "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
- { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
- { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
- { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
-
/* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */
{ "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
@@ -2014,6 +1987,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_spansion,
&spi_nor_sst,
&spi_nor_winbond,
+ &spi_nor_xilinx,
};

static const struct flash_info *
@@ -2199,46 +2173,6 @@ static int spi_nor_check(struct spi_nor *nor)
return 0;
}

-static int s3an_nor_setup(struct spi_nor *nor,
- const struct spi_nor_hwcaps *hwcaps)
-{
- int ret;
-
- ret = spi_nor_xread_sr(nor, nor->bouncebuf);
- if (ret)
- return ret;
-
- nor->erase_opcode = SPINOR_OP_XSE;
- nor->program_opcode = SPINOR_OP_XPP;
- nor->read_opcode = SPINOR_OP_READ;
- nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
-
- /*
- * This flashes have a page size of 264 or 528 bytes (known as
- * Default addressing mode). It can be changed to a more standard
- * Power of two mode where the page size is 256/512. This comes
- * with a price: there is 3% less of space, the data is corrupted
- * and the page size cannot be changed back to default addressing
- * mode.
- *
- * The current addressing mode can be read from the XRDSR register
- * and should not be changed, because is a destructive operation.
- */
- if (nor->bouncebuf[0] & XSR_PAGESIZE) {
- /* Flash in Power of 2 mode */
- nor->page_size = (nor->page_size == 264) ? 256 : 512;
- nor->mtd.writebufsize = nor->page_size;
- nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
- nor->mtd.erasesize = 8 * nor->page_size;
- } else {
- /* Flash in Default addressing mode */
- nor->params.convert_addr = s3an_convert_addr;
- nor->mtd.erasesize = nor->info->sector_size;
- }
-
- return 0;
-}
-
static void
spi_nor_set_read_settings(struct spi_nor_read_command *read,
u8 num_mode_clocks,
@@ -2837,11 +2771,6 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
}

-static void s3an_post_sfdp_fixups(struct spi_nor *nor)
-{
- nor->params.setup = s3an_nor_setup;
-}
-
/**
* spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
* after SFDP has been parsed (is also called for SPI NORs that do not
@@ -2854,9 +2783,6 @@ static void s3an_post_sfdp_fixups(struct spi_nor *nor)
*/
static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
{
- if (nor->info->flags & SPI_S3AN)
- s3an_post_sfdp_fixups(nor);
-
if (nor->manufacturer && nor->manufacturer->fixups &&
nor->manufacturer->fixups->post_sfdp)
nor->manufacturer->fixups->post_sfdp(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 9eb46900bc72..abd5332afaf5 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -73,16 +73,6 @@ struct flash_info {
#define SPI_NOR_XSR_RDY BIT(10) /*
* S3AN flashes have specific opcode to
* read the status register.
- * Flags SPI_NOR_XSR_RDY and SPI_S3AN
- * use the same bit as one implies the
- * other, but we will get rid of
- * SPI_S3AN soon.
- */
-#define SPI_S3AN BIT(10) /*
- * Xilinx Spartan 3AN In-System Flash
- * (MFR cannot be used for probing
- * because it has the same value as
- * ATMEL flashes)
*/
#define SPI_NOR_4B_OPCODES BIT(11) /*
* Use dedicated 4byte address op codes
@@ -150,7 +140,7 @@ struct flash_info {
.n_sectors = (_n_sectors), \
.page_size = _page_size, \
.addr_width = 3, \
- .flags = SPI_NOR_NO_FR | SPI_S3AN,
+ .flags = SPI_NOR_NO_FR | SPI_NOR_XSR_RDY,

/**
* struct spi_nor_manufacturer - SPI NOR manufacturer object
@@ -182,6 +172,7 @@ extern const struct spi_nor_manufacturer spi_nor_st;
extern const struct spi_nor_manufacturer spi_nor_spansion;
extern const struct spi_nor_manufacturer spi_nor_sst;
extern const struct spi_nor_manufacturer spi_nor_winbond;
+extern const struct spi_nor_manufacturer spi_nor_xilinx;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
new file mode 100644
index 000000000000..fcf635d89f65
--- /dev/null
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info xilinx_parts[] = {
+ /* Xilinx S3AN Internal Flash */
+ { "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
+ { "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
+ { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
+ { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
+ { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
+};
+
+/*
+ * This code converts an address to the Default Address Mode, that has non
+ * power of two page sizes. We must support this mode because it is the default
+ * mode supported by Xilinx tools, it can access the whole flash area and
+ * changing over to the Power-of-two mode is irreversible and corrupts the
+ * original data.
+ * Addr can safely be unsigned int, the biggest S3AN device is smaller than
+ * 4 MiB.
+ */
+static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr)
+{
+ u32 offset, page;
+
+ offset = addr % nor->page_size;
+ page = addr / nor->page_size;
+ page <<= (nor->page_size > 512) ? 10 : 9;
+
+ return page | offset;
+}
+
+static int xilinx_nor_setup(struct spi_nor *nor,
+ const struct spi_nor_hwcaps *hwcaps)
+{
+ int ret;
+
+ ret = spi_nor_xread_sr(nor, nor->bouncebuf);
+ if (ret)
+ return ret;
+
+ nor->erase_opcode = SPINOR_OP_XSE;
+ nor->program_opcode = SPINOR_OP_XPP;
+ nor->read_opcode = SPINOR_OP_READ;
+ nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
+
+ /*
+ * This flashes have a page size of 264 or 528 bytes (known as
+ * Default addressing mode). It can be changed to a more standard
+ * Power of two mode where the page size is 256/512. This comes
+ * with a price: there is 3% less of space, the data is corrupted
+ * and the page size cannot be changed back to default addressing
+ * mode.
+ *
+ * The current addressing mode can be read from the XRDSR register
+ * and should not be changed, because is a destructive operation.
+ */
+ if (nor->bouncebuf[0] & XSR_PAGESIZE) {
+ /* Flash in Power of 2 mode */
+ nor->page_size = (nor->page_size == 264) ? 256 : 512;
+ nor->mtd.writebufsize = nor->page_size;
+ nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
+ nor->mtd.erasesize = 8 * nor->page_size;
+ } else {
+ /* Flash in Default addressing mode */
+ nor->params.convert_addr = s3an_convert_addr;
+ nor->mtd.erasesize = nor->info->sector_size;
+ }
+
+ return 0;
+}
+
+static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
+{
+ nor->params.setup = xilinx_nor_setup;
+}
+
+static const struct spi_nor_fixups xilinx_fixups = {
+ .post_sfdp = xilinx_post_sfdp_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_xilinx = {
+ .name = "xilinx",
+ .parts = xilinx_parts,
+ .nparts = ARRAY_SIZE(xilinx_parts),
+ .fixups = &xilinx_fixups,
+};
--
2.23.0

2020-03-02 18:53:45

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 15/23] mtd: spi-nor: Move Micron/ST bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Micron/ST chips, and move the
Micron/ST definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 98 +-----------------------
drivers/mtd/spi-nor/core.h | 2 +
drivers/mtd/spi-nor/micron-st.c | 129 ++++++++++++++++++++++++++++++++
4 files changed, 134 insertions(+), 96 deletions(-)
create mode 100644 drivers/mtd/spi-nor/micron-st.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index c94798987801..c7e5fb908bec 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -10,4 +10,5 @@ spi-nor-objs += gigadevice.o
spi-nor-objs += intel.o
spi-nor-objs += issi.o
spi-nor-objs += macronix.o
+spi-nor-objs += micron-st.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 9d0e0fc5af45..8d54dfe33cdc 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2017,53 +2017,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* Micron <--> ST Micro */
- { "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K |
- USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K |
- USE_FSR | SPI_NOR_QUAD_READ) },
- { "mt25ql256a", INFO6(0x20ba19, 0x104400, 64 * 1024, 512,
- SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
- SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K |
- USE_FSR | SPI_NOR_DUAL_READ |
- SPI_NOR_QUAD_READ) },
- { "mt25qu256a", INFO6(0x20bb19, 0x104400, 64 * 1024, 512,
- SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
- SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K |
- USE_FSR | SPI_NOR_QUAD_READ) },
- { "mt25ql512a", INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
- SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
- SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
- { "mt25qu512a", INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
- SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
- SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K |
- USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
- { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
- { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096,
- SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
- NO_CHIP_ERASE) },
- { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
-
- /* Micron */
- {
- "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
- SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
- SPI_NOR_4B_OPCODES)
- },
- { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
- SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
- SPI_NOR_4B_OPCODES) },
-
/* Spansion/Cypress -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
@@ -2121,42 +2074,6 @@ static const struct flash_info spi_nor_ids[] = {
SPI_NOR_DUAL_READ) },
{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },

- /* ST Microelectronics -- newer production may have feature updates */
- { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
- { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) },
- { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) },
- { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) },
- { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) },
- { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) },
- { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
- { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
- { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
-
- { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
- { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
- { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) },
- { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) },
- { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) },
- { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) },
- { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) },
- { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) },
- { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) },
-
- { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) },
- { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) },
- { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) },
-
- { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) },
- { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) },
- { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) },
-
- { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) },
- { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) },
- { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) },
-
/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
{ "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
{ "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
@@ -2254,6 +2171,8 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_intel,
&spi_nor_issi,
&spi_nor_macronix,
+ &spi_nor_micron,
+ &spi_nor_st,
};

static const struct flash_info *
@@ -3038,14 +2957,6 @@ static void sst_set_default_init(struct spi_nor *nor)
nor->flags |= SNOR_F_HAS_LOCK;
}

-static void st_micron_set_default_init(struct spi_nor *nor)
-{
- nor->flags |= SNOR_F_HAS_LOCK;
- nor->flags &= ~SNOR_F_HAS_16BIT_SR;
- nor->params.quad_enable = NULL;
- nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
-}
-
static void winbond_set_default_init(struct spi_nor *nor)
{
nor->params.set_4byte = winbond_set_4byte;
@@ -3060,11 +2971,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
/* Init flash parameters based on MFR */
switch (JEDEC_MFR(nor->info)) {
- case SNOR_MFR_ST:
- case SNOR_MFR_MICRON:
- st_micron_set_default_init(nor);
- break;
-
case SNOR_MFR_SST:
sst_set_default_init(nor);
break;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 9af3a701de95..7e3ec8e4ef34 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -176,6 +176,8 @@ extern const struct spi_nor_manufacturer spi_nor_gigadevice;
extern const struct spi_nor_manufacturer spi_nor_intel;
extern const struct spi_nor_manufacturer spi_nor_issi;
extern const struct spi_nor_manufacturer spi_nor_macronix;
+extern const struct spi_nor_manufacturer spi_nor_micron;
+extern const struct spi_nor_manufacturer spi_nor_st;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
new file mode 100644
index 000000000000..8017ca58b3a5
--- /dev/null
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info micron_parts[] = {
+ { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
+ SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+ SPI_NOR_4B_OPCODES) },
+ { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
+ SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+ SPI_NOR_4B_OPCODES) },
+};
+
+static const struct flash_info st_parts[] = {
+ { "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_QUAD_READ) },
+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ) },
+ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ) },
+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ) },
+ { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ) },
+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+ { "mt25ql256a", INFO6(0x20ba19, 0x104400, 64 * 1024, 512,
+ SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K |
+ USE_FSR | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+ { "mt25qu256a", INFO6(0x20bb19, 0x104400, 64 * 1024, 512,
+ SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+ { "mt25ql512a", INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
+ SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+ { "mt25qu512a", INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
+ SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+ NO_CHIP_ERASE) },
+ { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+ NO_CHIP_ERASE) },
+ { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+ NO_CHIP_ERASE) },
+ { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+ NO_CHIP_ERASE) },
+
+ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
+ { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) },
+ { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) },
+ { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) },
+ { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) },
+ { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) },
+ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
+ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
+ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
+
+ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
+ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
+ { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) },
+ { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) },
+ { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) },
+ { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) },
+ { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) },
+ { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) },
+ { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) },
+
+ { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) },
+ { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) },
+ { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) },
+
+ { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) },
+ { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) },
+ { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) },
+
+ { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) },
+ { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) },
+ { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) },
+ { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) },
+ { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) },
+ { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) },
+};
+
+static void micron_st_default_init(struct spi_nor *nor)
+{
+ nor->flags |= SNOR_F_HAS_LOCK;
+ nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+ nor->params.quad_enable = NULL;
+ nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
+}
+
+static const struct spi_nor_fixups micron_st_fixups = {
+ .default_init = micron_st_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_micron = {
+ .name = "micron",
+ .parts = micron_parts,
+ .nparts = ARRAY_SIZE(micron_parts),
+ .fixups = &micron_st_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_st = {
+ .name = "st",
+ .parts = st_parts,
+ .nparts = ARRAY_SIZE(st_parts),
+ .fixups = &micron_st_fixups,
+};
--
2.23.0

2020-03-02 18:55:07

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h

From: Tudor Ambarus <[email protected]>

The SPI NOR controllers drivers must not be able to use structures that
are meant just for the SPI NOR core.

struct spi_nor_flash_parameter is filled at run-time with info gathered
from flash_info, manufacturer and sfdp data. struct spi_nor_flash_parameter
should be opaque to the SPI NOR controller drivers, make sure it is.

spi_nor_option_flags, spi_nor_read_command, spi_nor_pp_command,
spi_nor_read_command_index and spi_nor_pp_command_index are defined for the
core use, make sure they are opaque to the SPI NOR controller drivers.

Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/core.c | 86 ++++++----
drivers/mtd/spi-nor/core.h | 214 +++++++++++++++++++++++++
drivers/mtd/spi-nor/gigadevice.c | 2 +-
drivers/mtd/spi-nor/issi.c | 2 +-
drivers/mtd/spi-nor/macronix.c | 4 +-
drivers/mtd/spi-nor/micron-st.c | 4 +-
drivers/mtd/spi-nor/sfdp.c | 10 ++
drivers/mtd/spi-nor/spansion.c | 2 +-
drivers/mtd/spi-nor/winbond.c | 2 +-
drivers/mtd/spi-nor/xilinx.c | 4 +-
include/linux/mtd/spi-nor.h | 259 +------------------------------
11 files changed, 294 insertions(+), 295 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index a2e1917b608d..860dac1dff90 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -802,7 +802,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
ret = spi_nor_read_cr(nor, &sr_cr[1]);
if (ret)
return ret;
- } else if (nor->params.quad_enable) {
+ } else if (nor->params->quad_enable) {
/*
* If the Status Register 2 Read command (35h) is not
* supported, we should at least be sure we don't
@@ -810,7 +810,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
*
* We can safely assume that when the Quad Enable method is
* set, the value of the QE bit is one, as a consequence of the
- * nor->params.quad_enable() call.
+ * nor->params->quad_enable() call.
*
* We can safely assume that the Quad Enable bit is present in
* the Status Register 2 at BIT(1). According to the JESD216
@@ -1075,6 +1075,11 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
ARRAY_SIZE(spi_nor_3to4_erase));
}

+static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
+{
+ return !!nor->params->erase_map.uniform_erase_type;
+}
+
static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
{
nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
@@ -1082,7 +1087,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);

if (!spi_nor_has_uniform_erase(nor)) {
- struct spi_nor_erase_map *map = &nor->params.erase_map;
+ struct spi_nor_erase_map *map = &nor->params->erase_map;
struct spi_nor_erase_type *erase;
int i;

@@ -1119,10 +1124,10 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)

static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
{
- if (!nor->params.convert_addr)
+ if (!nor->params->convert_addr)
return addr;

- return nor->params.convert_addr(nor, addr);
+ return nor->params->convert_addr(nor, addr);
}

/*
@@ -1227,6 +1232,16 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
return NULL;
}

+static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region)
+{
+ return region->offset & SNOR_LAST_REGION;
+}
+
+static u64 spi_nor_region_end(const struct spi_nor_erase_region *region)
+{
+ return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
+}
+
/**
* spi_nor_region_next() - get the next spi nor region
* @region: pointer to a structure that describes a SPI NOR erase region
@@ -1331,7 +1346,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
struct list_head *erase_list,
u64 addr, u32 len)
{
- const struct spi_nor_erase_map *map = &nor->params.erase_map;
+ const struct spi_nor_erase_map *map = &nor->params->erase_map;
const struct spi_nor_erase_type *erase, *prev_erase = NULL;
struct spi_nor_erase_region *region;
struct spi_nor_erase_command *cmd = NULL;
@@ -1817,7 +1832,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
if (ret)
return ret;

- ret = nor->params.locking_ops->lock(nor, ofs, len);
+ ret = nor->params->locking_ops->lock(nor, ofs, len);

spi_nor_unlock_and_unprep(nor);
return ret;
@@ -1832,7 +1847,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
if (ret)
return ret;

- ret = nor->params.locking_ops->unlock(nor, ofs, len);
+ ret = nor->params->locking_ops->unlock(nor, ofs, len);

spi_nor_unlock_and_unprep(nor);
return ret;
@@ -1847,7 +1862,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
if (ret)
return ret;

- ret = nor->params.locking_ops->is_locked(nor, ofs, len);
+ ret = nor->params->locking_ops->is_locked(nor, ofs, len);

spi_nor_unlock_and_unprep(nor);
return ret;
@@ -2312,7 +2327,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor,
static void
spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
{
- struct spi_nor_flash_parameter *params = &nor->params;
+ struct spi_nor_flash_parameter *params = nor->params;
unsigned int cap;

/* DTR modes are not supported yet, mask them all. */
@@ -2411,7 +2426,7 @@ static int spi_nor_select_read(struct spi_nor *nor,
if (cmd < 0)
return -EINVAL;

- read = &nor->params.reads[cmd];
+ read = &nor->params->reads[cmd];
nor->read_opcode = read->opcode;
nor->read_proto = read->proto;

@@ -2442,7 +2457,7 @@ static int spi_nor_select_pp(struct spi_nor *nor,
if (cmd < 0)
return -EINVAL;

- pp = &nor->params.page_programs[cmd];
+ pp = &nor->params->page_programs[cmd];
nor->program_opcode = pp->opcode;
nor->write_proto = pp->proto;
return 0;
@@ -2503,7 +2518,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,

static int spi_nor_select_erase(struct spi_nor *nor)
{
- struct spi_nor_erase_map *map = &nor->params.erase_map;
+ struct spi_nor_erase_map *map = &nor->params->erase_map;
const struct spi_nor_erase_type *erase = NULL;
struct mtd_info *mtd = &nor->mtd;
u32 wanted_size = nor->info->sector_size;
@@ -2552,7 +2567,7 @@ static int spi_nor_select_erase(struct spi_nor *nor)
static int spi_nor_default_setup(struct spi_nor *nor,
const struct spi_nor_hwcaps *hwcaps)
{
- struct spi_nor_flash_parameter *params = &nor->params;
+ struct spi_nor_flash_parameter *params = nor->params;
u32 ignored_mask, shared_mask;
int err;

@@ -2613,10 +2628,10 @@ static int spi_nor_default_setup(struct spi_nor *nor,
static int spi_nor_setup(struct spi_nor *nor,
const struct spi_nor_hwcaps *hwcaps)
{
- if (!nor->params.setup)
+ if (!nor->params->setup)
return 0;

- return nor->params.setup(nor, hwcaps);
+ return nor->params->setup(nor, hwcaps);
}

/**
@@ -2646,13 +2661,13 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
{
struct spi_nor_flash_parameter sfdp_params;

- memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
+ memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));

if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
nor->addr_width = 0;
nor->flags &= ~SNOR_F_4B_OPCODES;
} else {
- memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
+ memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
}
}

@@ -2663,7 +2678,7 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
*/
static void spi_nor_info_init_params(struct spi_nor *nor)
{
- struct spi_nor_flash_parameter *params = &nor->params;
+ struct spi_nor_flash_parameter *params = nor->params;
struct spi_nor_erase_map *map = &params->erase_map;
const struct flash_info *info = nor->info;
struct device_node *np = spi_nor_get_flash_node(nor);
@@ -2782,8 +2797,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
* NOR protection support. When locking_ops are not provided, we pick
* the default ones.
*/
- if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
- nor->params.locking_ops = &spi_nor_sr_locking_ops;
+ if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
+ nor->params->locking_ops = &spi_nor_sr_locking_ops;
}

/**
@@ -2823,8 +2838,12 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
* ->default_init() hook or the SFDP parser do not set specific params.
* spi_nor_late_init_params()
*/
-static void spi_nor_init_params(struct spi_nor *nor)
+static int spi_nor_init_params(struct spi_nor *nor)
{
+ nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
+ if (!nor->params)
+ return -ENOMEM;
+
spi_nor_info_init_params(nor);

spi_nor_manufacturer_init_params(nor);
@@ -2836,6 +2855,8 @@ static void spi_nor_init_params(struct spi_nor *nor)
spi_nor_post_sfdp_fixups(nor);

spi_nor_late_init_params(nor);
+
+ return 0;
}

/**
@@ -2846,14 +2867,14 @@ static void spi_nor_init_params(struct spi_nor *nor)
*/
static int spi_nor_quad_enable(struct spi_nor *nor)
{
- if (!nor->params.quad_enable)
+ if (!nor->params->quad_enable)
return 0;

if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
spi_nor_get_protocol_width(nor->write_proto) == 4))
return 0;

- return nor->params.quad_enable(nor);
+ return nor->params->quad_enable(nor);
}

/**
@@ -2868,7 +2889,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor)
static int spi_nor_unlock_all(struct spi_nor *nor)
{
if (nor->flags & SNOR_F_HAS_LOCK)
- return spi_nor_unlock(&nor->mtd, 0, nor->params.size);
+ return spi_nor_unlock(&nor->mtd, 0, nor->params->size);

return 0;
}
@@ -2899,7 +2920,7 @@ static int spi_nor_init(struct spi_nor *nor)
*/
WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
"enabling reset hack; may not recover from unexpected reboots\n");
- nor->params.set_4byte(nor, true);
+ nor->params->set_4byte(nor, true);
}

return 0;
@@ -2923,7 +2944,7 @@ void spi_nor_restore(struct spi_nor *nor)
/* restore the addressing mode */
if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
nor->flags & SNOR_F_BROKEN_RESET)
- nor->params.set_4byte(nor, false);
+ nor->params->set_4byte(nor, false);
}
EXPORT_SYMBOL_GPL(spi_nor_restore);

@@ -3028,7 +3049,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
struct device *dev = nor->dev;
struct mtd_info *mtd = &nor->mtd;
struct device_node *np = spi_nor_get_flash_node(nor);
- struct spi_nor_flash_parameter *params = &nor->params;
int ret;
int i;

@@ -3079,7 +3099,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
mtd->_write = spi_nor_write;

/* Init flash parameters based on flash_info struct and SFDP */
- spi_nor_init_params(nor);
+ ret = spi_nor_init_params(nor);
+ if (ret)
+ return ret;

if (!mtd->name)
mtd->name = dev_name(dev);
@@ -3087,12 +3109,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
mtd->type = MTD_NORFLASH;
mtd->writesize = 1;
mtd->flags = MTD_CAP_NORFLASH;
- mtd->size = params->size;
+ mtd->size = nor->params->size;
mtd->_erase = spi_nor_erase;
mtd->_read = spi_nor_read;
mtd->_resume = spi_nor_resume;

- if (nor->params.locking_ops) {
+ if (nor->params->locking_ops) {
mtd->_lock = spi_nor_lock;
mtd->_unlock = spi_nor_unlock;
mtd->_is_locked = spi_nor_is_locked;
@@ -3115,7 +3137,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
mtd->flags |= MTD_NO_ERASE;

mtd->dev.parent = dev;
- nor->page_size = params->page_size;
+ nor->page_size = nor->params->page_size;
mtd->writebufsize = nor->page_size;

if (of_property_read_bool(np, "broken-flash-reset"))
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 3541a84c03d8..7654b6f3b966 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -11,6 +11,220 @@

#define SPI_NOR_MAX_ID_LEN 6

+enum spi_nor_option_flags {
+ SNOR_F_USE_FSR = BIT(0),
+ SNOR_F_HAS_SR_TB = BIT(1),
+ SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
+ SNOR_F_READY_XSR_RDY = BIT(3),
+ SNOR_F_USE_CLSR = BIT(4),
+ SNOR_F_BROKEN_RESET = BIT(5),
+ SNOR_F_4B_OPCODES = BIT(6),
+ SNOR_F_HAS_4BAIT = BIT(7),
+ SNOR_F_HAS_LOCK = BIT(8),
+ SNOR_F_HAS_16BIT_SR = BIT(9),
+ SNOR_F_NO_READ_CR = BIT(10),
+ SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
+};
+
+struct spi_nor_read_command {
+ u8 num_mode_clocks;
+ u8 num_wait_states;
+ u8 opcode;
+ enum spi_nor_protocol proto;
+};
+
+struct spi_nor_pp_command {
+ u8 opcode;
+ enum spi_nor_protocol proto;
+};
+
+enum spi_nor_read_command_index {
+ SNOR_CMD_READ,
+ SNOR_CMD_READ_FAST,
+ SNOR_CMD_READ_1_1_1_DTR,
+
+ /* Dual SPI */
+ SNOR_CMD_READ_1_1_2,
+ SNOR_CMD_READ_1_2_2,
+ SNOR_CMD_READ_2_2_2,
+ SNOR_CMD_READ_1_2_2_DTR,
+
+ /* Quad SPI */
+ SNOR_CMD_READ_1_1_4,
+ SNOR_CMD_READ_1_4_4,
+ SNOR_CMD_READ_4_4_4,
+ SNOR_CMD_READ_1_4_4_DTR,
+
+ /* Octal SPI */
+ SNOR_CMD_READ_1_1_8,
+ SNOR_CMD_READ_1_8_8,
+ SNOR_CMD_READ_8_8_8,
+ SNOR_CMD_READ_1_8_8_DTR,
+
+ SNOR_CMD_READ_MAX
+};
+
+enum spi_nor_pp_command_index {
+ SNOR_CMD_PP,
+
+ /* Quad SPI */
+ SNOR_CMD_PP_1_1_4,
+ SNOR_CMD_PP_1_4_4,
+ SNOR_CMD_PP_4_4_4,
+
+ /* Octal SPI */
+ SNOR_CMD_PP_1_1_8,
+ SNOR_CMD_PP_1_8_8,
+ SNOR_CMD_PP_8_8_8,
+
+ SNOR_CMD_PP_MAX
+};
+
+/**
+ * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
+ * @size: the size of the sector/block erased by the erase type.
+ * JEDEC JESD216B imposes erase sizes to be a power of 2.
+ * @size_shift: @size is a power of 2, the shift is stored in
+ * @size_shift.
+ * @size_mask: the size mask based on @size_shift.
+ * @opcode: the SPI command op code to erase the sector/block.
+ * @idx: Erase Type index as sorted in the Basic Flash Parameter
+ * Table. It will be used to synchronize the supported
+ * Erase Types with the ones identified in the SFDP
+ * optional tables.
+ */
+struct spi_nor_erase_type {
+ u32 size;
+ u32 size_shift;
+ u32 size_mask;
+ u8 opcode;
+ u8 idx;
+};
+
+/**
+ * struct spi_nor_erase_command - Used for non-uniform erases
+ * The structure is used to describe a list of erase commands to be executed
+ * once we validate that the erase can be performed. The elements in the list
+ * are run-length encoded.
+ * @list: for inclusion into the list of erase commands.
+ * @count: how many times the same erase command should be
+ * consecutively used.
+ * @size: the size of the sector/block erased by the command.
+ * @opcode: the SPI command op code to erase the sector/block.
+ */
+struct spi_nor_erase_command {
+ struct list_head list;
+ u32 count;
+ u32 size;
+ u8 opcode;
+};
+
+/**
+ * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
+ * @offset: the offset in the data array of erase region start.
+ * LSB bits are used as a bitmask encoding flags to
+ * determine if this region is overlaid, if this region is
+ * the last in the SPI NOR flash memory and to indicate
+ * all the supported erase commands inside this region.
+ * The erase types are sorted in ascending order with the
+ * smallest Erase Type size being at BIT(0).
+ * @size: the size of the region in bytes.
+ */
+struct spi_nor_erase_region {
+ u64 offset;
+ u64 size;
+};
+
+#define SNOR_ERASE_TYPE_MAX 4
+#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
+
+#define SNOR_LAST_REGION BIT(4)
+#define SNOR_OVERLAID_REGION BIT(5)
+
+#define SNOR_ERASE_FLAGS_MAX 6
+#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
+
+/**
+ * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
+ * @regions: array of erase regions. The regions are consecutive in
+ * address space. Walking through the regions is done
+ * incrementally.
+ * @uniform_region: a pre-allocated erase region for SPI NOR with a uniform
+ * sector size (legacy implementation).
+ * @erase_type: an array of erase types shared by all the regions.
+ * The erase types are sorted in ascending order, with the
+ * smallest Erase Type size being the first member in the
+ * erase_type array.
+ * @uniform_erase_type: bitmask encoding erase types that can erase the
+ * entire memory. This member is completed at init by
+ * uniform and non-uniform SPI NOR flash memories if they
+ * support at least one erase type that can erase the
+ * entire memory.
+ */
+struct spi_nor_erase_map {
+ struct spi_nor_erase_region *regions;
+ struct spi_nor_erase_region uniform_region;
+ struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX];
+ u8 uniform_erase_type;
+};
+
+/**
+ * struct spi_nor_locking_ops - SPI NOR locking methods
+ * @lock: lock a region of the SPI NOR.
+ * @unlock: unlock a region of the SPI NOR.
+ * @is_locked: check if a region of the SPI NOR is completely locked
+ */
+struct spi_nor_locking_ops {
+ int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+ int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+ int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+};
+
+/**
+ * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
+ * Includes legacy flash parameters and settings that can be overwritten
+ * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
+ * Serial Flash Discoverable Parameters (SFDP) tables.
+ *
+ * @size: the flash memory density in bytes.
+ * @page_size: the page size of the SPI NOR flash memory.
+ * @hwcaps: describes the read and page program hardware
+ * capabilities.
+ * @reads: read capabilities ordered by priority: the higher index
+ * in the array, the higher priority.
+ * @page_programs: page program capabilities ordered by priority: the
+ * higher index in the array, the higher priority.
+ * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
+ * Table.
+ * @quad_enable: enables SPI NOR quad mode.
+ * @set_4byte: puts the SPI NOR in 4 byte addressing mode.
+ * @convert_addr: converts an absolute address into something the flash
+ * will understand. Particularly useful when pagesize is
+ * not a power-of-2.
+ * @setup: configures the SPI NOR memory. Useful for SPI NOR
+ * flashes that have peculiarities to the SPI NOR standard
+ * e.g. different opcodes, specific address calculation,
+ * page size, etc.
+ * @locking_ops: SPI NOR locking methods.
+ */
+struct spi_nor_flash_parameter {
+ u64 size;
+ u32 page_size;
+
+ struct spi_nor_hwcaps hwcaps;
+ struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
+ struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
+
+ struct spi_nor_erase_map erase_map;
+
+ int (*quad_enable)(struct spi_nor *nor);
+ int (*set_4byte)(struct spi_nor *nor, bool enable);
+ u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
+ int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
+
+ const struct spi_nor_locking_ops *locking_ops;
+};
+
/**
* struct spi_nor_fixups - SPI NOR fixup hooks
* @default_init: called after default flash parameters init. Used to tweak
diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
index 7930e4490dab..447d84bb2128 100644
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -16,7 +16,7 @@ static void gd25q256_default_init(struct spi_nor *nor)
* indicate the quad_enable method for this case, we need
* to set it in the default_init fixup hook.
*/
- nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+ nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
}

static struct spi_nor_fixups gd25q256_fixups = {
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index 3a1c34c41388..ffcb60e54a80 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -68,7 +68,7 @@ static const struct flash_info issi_parts[] = {

static void issi_default_init(struct spi_nor *nor)
{
- nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+ nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
}

static const struct spi_nor_fixups issi_fixups = {
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index 1ae609c44676..d73bd0363144 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -82,8 +82,8 @@ static const struct flash_info macronix_parts[] = {

static void macronix_default_init(struct spi_nor *nor)
{
- nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
- nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
+ nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
+ nor->params->set_4byte = spi_nor_en4_ex4_set_4byte;
}

static const struct spi_nor_fixups macronix_fixups = {
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 8017ca58b3a5..5be817d2f27c 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -106,8 +106,8 @@ static void micron_st_default_init(struct spi_nor *nor)
{
nor->flags |= SNOR_F_HAS_LOCK;
nor->flags &= ~SNOR_F_HAS_16BIT_SR;
- nor->params.quad_enable = NULL;
- nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
+ nor->params->quad_enable = NULL;
+ nor->params->set_4byte = spi_nor_en4_ex4_wen_set_4byte;
}

static const struct spi_nor_fixups micron_st_fixups = {
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index b790c3ec871f..6829dc7e4f74 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -734,6 +734,16 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
return ret;
}

+static void spi_nor_region_mark_end(struct spi_nor_erase_region *region)
+{
+ region->offset |= SNOR_LAST_REGION;
+}
+
+static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
+{
+ region->offset |= SNOR_OVERLAID_REGION;
+}
+
/**
* spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
* @region: pointer to a structure that describes a SPI NOR erase region
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 16683983a20e..6756202ace4b 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -74,7 +74,7 @@ static const struct flash_info spansion_parts[] = {

static void spansion_post_sfdp_fixups(struct spi_nor *nor)
{
- if (nor->params.size <= SZ_16M)
+ if (nor->params->size <= SZ_16M)
return;

nor->flags |= SNOR_F_4B_OPCODES;
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index 1e77dffbf729..f15be50024d1 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -97,7 +97,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)

static void winbond_default_init(struct spi_nor *nor)
{
- nor->params.set_4byte = winbond_set_4byte;
+ nor->params->set_4byte = winbond_set_4byte;
}

static const struct spi_nor_fixups winbond_fixups = {
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
index fcf635d89f65..1138bdbf4199 100644
--- a/drivers/mtd/spi-nor/xilinx.c
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -70,7 +70,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
nor->mtd.erasesize = 8 * nor->page_size;
} else {
/* Flash in Default addressing mode */
- nor->params.convert_addr = s3an_convert_addr;
+ nor->params->convert_addr = s3an_convert_addr;
nor->mtd.erasesize = nor->info->sector_size;
}

@@ -79,7 +79,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,

static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
{
- nor->params.setup = xilinx_nor_setup;
+ nor->params->setup = xilinx_nor_setup;
}

static const struct spi_nor_fixups xilinx_fixups = {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index dde2988a809e..d3d34c4eea48 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -227,110 +227,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
return spi_nor_get_protocol_data_nbits(proto);
}

-enum spi_nor_option_flags {
- SNOR_F_USE_FSR = BIT(0),
- SNOR_F_HAS_SR_TB = BIT(1),
- SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
- SNOR_F_READY_XSR_RDY = BIT(3),
- SNOR_F_USE_CLSR = BIT(4),
- SNOR_F_BROKEN_RESET = BIT(5),
- SNOR_F_4B_OPCODES = BIT(6),
- SNOR_F_HAS_4BAIT = BIT(7),
- SNOR_F_HAS_LOCK = BIT(8),
- SNOR_F_HAS_16BIT_SR = BIT(9),
- SNOR_F_NO_READ_CR = BIT(10),
- SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
-
-};
-
-/**
- * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
- * @size: the size of the sector/block erased by the erase type.
- * JEDEC JESD216B imposes erase sizes to be a power of 2.
- * @size_shift: @size is a power of 2, the shift is stored in
- * @size_shift.
- * @size_mask: the size mask based on @size_shift.
- * @opcode: the SPI command op code to erase the sector/block.
- * @idx: Erase Type index as sorted in the Basic Flash Parameter
- * Table. It will be used to synchronize the supported
- * Erase Types with the ones identified in the SFDP
- * optional tables.
- */
-struct spi_nor_erase_type {
- u32 size;
- u32 size_shift;
- u32 size_mask;
- u8 opcode;
- u8 idx;
-};
-
-/**
- * struct spi_nor_erase_command - Used for non-uniform erases
- * The structure is used to describe a list of erase commands to be executed
- * once we validate that the erase can be performed. The elements in the list
- * are run-length encoded.
- * @list: for inclusion into the list of erase commands.
- * @count: how many times the same erase command should be
- * consecutively used.
- * @size: the size of the sector/block erased by the command.
- * @opcode: the SPI command op code to erase the sector/block.
- */
-struct spi_nor_erase_command {
- struct list_head list;
- u32 count;
- u32 size;
- u8 opcode;
-};
-
-/**
- * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
- * @offset: the offset in the data array of erase region start.
- * LSB bits are used as a bitmask encoding flags to
- * determine if this region is overlaid, if this region is
- * the last in the SPI NOR flash memory and to indicate
- * all the supported erase commands inside this region.
- * The erase types are sorted in ascending order with the
- * smallest Erase Type size being at BIT(0).
- * @size: the size of the region in bytes.
- */
-struct spi_nor_erase_region {
- u64 offset;
- u64 size;
-};
-
-#define SNOR_ERASE_TYPE_MAX 4
-#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
-
-#define SNOR_LAST_REGION BIT(4)
-#define SNOR_OVERLAID_REGION BIT(5)
-
-#define SNOR_ERASE_FLAGS_MAX 6
-#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
-
-/**
- * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
- * @regions: array of erase regions. The regions are consecutive in
- * address space. Walking through the regions is done
- * incrementally.
- * @uniform_region: a pre-allocated erase region for SPI NOR with a uniform
- * sector size (legacy implementation).
- * @erase_type: an array of erase types shared by all the regions.
- * The erase types are sorted in ascending order, with the
- * smallest Erase Type size being the first member in the
- * erase_type array.
- * @uniform_erase_type: bitmask encoding erase types that can erase the
- * entire memory. This member is completed at init by
- * uniform and non-uniform SPI NOR flash memories if they
- * support at least one erase type that can erase the
- * entire memory.
- */
-struct spi_nor_erase_map {
- struct spi_nor_erase_region *regions;
- struct spi_nor_erase_region uniform_region;
- struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX];
- u8 uniform_erase_type;
-};
-
/**
* struct spi_nor_hwcaps - Structure for describing the hardware capabilies
* supported by the SPI controller (bus master).
@@ -406,61 +302,7 @@ struct spi_nor_hwcaps {
#define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \
SNOR_HWCAPS_PP_MASK)

-struct spi_nor_read_command {
- u8 num_mode_clocks;
- u8 num_wait_states;
- u8 opcode;
- enum spi_nor_protocol proto;
-};
-
-struct spi_nor_pp_command {
- u8 opcode;
- enum spi_nor_protocol proto;
-};
-
-enum spi_nor_read_command_index {
- SNOR_CMD_READ,
- SNOR_CMD_READ_FAST,
- SNOR_CMD_READ_1_1_1_DTR,
-
- /* Dual SPI */
- SNOR_CMD_READ_1_1_2,
- SNOR_CMD_READ_1_2_2,
- SNOR_CMD_READ_2_2_2,
- SNOR_CMD_READ_1_2_2_DTR,
-
- /* Quad SPI */
- SNOR_CMD_READ_1_1_4,
- SNOR_CMD_READ_1_4_4,
- SNOR_CMD_READ_4_4_4,
- SNOR_CMD_READ_1_4_4_DTR,
-
- /* Octal SPI */
- SNOR_CMD_READ_1_1_8,
- SNOR_CMD_READ_1_8_8,
- SNOR_CMD_READ_8_8_8,
- SNOR_CMD_READ_1_8_8_DTR,
-
- SNOR_CMD_READ_MAX
-};
-
-enum spi_nor_pp_command_index {
- SNOR_CMD_PP,
-
- /* Quad SPI */
- SNOR_CMD_PP_1_1_4,
- SNOR_CMD_PP_1_4_4,
- SNOR_CMD_PP_4_4_4,
-
- /* Octal SPI */
- SNOR_CMD_PP_1_1_8,
- SNOR_CMD_PP_1_8_8,
- SNOR_CMD_PP_8_8_8,
-
- SNOR_CMD_PP_MAX
-};
-
-/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
+/* Forward declaration that is used in 'struct spi_nor_controller_ops' */
struct spi_nor;

/**
@@ -491,74 +333,14 @@ struct spi_nor_controller_ops {
int (*erase)(struct spi_nor *nor, loff_t offs);
};

-/**
- * struct spi_nor_locking_ops - SPI NOR locking methods
- * @lock: lock a region of the SPI NOR.
- * @unlock: unlock a region of the SPI NOR.
- * @is_locked: check if a region of the SPI NOR is completely locked
- */
-struct spi_nor_locking_ops {
- int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
- int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
- int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
-};
-
-/**
- * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
- * Includes legacy flash parameters and settings that can be overwritten
- * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
- * Serial Flash Discoverable Parameters (SFDP) tables.
- *
- * @size: the flash memory density in bytes.
- * @page_size: the page size of the SPI NOR flash memory.
- * @hwcaps: describes the read and page program hardware
- * capabilities.
- * @reads: read capabilities ordered by priority: the higher index
- * in the array, the higher priority.
- * @page_programs: page program capabilities ordered by priority: the
- * higher index in the array, the higher priority.
- * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
- * Table.
- * @quad_enable: enables SPI NOR quad mode.
- * @set_4byte: puts the SPI NOR in 4 byte addressing mode.
- * @convert_addr: converts an absolute address into something the flash
- * will understand. Particularly useful when pagesize is
- * not a power-of-2.
- * @setup: configures the SPI NOR memory. Useful for SPI NOR
- * flashes that have peculiarities to the SPI NOR standard
- * e.g. different opcodes, specific address calculation,
- * page size, etc.
- * @locking_ops: SPI NOR locking methods.
- */
-struct spi_nor_flash_parameter {
- u64 size;
- u32 page_size;
-
- struct spi_nor_hwcaps hwcaps;
- struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
- struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];

- struct spi_nor_erase_map erase_map;
-
- int (*quad_enable)(struct spi_nor *nor);
- int (*set_4byte)(struct spi_nor *nor, bool enable);
- u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
- int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
-
- const struct spi_nor_locking_ops *locking_ops;
-};
-
-/**
- * struct flash_info - Forward declaration of a structure used internally by
- * spi_nor_scan()
+/*
+ * Forward declarations that are used internally by the core and manufacturer
+ * drivers.
*/
struct flash_info;
-
-/**
- * struct spi_nor_manufacturer - Forward declaration of a structure used
- * internally by the core and manufacturer drivers.
- */
struct spi_nor_manufacturer;
+struct spi_nor_flash_parameter;

/**
* struct spi_nor - Structure for defining a the SPI NOR layer
@@ -613,7 +395,7 @@ struct spi_nor {

const struct spi_nor_controller_ops *controller_ops;

- struct spi_nor_flash_parameter params;
+ struct spi_nor_flash_parameter *params;

struct {
struct spi_mem_dirmap_desc *rdesc;
@@ -623,35 +405,6 @@ struct spi_nor {
void *priv;
};

-static u64 __maybe_unused
-spi_nor_region_is_last(const struct spi_nor_erase_region *region)
-{
- return region->offset & SNOR_LAST_REGION;
-}
-
-static u64 __maybe_unused
-spi_nor_region_end(const struct spi_nor_erase_region *region)
-{
- return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
-}
-
-static void __maybe_unused
-spi_nor_region_mark_end(struct spi_nor_erase_region *region)
-{
- region->offset |= SNOR_LAST_REGION;
-}
-
-static void __maybe_unused
-spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
-{
- region->offset |= SNOR_OVERLAID_REGION;
-}
-
-static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
-{
- return !!nor->params.erase_map.uniform_erase_type;
-}
-
static inline void spi_nor_set_flash_node(struct spi_nor *nor,
struct device_node *np)
{
--
2.23.0

2020-03-02 19:09:54

by Tudor Ambarus

[permalink] [raw]
Subject: [PATCH 14/23] mtd: spi-nor: Move Macronix bits out of core.c

From: Boris Brezillon <[email protected]>

Create a SPI NOR manufacturer driver for Macronix chips, and move the
Macronix definitions outside of core.c.

Signed-off-by: Boris Brezillon <[email protected]>
Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/core.c | 69 +-----------------------
drivers/mtd/spi-nor/core.h | 1 +
drivers/mtd/spi-nor/macronix.c | 98 ++++++++++++++++++++++++++++++++++
4 files changed, 101 insertions(+), 68 deletions(-)
create mode 100644 drivers/mtd/spi-nor/macronix.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 5c849f104cc4..c94798987801 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -9,4 +9,5 @@ spi-nor-objs += fujitsu.o
spi-nor-objs += gigadevice.o
spi-nor-objs += intel.o
spi-nor-objs += issi.o
+spi-nor-objs += macronix.o
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index d781cb9af182..9d0e0fc5af45 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2005,31 +2005,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
return 0;
}

-static int
-mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
- const struct sfdp_parameter_header *bfpt_header,
- const struct sfdp_bfpt *bfpt,
- struct spi_nor_flash_parameter *params)
-{
- /*
- * MX25L25635F supports 4B opcodes but MX25L25635E does not.
- * Unfortunately, Macronix has re-used the same JEDEC ID for both
- * variants which prevents us from defining a new entry in the parts
- * table.
- * We need a way to differentiate MX25L25635E and MX25L25635F, and it
- * seems that the F version advertises support for Fast Read 4-4-4 in
- * its BFPT table.
- */
- if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
- nor->flags |= SNOR_F_4B_OPCODES;
-
- return 0;
-}
-
-static struct spi_nor_fixups mx25l25635_fixups = {
- .post_bfpt = mx25l25635_post_bfpt_fixups,
-};
-
/* NOTE: double check command sets and memory organization when you add
* more nor chips. This current list focusses on newer chips, which
* have been converging on command sets which including JEDEC ID.
@@ -2042,39 +2017,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
* old entries may be missing 4K flag.
*/
static const struct flash_info spi_nor_ids[] = {
- /* Macronix */
- { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) },
- { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
- { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
- { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
- { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
- { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
- { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
- { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) },
- { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) },
- { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) },
- { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
- { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
- { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
- SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
- .fixups = &mx25l25635_fixups },
- { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
- { "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
- { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
- { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
-
/* Micron <--> ST Micro */
{ "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) },
{ "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
@@ -2311,6 +2253,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
&spi_nor_gigadevice,
&spi_nor_intel,
&spi_nor_issi,
+ &spi_nor_macronix,
};

static const struct flash_info *
@@ -3090,12 +3033,6 @@ static int spi_nor_setup(struct spi_nor *nor,
return nor->params.setup(nor, hwcaps);
}

-static void macronix_set_default_init(struct spi_nor *nor)
-{
- nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
- nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
-}
-
static void sst_set_default_init(struct spi_nor *nor)
{
nor->flags |= SNOR_F_HAS_LOCK;
@@ -3123,10 +3060,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
/* Init flash parameters based on MFR */
switch (JEDEC_MFR(nor->info)) {
- case SNOR_MFR_MACRONIX:
- macronix_set_default_init(nor);
- break;
-
case SNOR_MFR_ST:
case SNOR_MFR_MICRON:
st_micron_set_default_init(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index b4ed9acbef63..9af3a701de95 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -175,6 +175,7 @@ extern const struct spi_nor_manufacturer spi_nor_fujitsu;
extern const struct spi_nor_manufacturer spi_nor_gigadevice;
extern const struct spi_nor_manufacturer spi_nor_intel;
extern const struct spi_nor_manufacturer spi_nor_issi;
+extern const struct spi_nor_manufacturer spi_nor_macronix;

int spi_nor_write_enable(struct spi_nor *nor);
int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
new file mode 100644
index 000000000000..1ae609c44676
--- /dev/null
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static int
+mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params)
+{
+ /*
+ * MX25L25635F supports 4B opcodes but MX25L25635E does not.
+ * Unfortunately, Macronix has re-used the same JEDEC ID for both
+ * variants which prevents us from defining a new entry in the parts
+ * table.
+ * We need a way to differentiate MX25L25635E and MX25L25635F, and it
+ * seems that the F version advertises support for Fast Read 4-4-4 in
+ * its BFPT table.
+ */
+ if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
+ nor->flags |= SNOR_F_4B_OPCODES;
+
+ return 0;
+}
+
+static struct spi_nor_fixups mx25l25635_fixups = {
+ .post_bfpt = mx25l25635_post_bfpt_fixups,
+};
+
+static const struct flash_info macronix_parts[] = {
+ /* Macronix */
+ { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) },
+ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
+ { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) },
+ { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+ { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) },
+ { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) },
+ { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
+ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
+ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
+ { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+ { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
+ .fixups = &mx25l25635_fixups },
+ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_4B_OPCODES) },
+ { "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_4B_OPCODES) },
+ { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048,
+ SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048,
+ SPI_NOR_QUAD_READ) },
+};
+
+static void macronix_default_init(struct spi_nor *nor)
+{
+ nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+ nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
+}
+
+static const struct spi_nor_fixups macronix_fixups = {
+ .default_init = macronix_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_macronix = {
+ .name = "macronix",
+ .parts = macronix_parts,
+ .nparts = ARRAY_SIZE(macronix_parts),
+ .fixups = &macronix_fixups,
+};
--
2.23.0

2020-03-03 07:16:16

by Joel Stanley

[permalink] [raw]
Subject: Re: [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core

Hi Tudor,

On Mon, 2 Mar 2020 at 18:07, <[email protected]> wrote:
>
> From: Tudor Ambarus <[email protected]>
>
> Hello,
>
> This patch series is an attempt at getting all manufacturer specific
> quirks/code out of the core to make the core logic more readable and
> thus ease maintainance.

I tried to apply this to linus' tree (5.6-rc4) but it had a bunch of
conflicts. What did you base this on?

2020-03-03 07:29:26

by Tudor Ambarus

[permalink] [raw]
Subject: Re: [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core

On Tuesday, March 3, 2020 9:15:31 AM EET Joel Stanley wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
>
> Hi Tudor,

Hi, Joel,

>
> On Mon, 2 Mar 2020 at 18:07, <[email protected]> wrote:
> > From: Tudor Ambarus <[email protected]>
> >
> > Hello,
> >
> > This patch series is an attempt at getting all manufacturer specific
> > quirks/code out of the core to make the core logic more readable and
> > thus ease maintainance.
>
> I tried to apply this to linus' tree (5.6-rc4) but it had a bunch of
> conflicts. What did you base this on?

T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git spi-
nor/next

Cheers,
ta

2020-03-03 10:23:25

by Mika Westerberg

[permalink] [raw]
Subject: Re: [PATCH 12/23] mtd: spi-nor: Move Intel bits out of core.c

On Mon, Mar 02, 2020 at 06:07:51PM +0000, [email protected] wrote:
> From: Boris Brezillon <[email protected]>
>
> Create a SPI NOR manufacturer driver for Intel chips, and move the
> Intel definitions outside of core.c.
>
> Signed-off-by: Boris Brezillon <[email protected]>
> Signed-off-by: Tudor Ambarus <[email protected]>

Reviewed-by: Mika Westerberg <[email protected]>

2020-03-04 07:21:58

by chenxiang (M)

[permalink] [raw]
Subject: Re: [PATCH 14/23] mtd: spi-nor: Move Macronix bits out of core.c

Hi,

在 2020/3/3 2:07, [email protected] 写道:
> From: Boris Brezillon <[email protected]>
>
> Create a SPI NOR manufacturer driver for Macronix chips, and move the
> Macronix definitions outside of core.c.

I have tested it with erase-wite-read-compare(1MB file) testcase on
mx25u12835f flash, it is ok. So add:
Tested-by: Xiang Chen <[email protected]>

>
> Signed-off-by: Boris Brezillon <[email protected]>
> Signed-off-by: Tudor Ambarus <[email protected]>
> ---
> drivers/mtd/spi-nor/Makefile | 1 +
> drivers/mtd/spi-nor/core.c | 69 +-----------------------
> drivers/mtd/spi-nor/core.h | 1 +
> drivers/mtd/spi-nor/macronix.c | 98 ++++++++++++++++++++++++++++++++++
> 4 files changed, 101 insertions(+), 68 deletions(-)
> create mode 100644 drivers/mtd/spi-nor/macronix.c
>
> diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
> index 5c849f104cc4..c94798987801 100644
> --- a/drivers/mtd/spi-nor/Makefile
> +++ b/drivers/mtd/spi-nor/Makefile
> @@ -9,4 +9,5 @@ spi-nor-objs += fujitsu.o
> spi-nor-objs += gigadevice.o
> spi-nor-objs += intel.o
> spi-nor-objs += issi.o
> +spi-nor-objs += macronix.o
> obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index d781cb9af182..9d0e0fc5af45 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2005,31 +2005,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
> return 0;
> }
>
> -static int
> -mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
> - const struct sfdp_parameter_header *bfpt_header,
> - const struct sfdp_bfpt *bfpt,
> - struct spi_nor_flash_parameter *params)
> -{
> - /*
> - * MX25L25635F supports 4B opcodes but MX25L25635E does not.
> - * Unfortunately, Macronix has re-used the same JEDEC ID for both
> - * variants which prevents us from defining a new entry in the parts
> - * table.
> - * We need a way to differentiate MX25L25635E and MX25L25635F, and it
> - * seems that the F version advertises support for Fast Read 4-4-4 in
> - * its BFPT table.
> - */
> - if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
> - nor->flags |= SNOR_F_4B_OPCODES;
> -
> - return 0;
> -}
> -
> -static struct spi_nor_fixups mx25l25635_fixups = {
> - .post_bfpt = mx25l25635_post_bfpt_fixups,
> -};
> -
> /* NOTE: double check command sets and memory organization when you add
> * more nor chips. This current list focusses on newer chips, which
> * have been converging on command sets which including JEDEC ID.
> @@ -2042,39 +2017,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
> * old entries may be missing 4K flag.
> */
> static const struct flash_info spi_nor_ids[] = {
> - /* Macronix */
> - { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) },
> - { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
> - { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
> - { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
> - { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
> - { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
> - { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
> - { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
> - { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) },
> - { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64,
> - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> - { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) },
> - { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) },
> - { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
> - { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
> - { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
> - { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
> - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> - { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
> - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> - { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
> - SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> - .fixups = &mx25l25635_fixups },
> - { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
> - { "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16,
> - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> - { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
> - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> - { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> - { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> - { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
> -
> /* Micron <--> ST Micro */
> { "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) },
> { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
> @@ -2311,6 +2253,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
> &spi_nor_gigadevice,
> &spi_nor_intel,
> &spi_nor_issi,
> + &spi_nor_macronix,
> };
>
> static const struct flash_info *
> @@ -3090,12 +3033,6 @@ static int spi_nor_setup(struct spi_nor *nor,
> return nor->params.setup(nor, hwcaps);
> }
>
> -static void macronix_set_default_init(struct spi_nor *nor)
> -{
> - nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> - nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> -}
> -
> static void sst_set_default_init(struct spi_nor *nor)
> {
> nor->flags |= SNOR_F_HAS_LOCK;
> @@ -3123,10 +3060,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
> {
> /* Init flash parameters based on MFR */
> switch (JEDEC_MFR(nor->info)) {
> - case SNOR_MFR_MACRONIX:
> - macronix_set_default_init(nor);
> - break;
> -
> case SNOR_MFR_ST:
> case SNOR_MFR_MICRON:
> st_micron_set_default_init(nor);
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index b4ed9acbef63..9af3a701de95 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -175,6 +175,7 @@ extern const struct spi_nor_manufacturer spi_nor_fujitsu;
> extern const struct spi_nor_manufacturer spi_nor_gigadevice;
> extern const struct spi_nor_manufacturer spi_nor_intel;
> extern const struct spi_nor_manufacturer spi_nor_issi;
> +extern const struct spi_nor_manufacturer spi_nor_macronix;
>
> int spi_nor_write_enable(struct spi_nor *nor);
> int spi_nor_write_disable(struct spi_nor *nor);
> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> new file mode 100644
> index 000000000000..1ae609c44676
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/macronix.c
> @@ -0,0 +1,98 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2005, Intec Automation Inc.
> + * Copyright (C) 2014, Freescale Semiconductor, Inc.
> + */
> +
> +#include <linux/mtd/spi-nor.h>
> +
> +#include "core.h"
> +
> +static int
> +mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
> + const struct sfdp_parameter_header *bfpt_header,
> + const struct sfdp_bfpt *bfpt,
> + struct spi_nor_flash_parameter *params)
> +{
> + /*
> + * MX25L25635F supports 4B opcodes but MX25L25635E does not.
> + * Unfortunately, Macronix has re-used the same JEDEC ID for both
> + * variants which prevents us from defining a new entry in the parts
> + * table.
> + * We need a way to differentiate MX25L25635E and MX25L25635F, and it
> + * seems that the F version advertises support for Fast Read 4-4-4 in
> + * its BFPT table.
> + */
> + if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
> + nor->flags |= SNOR_F_4B_OPCODES;
> +
> + return 0;
> +}
> +
> +static struct spi_nor_fixups mx25l25635_fixups = {
> + .post_bfpt = mx25l25635_post_bfpt_fixups,
> +};
> +
> +static const struct flash_info macronix_parts[] = {
> + /* Macronix */
> + { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) },
> + { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
> + { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
> + { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
> + { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
> + { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
> + { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
> + { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
> + { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) },
> + { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64,
> + SECT_4K | SPI_NOR_DUAL_READ |
> + SPI_NOR_QUAD_READ) },
> + { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) },
> + { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) },
> + { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
> + { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
> + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
> + { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
> + SECT_4K | SPI_NOR_DUAL_READ |
> + SPI_NOR_QUAD_READ) },
> + { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
> + SECT_4K | SPI_NOR_DUAL_READ |
> + SPI_NOR_QUAD_READ) },
> + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
> + SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> + .fixups = &mx25l25635_fixups },
> + { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
> + SECT_4K | SPI_NOR_4B_OPCODES) },
> + { "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16,
> + SECT_4K | SPI_NOR_DUAL_READ |
> + SPI_NOR_QUAD_READ) },
> + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
> + { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024,
> + SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> + SPI_NOR_4B_OPCODES) },
> + { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024,
> + SECT_4K | SPI_NOR_DUAL_READ |
> + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> + { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048,
> + SECT_4K | SPI_NOR_DUAL_READ |
> + SPI_NOR_QUAD_READ) },
> + { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048,
> + SPI_NOR_QUAD_READ) },
> +};
> +
> +static void macronix_default_init(struct spi_nor *nor)
> +{
> + nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> + nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> +}
> +
> +static const struct spi_nor_fixups macronix_fixups = {
> + .default_init = macronix_default_init,
> +};
> +
> +const struct spi_nor_manufacturer spi_nor_macronix = {
> + .name = "macronix",
> + .parts = macronix_parts,
> + .nparts = ARRAY_SIZE(macronix_parts),
> + .fixups = &macronix_fixups,
> +};


2020-03-07 14:51:06

by Boris Brezillon

[permalink] [raw]
Subject: Re: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h

On Mon, 2 Mar 2020 18:07:57 +0000
<[email protected]> wrote:

> From: Tudor Ambarus <[email protected]>
>
> The SPI NOR controllers drivers must not be able to use structures that
> are meant just for the SPI NOR core.
>
> struct spi_nor_flash_parameter is filled at run-time with info gathered
> from flash_info, manufacturer and sfdp data. struct spi_nor_flash_parameter
> should be opaque to the SPI NOR controller drivers, make sure it is.
>
> spi_nor_option_flags, spi_nor_read_command, spi_nor_pp_command,
> spi_nor_read_command_index and spi_nor_pp_command_index are defined for the
> core use, make sure they are opaque to the SPI NOR controller drivers.
>
> Signed-off-by: Tudor Ambarus <[email protected]>

Reviewed-by: Boris Brezillon <[email protected]>

> ---
> drivers/mtd/spi-nor/core.c | 86 ++++++----
> drivers/mtd/spi-nor/core.h | 214 +++++++++++++++++++++++++
> drivers/mtd/spi-nor/gigadevice.c | 2 +-
> drivers/mtd/spi-nor/issi.c | 2 +-
> drivers/mtd/spi-nor/macronix.c | 4 +-
> drivers/mtd/spi-nor/micron-st.c | 4 +-
> drivers/mtd/spi-nor/sfdp.c | 10 ++
> drivers/mtd/spi-nor/spansion.c | 2 +-
> drivers/mtd/spi-nor/winbond.c | 2 +-
> drivers/mtd/spi-nor/xilinx.c | 4 +-
> include/linux/mtd/spi-nor.h | 259 +------------------------------
> 11 files changed, 294 insertions(+), 295 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index a2e1917b608d..860dac1dff90 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -802,7 +802,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
> ret = spi_nor_read_cr(nor, &sr_cr[1]);
> if (ret)
> return ret;
> - } else if (nor->params.quad_enable) {
> + } else if (nor->params->quad_enable) {
> /*
> * If the Status Register 2 Read command (35h) is not
> * supported, we should at least be sure we don't
> @@ -810,7 +810,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
> *
> * We can safely assume that when the Quad Enable method is
> * set, the value of the QE bit is one, as a consequence of the
> - * nor->params.quad_enable() call.
> + * nor->params->quad_enable() call.
> *
> * We can safely assume that the Quad Enable bit is present in
> * the Status Register 2 at BIT(1). According to the JESD216
> @@ -1075,6 +1075,11 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
> ARRAY_SIZE(spi_nor_3to4_erase));
> }
>
> +static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
> +{
> + return !!nor->params->erase_map.uniform_erase_type;
> +}
> +
> static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
> {
> nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
> @@ -1082,7 +1087,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
> nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
>
> if (!spi_nor_has_uniform_erase(nor)) {
> - struct spi_nor_erase_map *map = &nor->params.erase_map;
> + struct spi_nor_erase_map *map = &nor->params->erase_map;
> struct spi_nor_erase_type *erase;
> int i;
>
> @@ -1119,10 +1124,10 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)
>
> static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
> {
> - if (!nor->params.convert_addr)
> + if (!nor->params->convert_addr)
> return addr;
>
> - return nor->params.convert_addr(nor, addr);
> + return nor->params->convert_addr(nor, addr);
> }
>
> /*
> @@ -1227,6 +1232,16 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
> return NULL;
> }
>
> +static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> +{
> + return region->offset & SNOR_LAST_REGION;
> +}
> +
> +static u64 spi_nor_region_end(const struct spi_nor_erase_region *region)
> +{
> + return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> +}
> +
> /**
> * spi_nor_region_next() - get the next spi nor region
> * @region: pointer to a structure that describes a SPI NOR erase region
> @@ -1331,7 +1346,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
> struct list_head *erase_list,
> u64 addr, u32 len)
> {
> - const struct spi_nor_erase_map *map = &nor->params.erase_map;
> + const struct spi_nor_erase_map *map = &nor->params->erase_map;
> const struct spi_nor_erase_type *erase, *prev_erase = NULL;
> struct spi_nor_erase_region *region;
> struct spi_nor_erase_command *cmd = NULL;
> @@ -1817,7 +1832,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> if (ret)
> return ret;
>
> - ret = nor->params.locking_ops->lock(nor, ofs, len);
> + ret = nor->params->locking_ops->lock(nor, ofs, len);
>
> spi_nor_unlock_and_unprep(nor);
> return ret;
> @@ -1832,7 +1847,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> if (ret)
> return ret;
>
> - ret = nor->params.locking_ops->unlock(nor, ofs, len);
> + ret = nor->params->locking_ops->unlock(nor, ofs, len);
>
> spi_nor_unlock_and_unprep(nor);
> return ret;
> @@ -1847,7 +1862,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> if (ret)
> return ret;
>
> - ret = nor->params.locking_ops->is_locked(nor, ofs, len);
> + ret = nor->params->locking_ops->is_locked(nor, ofs, len);
>
> spi_nor_unlock_and_unprep(nor);
> return ret;
> @@ -2312,7 +2327,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor,
> static void
> spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
> {
> - struct spi_nor_flash_parameter *params = &nor->params;
> + struct spi_nor_flash_parameter *params = nor->params;
> unsigned int cap;
>
> /* DTR modes are not supported yet, mask them all. */
> @@ -2411,7 +2426,7 @@ static int spi_nor_select_read(struct spi_nor *nor,
> if (cmd < 0)
> return -EINVAL;
>
> - read = &nor->params.reads[cmd];
> + read = &nor->params->reads[cmd];
> nor->read_opcode = read->opcode;
> nor->read_proto = read->proto;
>
> @@ -2442,7 +2457,7 @@ static int spi_nor_select_pp(struct spi_nor *nor,
> if (cmd < 0)
> return -EINVAL;
>
> - pp = &nor->params.page_programs[cmd];
> + pp = &nor->params->page_programs[cmd];
> nor->program_opcode = pp->opcode;
> nor->write_proto = pp->proto;
> return 0;
> @@ -2503,7 +2518,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
>
> static int spi_nor_select_erase(struct spi_nor *nor)
> {
> - struct spi_nor_erase_map *map = &nor->params.erase_map;
> + struct spi_nor_erase_map *map = &nor->params->erase_map;
> const struct spi_nor_erase_type *erase = NULL;
> struct mtd_info *mtd = &nor->mtd;
> u32 wanted_size = nor->info->sector_size;
> @@ -2552,7 +2567,7 @@ static int spi_nor_select_erase(struct spi_nor *nor)
> static int spi_nor_default_setup(struct spi_nor *nor,
> const struct spi_nor_hwcaps *hwcaps)
> {
> - struct spi_nor_flash_parameter *params = &nor->params;
> + struct spi_nor_flash_parameter *params = nor->params;
> u32 ignored_mask, shared_mask;
> int err;
>
> @@ -2613,10 +2628,10 @@ static int spi_nor_default_setup(struct spi_nor *nor,
> static int spi_nor_setup(struct spi_nor *nor,
> const struct spi_nor_hwcaps *hwcaps)
> {
> - if (!nor->params.setup)
> + if (!nor->params->setup)
> return 0;
>
> - return nor->params.setup(nor, hwcaps);
> + return nor->params->setup(nor, hwcaps);
> }
>
> /**
> @@ -2646,13 +2661,13 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
> {
> struct spi_nor_flash_parameter sfdp_params;
>
> - memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
> + memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
>
> if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
> nor->addr_width = 0;
> nor->flags &= ~SNOR_F_4B_OPCODES;
> } else {
> - memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
> + memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
> }
> }
>
> @@ -2663,7 +2678,7 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
> */
> static void spi_nor_info_init_params(struct spi_nor *nor)
> {
> - struct spi_nor_flash_parameter *params = &nor->params;
> + struct spi_nor_flash_parameter *params = nor->params;
> struct spi_nor_erase_map *map = &params->erase_map;
> const struct flash_info *info = nor->info;
> struct device_node *np = spi_nor_get_flash_node(nor);
> @@ -2782,8 +2797,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
> * NOR protection support. When locking_ops are not provided, we pick
> * the default ones.
> */
> - if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
> - nor->params.locking_ops = &spi_nor_sr_locking_ops;
> + if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
> + nor->params->locking_ops = &spi_nor_sr_locking_ops;
> }
>
> /**
> @@ -2823,8 +2838,12 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
> * ->default_init() hook or the SFDP parser do not set specific params.
> * spi_nor_late_init_params()
> */
> -static void spi_nor_init_params(struct spi_nor *nor)
> +static int spi_nor_init_params(struct spi_nor *nor)
> {
> + nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
> + if (!nor->params)
> + return -ENOMEM;
> +
> spi_nor_info_init_params(nor);
>
> spi_nor_manufacturer_init_params(nor);
> @@ -2836,6 +2855,8 @@ static void spi_nor_init_params(struct spi_nor *nor)
> spi_nor_post_sfdp_fixups(nor);
>
> spi_nor_late_init_params(nor);
> +
> + return 0;
> }
>
> /**
> @@ -2846,14 +2867,14 @@ static void spi_nor_init_params(struct spi_nor *nor)
> */
> static int spi_nor_quad_enable(struct spi_nor *nor)
> {
> - if (!nor->params.quad_enable)
> + if (!nor->params->quad_enable)
> return 0;
>
> if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
> spi_nor_get_protocol_width(nor->write_proto) == 4))
> return 0;
>
> - return nor->params.quad_enable(nor);
> + return nor->params->quad_enable(nor);
> }
>
> /**
> @@ -2868,7 +2889,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor)
> static int spi_nor_unlock_all(struct spi_nor *nor)
> {
> if (nor->flags & SNOR_F_HAS_LOCK)
> - return spi_nor_unlock(&nor->mtd, 0, nor->params.size);
> + return spi_nor_unlock(&nor->mtd, 0, nor->params->size);
>
> return 0;
> }
> @@ -2899,7 +2920,7 @@ static int spi_nor_init(struct spi_nor *nor)
> */
> WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
> "enabling reset hack; may not recover from unexpected reboots\n");
> - nor->params.set_4byte(nor, true);
> + nor->params->set_4byte(nor, true);
> }
>
> return 0;
> @@ -2923,7 +2944,7 @@ void spi_nor_restore(struct spi_nor *nor)
> /* restore the addressing mode */
> if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
> nor->flags & SNOR_F_BROKEN_RESET)
> - nor->params.set_4byte(nor, false);
> + nor->params->set_4byte(nor, false);
> }
> EXPORT_SYMBOL_GPL(spi_nor_restore);
>
> @@ -3028,7 +3049,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> struct device *dev = nor->dev;
> struct mtd_info *mtd = &nor->mtd;
> struct device_node *np = spi_nor_get_flash_node(nor);
> - struct spi_nor_flash_parameter *params = &nor->params;
> int ret;
> int i;
>
> @@ -3079,7 +3099,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> mtd->_write = spi_nor_write;
>
> /* Init flash parameters based on flash_info struct and SFDP */
> - spi_nor_init_params(nor);
> + ret = spi_nor_init_params(nor);
> + if (ret)
> + return ret;
>
> if (!mtd->name)
> mtd->name = dev_name(dev);
> @@ -3087,12 +3109,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> mtd->type = MTD_NORFLASH;
> mtd->writesize = 1;
> mtd->flags = MTD_CAP_NORFLASH;
> - mtd->size = params->size;
> + mtd->size = nor->params->size;
> mtd->_erase = spi_nor_erase;
> mtd->_read = spi_nor_read;
> mtd->_resume = spi_nor_resume;
>
> - if (nor->params.locking_ops) {
> + if (nor->params->locking_ops) {
> mtd->_lock = spi_nor_lock;
> mtd->_unlock = spi_nor_unlock;
> mtd->_is_locked = spi_nor_is_locked;
> @@ -3115,7 +3137,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> mtd->flags |= MTD_NO_ERASE;
>
> mtd->dev.parent = dev;
> - nor->page_size = params->page_size;
> + nor->page_size = nor->params->page_size;
> mtd->writebufsize = nor->page_size;
>
> if (of_property_read_bool(np, "broken-flash-reset"))
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 3541a84c03d8..7654b6f3b966 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -11,6 +11,220 @@
>
> #define SPI_NOR_MAX_ID_LEN 6
>
> +enum spi_nor_option_flags {
> + SNOR_F_USE_FSR = BIT(0),
> + SNOR_F_HAS_SR_TB = BIT(1),
> + SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
> + SNOR_F_READY_XSR_RDY = BIT(3),
> + SNOR_F_USE_CLSR = BIT(4),
> + SNOR_F_BROKEN_RESET = BIT(5),
> + SNOR_F_4B_OPCODES = BIT(6),
> + SNOR_F_HAS_4BAIT = BIT(7),
> + SNOR_F_HAS_LOCK = BIT(8),
> + SNOR_F_HAS_16BIT_SR = BIT(9),
> + SNOR_F_NO_READ_CR = BIT(10),
> + SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
> +};
> +
> +struct spi_nor_read_command {
> + u8 num_mode_clocks;
> + u8 num_wait_states;
> + u8 opcode;
> + enum spi_nor_protocol proto;
> +};
> +
> +struct spi_nor_pp_command {
> + u8 opcode;
> + enum spi_nor_protocol proto;
> +};
> +
> +enum spi_nor_read_command_index {
> + SNOR_CMD_READ,
> + SNOR_CMD_READ_FAST,
> + SNOR_CMD_READ_1_1_1_DTR,
> +
> + /* Dual SPI */
> + SNOR_CMD_READ_1_1_2,
> + SNOR_CMD_READ_1_2_2,
> + SNOR_CMD_READ_2_2_2,
> + SNOR_CMD_READ_1_2_2_DTR,
> +
> + /* Quad SPI */
> + SNOR_CMD_READ_1_1_4,
> + SNOR_CMD_READ_1_4_4,
> + SNOR_CMD_READ_4_4_4,
> + SNOR_CMD_READ_1_4_4_DTR,
> +
> + /* Octal SPI */
> + SNOR_CMD_READ_1_1_8,
> + SNOR_CMD_READ_1_8_8,
> + SNOR_CMD_READ_8_8_8,
> + SNOR_CMD_READ_1_8_8_DTR,
> +
> + SNOR_CMD_READ_MAX
> +};
> +
> +enum spi_nor_pp_command_index {
> + SNOR_CMD_PP,
> +
> + /* Quad SPI */
> + SNOR_CMD_PP_1_1_4,
> + SNOR_CMD_PP_1_4_4,
> + SNOR_CMD_PP_4_4_4,
> +
> + /* Octal SPI */
> + SNOR_CMD_PP_1_1_8,
> + SNOR_CMD_PP_1_8_8,
> + SNOR_CMD_PP_8_8_8,
> +
> + SNOR_CMD_PP_MAX
> +};
> +
> +/**
> + * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> + * @size: the size of the sector/block erased by the erase type.
> + * JEDEC JESD216B imposes erase sizes to be a power of 2.
> + * @size_shift: @size is a power of 2, the shift is stored in
> + * @size_shift.
> + * @size_mask: the size mask based on @size_shift.
> + * @opcode: the SPI command op code to erase the sector/block.
> + * @idx: Erase Type index as sorted in the Basic Flash Parameter
> + * Table. It will be used to synchronize the supported
> + * Erase Types with the ones identified in the SFDP
> + * optional tables.
> + */
> +struct spi_nor_erase_type {
> + u32 size;
> + u32 size_shift;
> + u32 size_mask;
> + u8 opcode;
> + u8 idx;
> +};
> +
> +/**
> + * struct spi_nor_erase_command - Used for non-uniform erases
> + * The structure is used to describe a list of erase commands to be executed
> + * once we validate that the erase can be performed. The elements in the list
> + * are run-length encoded.
> + * @list: for inclusion into the list of erase commands.
> + * @count: how many times the same erase command should be
> + * consecutively used.
> + * @size: the size of the sector/block erased by the command.
> + * @opcode: the SPI command op code to erase the sector/block.
> + */
> +struct spi_nor_erase_command {
> + struct list_head list;
> + u32 count;
> + u32 size;
> + u8 opcode;
> +};
> +
> +/**
> + * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> + * @offset: the offset in the data array of erase region start.
> + * LSB bits are used as a bitmask encoding flags to
> + * determine if this region is overlaid, if this region is
> + * the last in the SPI NOR flash memory and to indicate
> + * all the supported erase commands inside this region.
> + * The erase types are sorted in ascending order with the
> + * smallest Erase Type size being at BIT(0).
> + * @size: the size of the region in bytes.
> + */
> +struct spi_nor_erase_region {
> + u64 offset;
> + u64 size;
> +};
> +
> +#define SNOR_ERASE_TYPE_MAX 4
> +#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> +
> +#define SNOR_LAST_REGION BIT(4)
> +#define SNOR_OVERLAID_REGION BIT(5)
> +
> +#define SNOR_ERASE_FLAGS_MAX 6
> +#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> +
> +/**
> + * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> + * @regions: array of erase regions. The regions are consecutive in
> + * address space. Walking through the regions is done
> + * incrementally.
> + * @uniform_region: a pre-allocated erase region for SPI NOR with a uniform
> + * sector size (legacy implementation).
> + * @erase_type: an array of erase types shared by all the regions.
> + * The erase types are sorted in ascending order, with the
> + * smallest Erase Type size being the first member in the
> + * erase_type array.
> + * @uniform_erase_type: bitmask encoding erase types that can erase the
> + * entire memory. This member is completed at init by
> + * uniform and non-uniform SPI NOR flash memories if they
> + * support at least one erase type that can erase the
> + * entire memory.
> + */
> +struct spi_nor_erase_map {
> + struct spi_nor_erase_region *regions;
> + struct spi_nor_erase_region uniform_region;
> + struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX];
> + u8 uniform_erase_type;
> +};
> +
> +/**
> + * struct spi_nor_locking_ops - SPI NOR locking methods
> + * @lock: lock a region of the SPI NOR.
> + * @unlock: unlock a region of the SPI NOR.
> + * @is_locked: check if a region of the SPI NOR is completely locked
> + */
> +struct spi_nor_locking_ops {
> + int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> + int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> + int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +};
> +
> +/**
> + * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> + * Includes legacy flash parameters and settings that can be overwritten
> + * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> + * Serial Flash Discoverable Parameters (SFDP) tables.
> + *
> + * @size: the flash memory density in bytes.
> + * @page_size: the page size of the SPI NOR flash memory.
> + * @hwcaps: describes the read and page program hardware
> + * capabilities.
> + * @reads: read capabilities ordered by priority: the higher index
> + * in the array, the higher priority.
> + * @page_programs: page program capabilities ordered by priority: the
> + * higher index in the array, the higher priority.
> + * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
> + * Table.
> + * @quad_enable: enables SPI NOR quad mode.
> + * @set_4byte: puts the SPI NOR in 4 byte addressing mode.
> + * @convert_addr: converts an absolute address into something the flash
> + * will understand. Particularly useful when pagesize is
> + * not a power-of-2.
> + * @setup: configures the SPI NOR memory. Useful for SPI NOR
> + * flashes that have peculiarities to the SPI NOR standard
> + * e.g. different opcodes, specific address calculation,
> + * page size, etc.
> + * @locking_ops: SPI NOR locking methods.
> + */
> +struct spi_nor_flash_parameter {
> + u64 size;
> + u32 page_size;
> +
> + struct spi_nor_hwcaps hwcaps;
> + struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
> + struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
> +
> + struct spi_nor_erase_map erase_map;
> +
> + int (*quad_enable)(struct spi_nor *nor);
> + int (*set_4byte)(struct spi_nor *nor, bool enable);
> + u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> + int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> +
> + const struct spi_nor_locking_ops *locking_ops;
> +};
> +
> /**
> * struct spi_nor_fixups - SPI NOR fixup hooks
> * @default_init: called after default flash parameters init. Used to tweak
> diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
> index 7930e4490dab..447d84bb2128 100644
> --- a/drivers/mtd/spi-nor/gigadevice.c
> +++ b/drivers/mtd/spi-nor/gigadevice.c
> @@ -16,7 +16,7 @@ static void gd25q256_default_init(struct spi_nor *nor)
> * indicate the quad_enable method for this case, we need
> * to set it in the default_init fixup hook.
> */
> - nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> }
>
> static struct spi_nor_fixups gd25q256_fixups = {
> diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
> index 3a1c34c41388..ffcb60e54a80 100644
> --- a/drivers/mtd/spi-nor/issi.c
> +++ b/drivers/mtd/spi-nor/issi.c
> @@ -68,7 +68,7 @@ static const struct flash_info issi_parts[] = {
>
> static void issi_default_init(struct spi_nor *nor)
> {
> - nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> }
>
> static const struct spi_nor_fixups issi_fixups = {
> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> index 1ae609c44676..d73bd0363144 100644
> --- a/drivers/mtd/spi-nor/macronix.c
> +++ b/drivers/mtd/spi-nor/macronix.c
> @@ -82,8 +82,8 @@ static const struct flash_info macronix_parts[] = {
>
> static void macronix_default_init(struct spi_nor *nor)
> {
> - nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> - nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> + nor->params->set_4byte = spi_nor_en4_ex4_set_4byte;
> }
>
> static const struct spi_nor_fixups macronix_fixups = {
> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> index 8017ca58b3a5..5be817d2f27c 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -106,8 +106,8 @@ static void micron_st_default_init(struct spi_nor *nor)
> {
> nor->flags |= SNOR_F_HAS_LOCK;
> nor->flags &= ~SNOR_F_HAS_16BIT_SR;
> - nor->params.quad_enable = NULL;
> - nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
> + nor->params->quad_enable = NULL;
> + nor->params->set_4byte = spi_nor_en4_ex4_wen_set_4byte;
> }
>
> static const struct spi_nor_fixups micron_st_fixups = {
> diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
> index b790c3ec871f..6829dc7e4f74 100644
> --- a/drivers/mtd/spi-nor/sfdp.c
> +++ b/drivers/mtd/spi-nor/sfdp.c
> @@ -734,6 +734,16 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
> return ret;
> }
>
> +static void spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> +{
> + region->offset |= SNOR_LAST_REGION;
> +}
> +
> +static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> +{
> + region->offset |= SNOR_OVERLAID_REGION;
> +}
> +
> /**
> * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
> * @region: pointer to a structure that describes a SPI NOR erase region
> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> index 16683983a20e..6756202ace4b 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -74,7 +74,7 @@ static const struct flash_info spansion_parts[] = {
>
> static void spansion_post_sfdp_fixups(struct spi_nor *nor)
> {
> - if (nor->params.size <= SZ_16M)
> + if (nor->params->size <= SZ_16M)
> return;
>
> nor->flags |= SNOR_F_4B_OPCODES;
> diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
> index 1e77dffbf729..f15be50024d1 100644
> --- a/drivers/mtd/spi-nor/winbond.c
> +++ b/drivers/mtd/spi-nor/winbond.c
> @@ -97,7 +97,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)
>
> static void winbond_default_init(struct spi_nor *nor)
> {
> - nor->params.set_4byte = winbond_set_4byte;
> + nor->params->set_4byte = winbond_set_4byte;
> }
>
> static const struct spi_nor_fixups winbond_fixups = {
> diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
> index fcf635d89f65..1138bdbf4199 100644
> --- a/drivers/mtd/spi-nor/xilinx.c
> +++ b/drivers/mtd/spi-nor/xilinx.c
> @@ -70,7 +70,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
> nor->mtd.erasesize = 8 * nor->page_size;
> } else {
> /* Flash in Default addressing mode */
> - nor->params.convert_addr = s3an_convert_addr;
> + nor->params->convert_addr = s3an_convert_addr;
> nor->mtd.erasesize = nor->info->sector_size;
> }
>
> @@ -79,7 +79,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
>
> static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
> {
> - nor->params.setup = xilinx_nor_setup;
> + nor->params->setup = xilinx_nor_setup;
> }
>
> static const struct spi_nor_fixups xilinx_fixups = {
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index dde2988a809e..d3d34c4eea48 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -227,110 +227,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
> return spi_nor_get_protocol_data_nbits(proto);
> }
>
> -enum spi_nor_option_flags {
> - SNOR_F_USE_FSR = BIT(0),
> - SNOR_F_HAS_SR_TB = BIT(1),
> - SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
> - SNOR_F_READY_XSR_RDY = BIT(3),
> - SNOR_F_USE_CLSR = BIT(4),
> - SNOR_F_BROKEN_RESET = BIT(5),
> - SNOR_F_4B_OPCODES = BIT(6),
> - SNOR_F_HAS_4BAIT = BIT(7),
> - SNOR_F_HAS_LOCK = BIT(8),
> - SNOR_F_HAS_16BIT_SR = BIT(9),
> - SNOR_F_NO_READ_CR = BIT(10),
> - SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
> -
> -};
> -
> -/**
> - * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> - * @size: the size of the sector/block erased by the erase type.
> - * JEDEC JESD216B imposes erase sizes to be a power of 2.
> - * @size_shift: @size is a power of 2, the shift is stored in
> - * @size_shift.
> - * @size_mask: the size mask based on @size_shift.
> - * @opcode: the SPI command op code to erase the sector/block.
> - * @idx: Erase Type index as sorted in the Basic Flash Parameter
> - * Table. It will be used to synchronize the supported
> - * Erase Types with the ones identified in the SFDP
> - * optional tables.
> - */
> -struct spi_nor_erase_type {
> - u32 size;
> - u32 size_shift;
> - u32 size_mask;
> - u8 opcode;
> - u8 idx;
> -};
> -
> -/**
> - * struct spi_nor_erase_command - Used for non-uniform erases
> - * The structure is used to describe a list of erase commands to be executed
> - * once we validate that the erase can be performed. The elements in the list
> - * are run-length encoded.
> - * @list: for inclusion into the list of erase commands.
> - * @count: how many times the same erase command should be
> - * consecutively used.
> - * @size: the size of the sector/block erased by the command.
> - * @opcode: the SPI command op code to erase the sector/block.
> - */
> -struct spi_nor_erase_command {
> - struct list_head list;
> - u32 count;
> - u32 size;
> - u8 opcode;
> -};
> -
> -/**
> - * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> - * @offset: the offset in the data array of erase region start.
> - * LSB bits are used as a bitmask encoding flags to
> - * determine if this region is overlaid, if this region is
> - * the last in the SPI NOR flash memory and to indicate
> - * all the supported erase commands inside this region.
> - * The erase types are sorted in ascending order with the
> - * smallest Erase Type size being at BIT(0).
> - * @size: the size of the region in bytes.
> - */
> -struct spi_nor_erase_region {
> - u64 offset;
> - u64 size;
> -};
> -
> -#define SNOR_ERASE_TYPE_MAX 4
> -#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> -
> -#define SNOR_LAST_REGION BIT(4)
> -#define SNOR_OVERLAID_REGION BIT(5)
> -
> -#define SNOR_ERASE_FLAGS_MAX 6
> -#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> -
> -/**
> - * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> - * @regions: array of erase regions. The regions are consecutive in
> - * address space. Walking through the regions is done
> - * incrementally.
> - * @uniform_region: a pre-allocated erase region for SPI NOR with a uniform
> - * sector size (legacy implementation).
> - * @erase_type: an array of erase types shared by all the regions.
> - * The erase types are sorted in ascending order, with the
> - * smallest Erase Type size being the first member in the
> - * erase_type array.
> - * @uniform_erase_type: bitmask encoding erase types that can erase the
> - * entire memory. This member is completed at init by
> - * uniform and non-uniform SPI NOR flash memories if they
> - * support at least one erase type that can erase the
> - * entire memory.
> - */
> -struct spi_nor_erase_map {
> - struct spi_nor_erase_region *regions;
> - struct spi_nor_erase_region uniform_region;
> - struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX];
> - u8 uniform_erase_type;
> -};
> -
> /**
> * struct spi_nor_hwcaps - Structure for describing the hardware capabilies
> * supported by the SPI controller (bus master).
> @@ -406,61 +302,7 @@ struct spi_nor_hwcaps {
> #define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \
> SNOR_HWCAPS_PP_MASK)
>
> -struct spi_nor_read_command {
> - u8 num_mode_clocks;
> - u8 num_wait_states;
> - u8 opcode;
> - enum spi_nor_protocol proto;
> -};
> -
> -struct spi_nor_pp_command {
> - u8 opcode;
> - enum spi_nor_protocol proto;
> -};
> -
> -enum spi_nor_read_command_index {
> - SNOR_CMD_READ,
> - SNOR_CMD_READ_FAST,
> - SNOR_CMD_READ_1_1_1_DTR,
> -
> - /* Dual SPI */
> - SNOR_CMD_READ_1_1_2,
> - SNOR_CMD_READ_1_2_2,
> - SNOR_CMD_READ_2_2_2,
> - SNOR_CMD_READ_1_2_2_DTR,
> -
> - /* Quad SPI */
> - SNOR_CMD_READ_1_1_4,
> - SNOR_CMD_READ_1_4_4,
> - SNOR_CMD_READ_4_4_4,
> - SNOR_CMD_READ_1_4_4_DTR,
> -
> - /* Octal SPI */
> - SNOR_CMD_READ_1_1_8,
> - SNOR_CMD_READ_1_8_8,
> - SNOR_CMD_READ_8_8_8,
> - SNOR_CMD_READ_1_8_8_DTR,
> -
> - SNOR_CMD_READ_MAX
> -};
> -
> -enum spi_nor_pp_command_index {
> - SNOR_CMD_PP,
> -
> - /* Quad SPI */
> - SNOR_CMD_PP_1_1_4,
> - SNOR_CMD_PP_1_4_4,
> - SNOR_CMD_PP_4_4_4,
> -
> - /* Octal SPI */
> - SNOR_CMD_PP_1_1_8,
> - SNOR_CMD_PP_1_8_8,
> - SNOR_CMD_PP_8_8_8,
> -
> - SNOR_CMD_PP_MAX
> -};
> -
> -/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
> +/* Forward declaration that is used in 'struct spi_nor_controller_ops' */
> struct spi_nor;
>
> /**
> @@ -491,74 +333,14 @@ struct spi_nor_controller_ops {
> int (*erase)(struct spi_nor *nor, loff_t offs);
> };
>
> -/**
> - * struct spi_nor_locking_ops - SPI NOR locking methods
> - * @lock: lock a region of the SPI NOR.
> - * @unlock: unlock a region of the SPI NOR.
> - * @is_locked: check if a region of the SPI NOR is completely locked
> - */
> -struct spi_nor_locking_ops {
> - int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> - int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> - int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -};
> -
> -/**
> - * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> - * Includes legacy flash parameters and settings that can be overwritten
> - * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> - * Serial Flash Discoverable Parameters (SFDP) tables.
> - *
> - * @size: the flash memory density in bytes.
> - * @page_size: the page size of the SPI NOR flash memory.
> - * @hwcaps: describes the read and page program hardware
> - * capabilities.
> - * @reads: read capabilities ordered by priority: the higher index
> - * in the array, the higher priority.
> - * @page_programs: page program capabilities ordered by priority: the
> - * higher index in the array, the higher priority.
> - * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
> - * Table.
> - * @quad_enable: enables SPI NOR quad mode.
> - * @set_4byte: puts the SPI NOR in 4 byte addressing mode.
> - * @convert_addr: converts an absolute address into something the flash
> - * will understand. Particularly useful when pagesize is
> - * not a power-of-2.
> - * @setup: configures the SPI NOR memory. Useful for SPI NOR
> - * flashes that have peculiarities to the SPI NOR standard
> - * e.g. different opcodes, specific address calculation,
> - * page size, etc.
> - * @locking_ops: SPI NOR locking methods.
> - */
> -struct spi_nor_flash_parameter {
> - u64 size;
> - u32 page_size;
> -
> - struct spi_nor_hwcaps hwcaps;
> - struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
> - struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
>
> - struct spi_nor_erase_map erase_map;
> -
> - int (*quad_enable)(struct spi_nor *nor);
> - int (*set_4byte)(struct spi_nor *nor, bool enable);
> - u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> - int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> -
> - const struct spi_nor_locking_ops *locking_ops;
> -};
> -
> -/**
> - * struct flash_info - Forward declaration of a structure used internally by
> - * spi_nor_scan()
> +/*
> + * Forward declarations that are used internally by the core and manufacturer
> + * drivers.
> */
> struct flash_info;
> -
> -/**
> - * struct spi_nor_manufacturer - Forward declaration of a structure used
> - * internally by the core and manufacturer drivers.
> - */
> struct spi_nor_manufacturer;
> +struct spi_nor_flash_parameter;
>
> /**
> * struct spi_nor - Structure for defining a the SPI NOR layer
> @@ -613,7 +395,7 @@ struct spi_nor {
>
> const struct spi_nor_controller_ops *controller_ops;
>
> - struct spi_nor_flash_parameter params;
> + struct spi_nor_flash_parameter *params;
>
> struct {
> struct spi_mem_dirmap_desc *rdesc;
> @@ -623,35 +405,6 @@ struct spi_nor {
> void *priv;
> };
>
> -static u64 __maybe_unused
> -spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> -{
> - return region->offset & SNOR_LAST_REGION;
> -}
> -
> -static u64 __maybe_unused
> -spi_nor_region_end(const struct spi_nor_erase_region *region)
> -{
> - return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> -{
> - region->offset |= SNOR_LAST_REGION;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> -{
> - region->offset |= SNOR_OVERLAID_REGION;
> -}
> -
> -static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
> -{
> - return !!nor->params.erase_map.uniform_erase_type;
> -}
> -
> static inline void spi_nor_set_flash_node(struct spi_nor *nor,
> struct device_node *np)
> {

2020-03-13 08:16:42

by Vignesh Raghavendra

[permalink] [raw]
Subject: Re: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h



On 02/03/20 11:37 pm, [email protected] wrote:
> From: Tudor Ambarus <[email protected]>
>
> The SPI NOR controllers drivers must not be able to use structures that
> are meant just for the SPI NOR core.
>
> struct spi_nor_flash_parameter is filled at run-time with info gathered
> from flash_info, manufacturer and sfdp data. struct spi_nor_flash_parameter
> should be opaque to the SPI NOR controller drivers, make sure it is.
>
> spi_nor_option_flags, spi_nor_read_command, spi_nor_pp_command,
> spi_nor_read_command_index and spi_nor_pp_command_index are defined for the
> core use, make sure they are opaque to the SPI NOR controller drivers.
>
> Signed-off-by: Tudor Ambarus <[email protected]>

Nice work!

Reviewed-by: Vignesh Raghavendra <[email protected]>

Should we drop SNOR_MFR_* macros as well or do you see a neeed for them?


> ---
> drivers/mtd/spi-nor/core.c | 86 ++++++----
> drivers/mtd/spi-nor/core.h | 214 +++++++++++++++++++++++++
> drivers/mtd/spi-nor/gigadevice.c | 2 +-
> drivers/mtd/spi-nor/issi.c | 2 +-
> drivers/mtd/spi-nor/macronix.c | 4 +-
> drivers/mtd/spi-nor/micron-st.c | 4 +-
> drivers/mtd/spi-nor/sfdp.c | 10 ++
> drivers/mtd/spi-nor/spansion.c | 2 +-
> drivers/mtd/spi-nor/winbond.c | 2 +-
> drivers/mtd/spi-nor/xilinx.c | 4 +-
> include/linux/mtd/spi-nor.h | 259 +------------------------------
> 11 files changed, 294 insertions(+), 295 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index a2e1917b608d..860dac1dff90 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -802,7 +802,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
> ret = spi_nor_read_cr(nor, &sr_cr[1]);
> if (ret)
> return ret;
> - } else if (nor->params.quad_enable) {
> + } else if (nor->params->quad_enable) {
> /*
> * If the Status Register 2 Read command (35h) is not
> * supported, we should at least be sure we don't
> @@ -810,7 +810,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
> *
> * We can safely assume that when the Quad Enable method is
> * set, the value of the QE bit is one, as a consequence of the
> - * nor->params.quad_enable() call.
> + * nor->params->quad_enable() call.
> *
> * We can safely assume that the Quad Enable bit is present in
> * the Status Register 2 at BIT(1). According to the JESD216
> @@ -1075,6 +1075,11 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
> ARRAY_SIZE(spi_nor_3to4_erase));
> }
>
> +static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
> +{
> + return !!nor->params->erase_map.uniform_erase_type;
> +}
> +
> static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
> {
> nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
> @@ -1082,7 +1087,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
> nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
>
> if (!spi_nor_has_uniform_erase(nor)) {
> - struct spi_nor_erase_map *map = &nor->params.erase_map;
> + struct spi_nor_erase_map *map = &nor->params->erase_map;
> struct spi_nor_erase_type *erase;
> int i;
>
> @@ -1119,10 +1124,10 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)
>
> static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
> {
> - if (!nor->params.convert_addr)
> + if (!nor->params->convert_addr)
> return addr;
>
> - return nor->params.convert_addr(nor, addr);
> + return nor->params->convert_addr(nor, addr);
> }
>
> /*
> @@ -1227,6 +1232,16 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
> return NULL;
> }
>
> +static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> +{
> + return region->offset & SNOR_LAST_REGION;
> +}
> +
> +static u64 spi_nor_region_end(const struct spi_nor_erase_region *region)
> +{
> + return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> +}
> +
> /**
> * spi_nor_region_next() - get the next spi nor region
> * @region: pointer to a structure that describes a SPI NOR erase region
> @@ -1331,7 +1346,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
> struct list_head *erase_list,
> u64 addr, u32 len)
> {
> - const struct spi_nor_erase_map *map = &nor->params.erase_map;
> + const struct spi_nor_erase_map *map = &nor->params->erase_map;
> const struct spi_nor_erase_type *erase, *prev_erase = NULL;
> struct spi_nor_erase_region *region;
> struct spi_nor_erase_command *cmd = NULL;
> @@ -1817,7 +1832,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> if (ret)
> return ret;
>
> - ret = nor->params.locking_ops->lock(nor, ofs, len);
> + ret = nor->params->locking_ops->lock(nor, ofs, len);
>
> spi_nor_unlock_and_unprep(nor);
> return ret;
> @@ -1832,7 +1847,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> if (ret)
> return ret;
>
> - ret = nor->params.locking_ops->unlock(nor, ofs, len);
> + ret = nor->params->locking_ops->unlock(nor, ofs, len);
>
> spi_nor_unlock_and_unprep(nor);
> return ret;
> @@ -1847,7 +1862,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
> if (ret)
> return ret;
>
> - ret = nor->params.locking_ops->is_locked(nor, ofs, len);
> + ret = nor->params->locking_ops->is_locked(nor, ofs, len);
>
> spi_nor_unlock_and_unprep(nor);
> return ret;
> @@ -2312,7 +2327,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor,
> static void
> spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
> {
> - struct spi_nor_flash_parameter *params = &nor->params;
> + struct spi_nor_flash_parameter *params = nor->params;
> unsigned int cap;
>
> /* DTR modes are not supported yet, mask them all. */
> @@ -2411,7 +2426,7 @@ static int spi_nor_select_read(struct spi_nor *nor,
> if (cmd < 0)
> return -EINVAL;
>
> - read = &nor->params.reads[cmd];
> + read = &nor->params->reads[cmd];
> nor->read_opcode = read->opcode;
> nor->read_proto = read->proto;
>
> @@ -2442,7 +2457,7 @@ static int spi_nor_select_pp(struct spi_nor *nor,
> if (cmd < 0)
> return -EINVAL;
>
> - pp = &nor->params.page_programs[cmd];
> + pp = &nor->params->page_programs[cmd];
> nor->program_opcode = pp->opcode;
> nor->write_proto = pp->proto;
> return 0;
> @@ -2503,7 +2518,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
>
> static int spi_nor_select_erase(struct spi_nor *nor)
> {
> - struct spi_nor_erase_map *map = &nor->params.erase_map;
> + struct spi_nor_erase_map *map = &nor->params->erase_map;
> const struct spi_nor_erase_type *erase = NULL;
> struct mtd_info *mtd = &nor->mtd;
> u32 wanted_size = nor->info->sector_size;
> @@ -2552,7 +2567,7 @@ static int spi_nor_select_erase(struct spi_nor *nor)
> static int spi_nor_default_setup(struct spi_nor *nor,
> const struct spi_nor_hwcaps *hwcaps)
> {
> - struct spi_nor_flash_parameter *params = &nor->params;
> + struct spi_nor_flash_parameter *params = nor->params;
> u32 ignored_mask, shared_mask;
> int err;
>
> @@ -2613,10 +2628,10 @@ static int spi_nor_default_setup(struct spi_nor *nor,
> static int spi_nor_setup(struct spi_nor *nor,
> const struct spi_nor_hwcaps *hwcaps)
> {
> - if (!nor->params.setup)
> + if (!nor->params->setup)
> return 0;
>
> - return nor->params.setup(nor, hwcaps);
> + return nor->params->setup(nor, hwcaps);
> }
>
> /**
> @@ -2646,13 +2661,13 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
> {
> struct spi_nor_flash_parameter sfdp_params;
>
> - memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
> + memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
>
> if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
> nor->addr_width = 0;
> nor->flags &= ~SNOR_F_4B_OPCODES;
> } else {
> - memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
> + memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
> }
> }
>
> @@ -2663,7 +2678,7 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
> */
> static void spi_nor_info_init_params(struct spi_nor *nor)
> {
> - struct spi_nor_flash_parameter *params = &nor->params;
> + struct spi_nor_flash_parameter *params = nor->params;
> struct spi_nor_erase_map *map = &params->erase_map;
> const struct flash_info *info = nor->info;
> struct device_node *np = spi_nor_get_flash_node(nor);
> @@ -2782,8 +2797,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
> * NOR protection support. When locking_ops are not provided, we pick
> * the default ones.
> */
> - if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
> - nor->params.locking_ops = &spi_nor_sr_locking_ops;
> + if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
> + nor->params->locking_ops = &spi_nor_sr_locking_ops;
> }
>
> /**
> @@ -2823,8 +2838,12 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
> * ->default_init() hook or the SFDP parser do not set specific params.
> * spi_nor_late_init_params()
> */
> -static void spi_nor_init_params(struct spi_nor *nor)
> +static int spi_nor_init_params(struct spi_nor *nor)
> {
> + nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
> + if (!nor->params)
> + return -ENOMEM;
> +
> spi_nor_info_init_params(nor);
>
> spi_nor_manufacturer_init_params(nor);
> @@ -2836,6 +2855,8 @@ static void spi_nor_init_params(struct spi_nor *nor)
> spi_nor_post_sfdp_fixups(nor);
>
> spi_nor_late_init_params(nor);
> +
> + return 0;
> }
>
> /**
> @@ -2846,14 +2867,14 @@ static void spi_nor_init_params(struct spi_nor *nor)
> */
> static int spi_nor_quad_enable(struct spi_nor *nor)
> {
> - if (!nor->params.quad_enable)
> + if (!nor->params->quad_enable)
> return 0;
>
> if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
> spi_nor_get_protocol_width(nor->write_proto) == 4))
> return 0;
>
> - return nor->params.quad_enable(nor);
> + return nor->params->quad_enable(nor);
> }
>
> /**
> @@ -2868,7 +2889,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor)
> static int spi_nor_unlock_all(struct spi_nor *nor)
> {
> if (nor->flags & SNOR_F_HAS_LOCK)
> - return spi_nor_unlock(&nor->mtd, 0, nor->params.size);
> + return spi_nor_unlock(&nor->mtd, 0, nor->params->size);
>
> return 0;
> }
> @@ -2899,7 +2920,7 @@ static int spi_nor_init(struct spi_nor *nor)
> */
> WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
> "enabling reset hack; may not recover from unexpected reboots\n");
> - nor->params.set_4byte(nor, true);
> + nor->params->set_4byte(nor, true);
> }
>
> return 0;
> @@ -2923,7 +2944,7 @@ void spi_nor_restore(struct spi_nor *nor)
> /* restore the addressing mode */
> if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
> nor->flags & SNOR_F_BROKEN_RESET)
> - nor->params.set_4byte(nor, false);
> + nor->params->set_4byte(nor, false);
> }
> EXPORT_SYMBOL_GPL(spi_nor_restore);
>
> @@ -3028,7 +3049,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> struct device *dev = nor->dev;
> struct mtd_info *mtd = &nor->mtd;
> struct device_node *np = spi_nor_get_flash_node(nor);
> - struct spi_nor_flash_parameter *params = &nor->params;
> int ret;
> int i;
>
> @@ -3079,7 +3099,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> mtd->_write = spi_nor_write;
>
> /* Init flash parameters based on flash_info struct and SFDP */
> - spi_nor_init_params(nor);
> + ret = spi_nor_init_params(nor);
> + if (ret)
> + return ret;
>
> if (!mtd->name)
> mtd->name = dev_name(dev);
> @@ -3087,12 +3109,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> mtd->type = MTD_NORFLASH;
> mtd->writesize = 1;
> mtd->flags = MTD_CAP_NORFLASH;
> - mtd->size = params->size;
> + mtd->size = nor->params->size;
> mtd->_erase = spi_nor_erase;
> mtd->_read = spi_nor_read;
> mtd->_resume = spi_nor_resume;
>
> - if (nor->params.locking_ops) {
> + if (nor->params->locking_ops) {
> mtd->_lock = spi_nor_lock;
> mtd->_unlock = spi_nor_unlock;
> mtd->_is_locked = spi_nor_is_locked;
> @@ -3115,7 +3137,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> mtd->flags |= MTD_NO_ERASE;
>
> mtd->dev.parent = dev;
> - nor->page_size = params->page_size;
> + nor->page_size = nor->params->page_size;
> mtd->writebufsize = nor->page_size;
>
> if (of_property_read_bool(np, "broken-flash-reset"))
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 3541a84c03d8..7654b6f3b966 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -11,6 +11,220 @@
>
> #define SPI_NOR_MAX_ID_LEN 6
>
> +enum spi_nor_option_flags {
> + SNOR_F_USE_FSR = BIT(0),
> + SNOR_F_HAS_SR_TB = BIT(1),
> + SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
> + SNOR_F_READY_XSR_RDY = BIT(3),
> + SNOR_F_USE_CLSR = BIT(4),
> + SNOR_F_BROKEN_RESET = BIT(5),
> + SNOR_F_4B_OPCODES = BIT(6),
> + SNOR_F_HAS_4BAIT = BIT(7),
> + SNOR_F_HAS_LOCK = BIT(8),
> + SNOR_F_HAS_16BIT_SR = BIT(9),
> + SNOR_F_NO_READ_CR = BIT(10),
> + SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
> +};
> +
> +struct spi_nor_read_command {
> + u8 num_mode_clocks;
> + u8 num_wait_states;
> + u8 opcode;
> + enum spi_nor_protocol proto;
> +};
> +
> +struct spi_nor_pp_command {
> + u8 opcode;
> + enum spi_nor_protocol proto;
> +};
> +
> +enum spi_nor_read_command_index {
> + SNOR_CMD_READ,
> + SNOR_CMD_READ_FAST,
> + SNOR_CMD_READ_1_1_1_DTR,
> +
> + /* Dual SPI */
> + SNOR_CMD_READ_1_1_2,
> + SNOR_CMD_READ_1_2_2,
> + SNOR_CMD_READ_2_2_2,
> + SNOR_CMD_READ_1_2_2_DTR,
> +
> + /* Quad SPI */
> + SNOR_CMD_READ_1_1_4,
> + SNOR_CMD_READ_1_4_4,
> + SNOR_CMD_READ_4_4_4,
> + SNOR_CMD_READ_1_4_4_DTR,
> +
> + /* Octal SPI */
> + SNOR_CMD_READ_1_1_8,
> + SNOR_CMD_READ_1_8_8,
> + SNOR_CMD_READ_8_8_8,
> + SNOR_CMD_READ_1_8_8_DTR,
> +
> + SNOR_CMD_READ_MAX
> +};
> +
> +enum spi_nor_pp_command_index {
> + SNOR_CMD_PP,
> +
> + /* Quad SPI */
> + SNOR_CMD_PP_1_1_4,
> + SNOR_CMD_PP_1_4_4,
> + SNOR_CMD_PP_4_4_4,
> +
> + /* Octal SPI */
> + SNOR_CMD_PP_1_1_8,
> + SNOR_CMD_PP_1_8_8,
> + SNOR_CMD_PP_8_8_8,
> +
> + SNOR_CMD_PP_MAX
> +};
> +
> +/**
> + * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> + * @size: the size of the sector/block erased by the erase type.
> + * JEDEC JESD216B imposes erase sizes to be a power of 2.
> + * @size_shift: @size is a power of 2, the shift is stored in
> + * @size_shift.
> + * @size_mask: the size mask based on @size_shift.
> + * @opcode: the SPI command op code to erase the sector/block.
> + * @idx: Erase Type index as sorted in the Basic Flash Parameter
> + * Table. It will be used to synchronize the supported
> + * Erase Types with the ones identified in the SFDP
> + * optional tables.
> + */
> +struct spi_nor_erase_type {
> + u32 size;
> + u32 size_shift;
> + u32 size_mask;
> + u8 opcode;
> + u8 idx;
> +};
> +
> +/**
> + * struct spi_nor_erase_command - Used for non-uniform erases
> + * The structure is used to describe a list of erase commands to be executed
> + * once we validate that the erase can be performed. The elements in the list
> + * are run-length encoded.
> + * @list: for inclusion into the list of erase commands.
> + * @count: how many times the same erase command should be
> + * consecutively used.
> + * @size: the size of the sector/block erased by the command.
> + * @opcode: the SPI command op code to erase the sector/block.
> + */
> +struct spi_nor_erase_command {
> + struct list_head list;
> + u32 count;
> + u32 size;
> + u8 opcode;
> +};
> +
> +/**
> + * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> + * @offset: the offset in the data array of erase region start.
> + * LSB bits are used as a bitmask encoding flags to
> + * determine if this region is overlaid, if this region is
> + * the last in the SPI NOR flash memory and to indicate
> + * all the supported erase commands inside this region.
> + * The erase types are sorted in ascending order with the
> + * smallest Erase Type size being at BIT(0).
> + * @size: the size of the region in bytes.
> + */
> +struct spi_nor_erase_region {
> + u64 offset;
> + u64 size;
> +};
> +
> +#define SNOR_ERASE_TYPE_MAX 4
> +#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> +
> +#define SNOR_LAST_REGION BIT(4)
> +#define SNOR_OVERLAID_REGION BIT(5)
> +
> +#define SNOR_ERASE_FLAGS_MAX 6
> +#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> +
> +/**
> + * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> + * @regions: array of erase regions. The regions are consecutive in
> + * address space. Walking through the regions is done
> + * incrementally.
> + * @uniform_region: a pre-allocated erase region for SPI NOR with a uniform
> + * sector size (legacy implementation).
> + * @erase_type: an array of erase types shared by all the regions.
> + * The erase types are sorted in ascending order, with the
> + * smallest Erase Type size being the first member in the
> + * erase_type array.
> + * @uniform_erase_type: bitmask encoding erase types that can erase the
> + * entire memory. This member is completed at init by
> + * uniform and non-uniform SPI NOR flash memories if they
> + * support at least one erase type that can erase the
> + * entire memory.
> + */
> +struct spi_nor_erase_map {
> + struct spi_nor_erase_region *regions;
> + struct spi_nor_erase_region uniform_region;
> + struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX];
> + u8 uniform_erase_type;
> +};
> +
> +/**
> + * struct spi_nor_locking_ops - SPI NOR locking methods
> + * @lock: lock a region of the SPI NOR.
> + * @unlock: unlock a region of the SPI NOR.
> + * @is_locked: check if a region of the SPI NOR is completely locked
> + */
> +struct spi_nor_locking_ops {
> + int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> + int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> + int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +};
> +
> +/**
> + * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> + * Includes legacy flash parameters and settings that can be overwritten
> + * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> + * Serial Flash Discoverable Parameters (SFDP) tables.
> + *
> + * @size: the flash memory density in bytes.
> + * @page_size: the page size of the SPI NOR flash memory.
> + * @hwcaps: describes the read and page program hardware
> + * capabilities.
> + * @reads: read capabilities ordered by priority: the higher index
> + * in the array, the higher priority.
> + * @page_programs: page program capabilities ordered by priority: the
> + * higher index in the array, the higher priority.
> + * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
> + * Table.
> + * @quad_enable: enables SPI NOR quad mode.
> + * @set_4byte: puts the SPI NOR in 4 byte addressing mode.
> + * @convert_addr: converts an absolute address into something the flash
> + * will understand. Particularly useful when pagesize is
> + * not a power-of-2.
> + * @setup: configures the SPI NOR memory. Useful for SPI NOR
> + * flashes that have peculiarities to the SPI NOR standard
> + * e.g. different opcodes, specific address calculation,
> + * page size, etc.
> + * @locking_ops: SPI NOR locking methods.
> + */
> +struct spi_nor_flash_parameter {
> + u64 size;
> + u32 page_size;
> +
> + struct spi_nor_hwcaps hwcaps;
> + struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
> + struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
> +
> + struct spi_nor_erase_map erase_map;
> +
> + int (*quad_enable)(struct spi_nor *nor);
> + int (*set_4byte)(struct spi_nor *nor, bool enable);
> + u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> + int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> +
> + const struct spi_nor_locking_ops *locking_ops;
> +};
> +
> /**
> * struct spi_nor_fixups - SPI NOR fixup hooks
> * @default_init: called after default flash parameters init. Used to tweak
> diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
> index 7930e4490dab..447d84bb2128 100644
> --- a/drivers/mtd/spi-nor/gigadevice.c
> +++ b/drivers/mtd/spi-nor/gigadevice.c
> @@ -16,7 +16,7 @@ static void gd25q256_default_init(struct spi_nor *nor)
> * indicate the quad_enable method for this case, we need
> * to set it in the default_init fixup hook.
> */
> - nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> }
>
> static struct spi_nor_fixups gd25q256_fixups = {
> diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
> index 3a1c34c41388..ffcb60e54a80 100644
> --- a/drivers/mtd/spi-nor/issi.c
> +++ b/drivers/mtd/spi-nor/issi.c
> @@ -68,7 +68,7 @@ static const struct flash_info issi_parts[] = {
>
> static void issi_default_init(struct spi_nor *nor)
> {
> - nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> }
>
> static const struct spi_nor_fixups issi_fixups = {
> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> index 1ae609c44676..d73bd0363144 100644
> --- a/drivers/mtd/spi-nor/macronix.c
> +++ b/drivers/mtd/spi-nor/macronix.c
> @@ -82,8 +82,8 @@ static const struct flash_info macronix_parts[] = {
>
> static void macronix_default_init(struct spi_nor *nor)
> {
> - nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> - nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> + nor->params->set_4byte = spi_nor_en4_ex4_set_4byte;
> }
>
> static const struct spi_nor_fixups macronix_fixups = {
> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> index 8017ca58b3a5..5be817d2f27c 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -106,8 +106,8 @@ static void micron_st_default_init(struct spi_nor *nor)
> {
> nor->flags |= SNOR_F_HAS_LOCK;
> nor->flags &= ~SNOR_F_HAS_16BIT_SR;
> - nor->params.quad_enable = NULL;
> - nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
> + nor->params->quad_enable = NULL;
> + nor->params->set_4byte = spi_nor_en4_ex4_wen_set_4byte;
> }
>
> static const struct spi_nor_fixups micron_st_fixups = {
> diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
> index b790c3ec871f..6829dc7e4f74 100644
> --- a/drivers/mtd/spi-nor/sfdp.c
> +++ b/drivers/mtd/spi-nor/sfdp.c
> @@ -734,6 +734,16 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
> return ret;
> }
>
> +static void spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> +{
> + region->offset |= SNOR_LAST_REGION;
> +}
> +
> +static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> +{
> + region->offset |= SNOR_OVERLAID_REGION;
> +}
> +
> /**
> * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
> * @region: pointer to a structure that describes a SPI NOR erase region
> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> index 16683983a20e..6756202ace4b 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -74,7 +74,7 @@ static const struct flash_info spansion_parts[] = {
>
> static void spansion_post_sfdp_fixups(struct spi_nor *nor)
> {
> - if (nor->params.size <= SZ_16M)
> + if (nor->params->size <= SZ_16M)
> return;
>
> nor->flags |= SNOR_F_4B_OPCODES;
> diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
> index 1e77dffbf729..f15be50024d1 100644
> --- a/drivers/mtd/spi-nor/winbond.c
> +++ b/drivers/mtd/spi-nor/winbond.c
> @@ -97,7 +97,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)
>
> static void winbond_default_init(struct spi_nor *nor)
> {
> - nor->params.set_4byte = winbond_set_4byte;
> + nor->params->set_4byte = winbond_set_4byte;
> }
>
> static const struct spi_nor_fixups winbond_fixups = {
> diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
> index fcf635d89f65..1138bdbf4199 100644
> --- a/drivers/mtd/spi-nor/xilinx.c
> +++ b/drivers/mtd/spi-nor/xilinx.c
> @@ -70,7 +70,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
> nor->mtd.erasesize = 8 * nor->page_size;
> } else {
> /* Flash in Default addressing mode */
> - nor->params.convert_addr = s3an_convert_addr;
> + nor->params->convert_addr = s3an_convert_addr;
> nor->mtd.erasesize = nor->info->sector_size;
> }
>
> @@ -79,7 +79,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
>
> static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
> {
> - nor->params.setup = xilinx_nor_setup;
> + nor->params->setup = xilinx_nor_setup;
> }
>
> static const struct spi_nor_fixups xilinx_fixups = {
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index dde2988a809e..d3d34c4eea48 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -227,110 +227,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
> return spi_nor_get_protocol_data_nbits(proto);
> }
>
> -enum spi_nor_option_flags {
> - SNOR_F_USE_FSR = BIT(0),
> - SNOR_F_HAS_SR_TB = BIT(1),
> - SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
> - SNOR_F_READY_XSR_RDY = BIT(3),
> - SNOR_F_USE_CLSR = BIT(4),
> - SNOR_F_BROKEN_RESET = BIT(5),
> - SNOR_F_4B_OPCODES = BIT(6),
> - SNOR_F_HAS_4BAIT = BIT(7),
> - SNOR_F_HAS_LOCK = BIT(8),
> - SNOR_F_HAS_16BIT_SR = BIT(9),
> - SNOR_F_NO_READ_CR = BIT(10),
> - SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
> -
> -};
> -
> -/**
> - * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> - * @size: the size of the sector/block erased by the erase type.
> - * JEDEC JESD216B imposes erase sizes to be a power of 2.
> - * @size_shift: @size is a power of 2, the shift is stored in
> - * @size_shift.
> - * @size_mask: the size mask based on @size_shift.
> - * @opcode: the SPI command op code to erase the sector/block.
> - * @idx: Erase Type index as sorted in the Basic Flash Parameter
> - * Table. It will be used to synchronize the supported
> - * Erase Types with the ones identified in the SFDP
> - * optional tables.
> - */
> -struct spi_nor_erase_type {
> - u32 size;
> - u32 size_shift;
> - u32 size_mask;
> - u8 opcode;
> - u8 idx;
> -};
> -
> -/**
> - * struct spi_nor_erase_command - Used for non-uniform erases
> - * The structure is used to describe a list of erase commands to be executed
> - * once we validate that the erase can be performed. The elements in the list
> - * are run-length encoded.
> - * @list: for inclusion into the list of erase commands.
> - * @count: how many times the same erase command should be
> - * consecutively used.
> - * @size: the size of the sector/block erased by the command.
> - * @opcode: the SPI command op code to erase the sector/block.
> - */
> -struct spi_nor_erase_command {
> - struct list_head list;
> - u32 count;
> - u32 size;
> - u8 opcode;
> -};
> -
> -/**
> - * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> - * @offset: the offset in the data array of erase region start.
> - * LSB bits are used as a bitmask encoding flags to
> - * determine if this region is overlaid, if this region is
> - * the last in the SPI NOR flash memory and to indicate
> - * all the supported erase commands inside this region.
> - * The erase types are sorted in ascending order with the
> - * smallest Erase Type size being at BIT(0).
> - * @size: the size of the region in bytes.
> - */
> -struct spi_nor_erase_region {
> - u64 offset;
> - u64 size;
> -};
> -
> -#define SNOR_ERASE_TYPE_MAX 4
> -#define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> -
> -#define SNOR_LAST_REGION BIT(4)
> -#define SNOR_OVERLAID_REGION BIT(5)
> -
> -#define SNOR_ERASE_FLAGS_MAX 6
> -#define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> -
> -/**
> - * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> - * @regions: array of erase regions. The regions are consecutive in
> - * address space. Walking through the regions is done
> - * incrementally.
> - * @uniform_region: a pre-allocated erase region for SPI NOR with a uniform
> - * sector size (legacy implementation).
> - * @erase_type: an array of erase types shared by all the regions.
> - * The erase types are sorted in ascending order, with the
> - * smallest Erase Type size being the first member in the
> - * erase_type array.
> - * @uniform_erase_type: bitmask encoding erase types that can erase the
> - * entire memory. This member is completed at init by
> - * uniform and non-uniform SPI NOR flash memories if they
> - * support at least one erase type that can erase the
> - * entire memory.
> - */
> -struct spi_nor_erase_map {
> - struct spi_nor_erase_region *regions;
> - struct spi_nor_erase_region uniform_region;
> - struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX];
> - u8 uniform_erase_type;
> -};
> -
> /**
> * struct spi_nor_hwcaps - Structure for describing the hardware capabilies
> * supported by the SPI controller (bus master).
> @@ -406,61 +302,7 @@ struct spi_nor_hwcaps {
> #define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \
> SNOR_HWCAPS_PP_MASK)
>
> -struct spi_nor_read_command {
> - u8 num_mode_clocks;
> - u8 num_wait_states;
> - u8 opcode;
> - enum spi_nor_protocol proto;
> -};
> -
> -struct spi_nor_pp_command {
> - u8 opcode;
> - enum spi_nor_protocol proto;
> -};
> -
> -enum spi_nor_read_command_index {
> - SNOR_CMD_READ,
> - SNOR_CMD_READ_FAST,
> - SNOR_CMD_READ_1_1_1_DTR,
> -
> - /* Dual SPI */
> - SNOR_CMD_READ_1_1_2,
> - SNOR_CMD_READ_1_2_2,
> - SNOR_CMD_READ_2_2_2,
> - SNOR_CMD_READ_1_2_2_DTR,
> -
> - /* Quad SPI */
> - SNOR_CMD_READ_1_1_4,
> - SNOR_CMD_READ_1_4_4,
> - SNOR_CMD_READ_4_4_4,
> - SNOR_CMD_READ_1_4_4_DTR,
> -
> - /* Octal SPI */
> - SNOR_CMD_READ_1_1_8,
> - SNOR_CMD_READ_1_8_8,
> - SNOR_CMD_READ_8_8_8,
> - SNOR_CMD_READ_1_8_8_DTR,
> -
> - SNOR_CMD_READ_MAX
> -};
> -
> -enum spi_nor_pp_command_index {
> - SNOR_CMD_PP,
> -
> - /* Quad SPI */
> - SNOR_CMD_PP_1_1_4,
> - SNOR_CMD_PP_1_4_4,
> - SNOR_CMD_PP_4_4_4,
> -
> - /* Octal SPI */
> - SNOR_CMD_PP_1_1_8,
> - SNOR_CMD_PP_1_8_8,
> - SNOR_CMD_PP_8_8_8,
> -
> - SNOR_CMD_PP_MAX
> -};
> -
> -/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
> +/* Forward declaration that is used in 'struct spi_nor_controller_ops' */
> struct spi_nor;
>
> /**
> @@ -491,74 +333,14 @@ struct spi_nor_controller_ops {
> int (*erase)(struct spi_nor *nor, loff_t offs);
> };
>
> -/**
> - * struct spi_nor_locking_ops - SPI NOR locking methods
> - * @lock: lock a region of the SPI NOR.
> - * @unlock: unlock a region of the SPI NOR.
> - * @is_locked: check if a region of the SPI NOR is completely locked
> - */
> -struct spi_nor_locking_ops {
> - int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> - int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> - int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -};
> -
> -/**
> - * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> - * Includes legacy flash parameters and settings that can be overwritten
> - * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> - * Serial Flash Discoverable Parameters (SFDP) tables.
> - *
> - * @size: the flash memory density in bytes.
> - * @page_size: the page size of the SPI NOR flash memory.
> - * @hwcaps: describes the read and page program hardware
> - * capabilities.
> - * @reads: read capabilities ordered by priority: the higher index
> - * in the array, the higher priority.
> - * @page_programs: page program capabilities ordered by priority: the
> - * higher index in the array, the higher priority.
> - * @erase_map: the erase map parsed from the SFDP Sector Map Parameter
> - * Table.
> - * @quad_enable: enables SPI NOR quad mode.
> - * @set_4byte: puts the SPI NOR in 4 byte addressing mode.
> - * @convert_addr: converts an absolute address into something the flash
> - * will understand. Particularly useful when pagesize is
> - * not a power-of-2.
> - * @setup: configures the SPI NOR memory. Useful for SPI NOR
> - * flashes that have peculiarities to the SPI NOR standard
> - * e.g. different opcodes, specific address calculation,
> - * page size, etc.
> - * @locking_ops: SPI NOR locking methods.
> - */
> -struct spi_nor_flash_parameter {
> - u64 size;
> - u32 page_size;
> -
> - struct spi_nor_hwcaps hwcaps;
> - struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
> - struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
>
> - struct spi_nor_erase_map erase_map;
> -
> - int (*quad_enable)(struct spi_nor *nor);
> - int (*set_4byte)(struct spi_nor *nor, bool enable);
> - u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> - int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> -
> - const struct spi_nor_locking_ops *locking_ops;
> -};
> -
> -/**
> - * struct flash_info - Forward declaration of a structure used internally by
> - * spi_nor_scan()
> +/*
> + * Forward declarations that are used internally by the core and manufacturer
> + * drivers.
> */
> struct flash_info;
> -
> -/**
> - * struct spi_nor_manufacturer - Forward declaration of a structure used
> - * internally by the core and manufacturer drivers.
> - */
> struct spi_nor_manufacturer;
> +struct spi_nor_flash_parameter;
>
> /**
> * struct spi_nor - Structure for defining a the SPI NOR layer
> @@ -613,7 +395,7 @@ struct spi_nor {
>
> const struct spi_nor_controller_ops *controller_ops;
>
> - struct spi_nor_flash_parameter params;
> + struct spi_nor_flash_parameter *params;
>
> struct {
> struct spi_mem_dirmap_desc *rdesc;
> @@ -623,35 +405,6 @@ struct spi_nor {
> void *priv;
> };
>
> -static u64 __maybe_unused
> -spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> -{
> - return region->offset & SNOR_LAST_REGION;
> -}
> -
> -static u64 __maybe_unused
> -spi_nor_region_end(const struct spi_nor_erase_region *region)
> -{
> - return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> -{
> - region->offset |= SNOR_LAST_REGION;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> -{
> - region->offset |= SNOR_OVERLAID_REGION;
> -}
> -
> -static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
> -{
> - return !!nor->params.erase_map.uniform_erase_type;
> -}
> -
> static inline void spi_nor_set_flash_node(struct spi_nor *nor,
> struct device_node *np)
> {
>

--
Regards
Vignesh

2020-03-13 08:28:19

by Tudor Ambarus

[permalink] [raw]
Subject: Re: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h

On Friday, March 13, 2020 10:13:17 AM EET Vignesh Raghavendra wrote:
> Should we drop SNOR_MFR_* macros as well or do you see a neeed for them?

Good catch. Cross-manufacturer code is unlikely and discouraged, we should get
rid of them.

Cheers,
ta