[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200302180730.1886678-24-tudor.ambarus@microchip.com>
Date: Mon, 2 Mar 2020 18:07:57 +0000
From: <Tudor.Ambarus@...rochip.com>
To: <bbrezillon@...nel.org>, <vigneshr@...com>,
<linux-mtd@...ts.infradead.org>
CC: <miquel.raynal@...tlin.com>, <richard@....at>, <joel@....id.au>,
<andrew@...id.au>, <Nicolas.Ferre@...rochip.com>,
<alexandre.belloni@...tlin.com>, <Ludovic.Desroches@...rochip.com>,
<matthias.bgg@...il.com>, <vz@...ia.com>,
<michal.simek@...inx.com>, <ludovic.barre@...com>,
<john.garry@...wei.com>, <tglx@...utronix.de>,
<nishkadg.linux@...il.com>, <michael@...le.cc>,
<dinguyen@...nel.org>, <thor.thayer@...ux.intel.com>,
<swboyd@...omium.org>, <opensource@...ayne.com>,
<mika.westerberg@...ux.intel.com>, <kstewart@...uxfoundation.org>,
<allison@...utok.net>, <jethro@...tanix.com>, <info@...ux.net>,
<alexander.sverdlin@...ia.com>, <rfontana@...hat.com>,
<linux-kernel@...r.kernel.org>,
<linux-mediatek@...ts.infradead.org>,
<linux-aspeed@...ts.ozlabs.org>,
<linux-arm-kernel@...ts.infradead.org>,
<Tudor.Ambarus@...rochip.com>
Subject: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h
From: Tudor Ambarus <tudor.ambarus@...rochip.com>
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 <tudor.ambarus@...rochip.com>
---
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 = ¶ms->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
Powered by blists - more mailing lists