Commit c4687217 authored by Tudor Ambarus's avatar Tudor Ambarus

mtd: spi-nor: Move erase_map to 'struct spi_nor_flash_parameter'

All flash parameters and settings should reside inside
'struct spi_nor_flash_parameter'. Move the SMPT parsed erase map
from 'struct spi_nor' to 'struct spi_nor_flash_parameter'.

Please note that there is a roll-back mechanism for the flash
parameter and settings, for cases when SFDP parser fails. The SFDP
parser receives a Stack allocated copy of nor->params, called
sfdp_params, and uses it to retrieve the serial flash discoverable
parameters. JESD216 SFDP is a standard and has a higher priority
than the default initialized flash parameters, so will overwrite the
sfdp_params data when needed. All SFDP code uses the local copy of
nor->params, that will overwrite it in the end, if the parser succeds.

Saving and restoring the nor->params.erase_map is no longer needed,
since the SFDP code does not touch it.
Signed-off-by: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: default avatarBoris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: default avatarVignesh Raghavendra <vigneshr@ti.com>
parent 42f59947
...@@ -600,7 +600,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) ...@@ -600,7 +600,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode); nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
if (!spi_nor_has_uniform_erase(nor)) { if (!spi_nor_has_uniform_erase(nor)) {
struct spi_nor_erase_map *map = &nor->erase_map; struct spi_nor_erase_map *map = &nor->params.erase_map;
struct spi_nor_erase_type *erase; struct spi_nor_erase_type *erase;
int i; int i;
...@@ -1133,7 +1133,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, ...@@ -1133,7 +1133,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
struct list_head *erase_list, struct list_head *erase_list,
u64 addr, u32 len) u64 addr, u32 len)
{ {
const struct spi_nor_erase_map *map = &nor->erase_map; const struct spi_nor_erase_map *map = &nor->params.erase_map;
const struct spi_nor_erase_type *erase, *prev_erase = NULL; const struct spi_nor_erase_type *erase, *prev_erase = NULL;
struct spi_nor_erase_region *region; struct spi_nor_erase_region *region;
struct spi_nor_erase_command *cmd = NULL; struct spi_nor_erase_command *cmd = NULL;
...@@ -3328,7 +3328,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, ...@@ -3328,7 +3328,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header, const struct sfdp_parameter_header *bfpt_header,
struct spi_nor_flash_parameter *params) struct spi_nor_flash_parameter *params)
{ {
struct spi_nor_erase_map *map = &nor->erase_map; struct spi_nor_erase_map *map = &params->erase_map;
struct spi_nor_erase_type *erase_type = map->erase_type; struct spi_nor_erase_type *erase_type = map->erase_type;
struct sfdp_bfpt bfpt; struct sfdp_bfpt bfpt;
size_t len; size_t len;
...@@ -3409,7 +3409,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, ...@@ -3409,7 +3409,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
* Erase Types defined in the bfpt table. * Erase Types defined in the bfpt table.
*/ */
erase_mask = 0; erase_mask = 0;
memset(&nor->erase_map, 0, sizeof(nor->erase_map)); memset(&params->erase_map, 0, sizeof(params->erase_map));
for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) { for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) {
const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i]; const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i];
u32 erasesize; u32 erasesize;
...@@ -3684,14 +3684,18 @@ spi_nor_region_check_overlay(struct spi_nor_erase_region *region, ...@@ -3684,14 +3684,18 @@ spi_nor_region_check_overlay(struct spi_nor_erase_region *region,
/** /**
* spi_nor_init_non_uniform_erase_map() - initialize the non-uniform erase map * spi_nor_init_non_uniform_erase_map() - initialize the non-uniform erase map
* @nor: pointer to a 'struct spi_nor' * @nor: pointer to a 'struct spi_nor'
* @params: pointer to a duplicate 'struct spi_nor_flash_parameter' that is
* used for storing SFDP parsed data
* @smpt: pointer to the sector map parameter table * @smpt: pointer to the sector map parameter table
* *
* Return: 0 on success, -errno otherwise. * Return: 0 on success, -errno otherwise.
*/ */
static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, static int
const u32 *smpt) spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
struct spi_nor_flash_parameter *params,
const u32 *smpt)
{ {
struct spi_nor_erase_map *map = &nor->erase_map; struct spi_nor_erase_map *map = &params->erase_map;
struct spi_nor_erase_type *erase = map->erase_type; struct spi_nor_erase_type *erase = map->erase_type;
struct spi_nor_erase_region *region; struct spi_nor_erase_region *region;
u64 offset; u64 offset;
...@@ -3770,6 +3774,8 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, ...@@ -3770,6 +3774,8 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
* spi_nor_parse_smpt() - parse Sector Map Parameter Table * spi_nor_parse_smpt() - parse Sector Map Parameter Table
* @nor: pointer to a 'struct spi_nor' * @nor: pointer to a 'struct spi_nor'
* @smpt_header: sector map parameter table header * @smpt_header: sector map parameter table header
* @params: pointer to a duplicate 'struct spi_nor_flash_parameter'
* that is used for storing SFDP parsed data
* *
* This table is optional, but when available, we parse it to identify the * This table is optional, but when available, we parse it to identify the
* location and size of sectors within the main data array of the flash memory * location and size of sectors within the main data array of the flash memory
...@@ -3778,7 +3784,8 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, ...@@ -3778,7 +3784,8 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
* Return: 0 on success, -errno otherwise. * Return: 0 on success, -errno otherwise.
*/ */
static int spi_nor_parse_smpt(struct spi_nor *nor, static int spi_nor_parse_smpt(struct spi_nor *nor,
const struct sfdp_parameter_header *smpt_header) const struct sfdp_parameter_header *smpt_header,
struct spi_nor_flash_parameter *params)
{ {
const u32 *sector_map; const u32 *sector_map;
u32 *smpt; u32 *smpt;
...@@ -3807,11 +3814,11 @@ static int spi_nor_parse_smpt(struct spi_nor *nor, ...@@ -3807,11 +3814,11 @@ static int spi_nor_parse_smpt(struct spi_nor *nor,
goto out; goto out;
} }
ret = spi_nor_init_non_uniform_erase_map(nor, sector_map); ret = spi_nor_init_non_uniform_erase_map(nor, params, sector_map);
if (ret) if (ret)
goto out; goto out;
spi_nor_regions_sort_erase_types(&nor->erase_map); spi_nor_regions_sort_erase_types(&params->erase_map);
/* fall through */ /* fall through */
out: out:
kfree(smpt); kfree(smpt);
...@@ -3867,7 +3874,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, ...@@ -3867,7 +3874,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor,
{ 0u /* not used */, BIT(12) }, { 0u /* not used */, BIT(12) },
}; };
struct spi_nor_pp_command *params_pp = params->page_programs; struct spi_nor_pp_command *params_pp = params->page_programs;
struct spi_nor_erase_map *map = &nor->erase_map; struct spi_nor_erase_map *map = &params->erase_map;
struct spi_nor_erase_type *erase_type = map->erase_type; struct spi_nor_erase_type *erase_type = map->erase_type;
u32 *dwords; u32 *dwords;
size_t len; size_t len;
...@@ -4097,7 +4104,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, ...@@ -4097,7 +4104,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
switch (SFDP_PARAM_HEADER_ID(param_header)) { switch (SFDP_PARAM_HEADER_ID(param_header)) {
case SFDP_SECTOR_MAP_ID: case SFDP_SECTOR_MAP_ID:
err = spi_nor_parse_smpt(nor, param_header); err = spi_nor_parse_smpt(nor, param_header, params);
break; break;
case SFDP_4BAIT_ID: case SFDP_4BAIT_ID:
...@@ -4129,7 +4136,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, ...@@ -4129,7 +4136,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
static int spi_nor_init_params(struct spi_nor *nor) static int spi_nor_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 = &nor->erase_map; struct spi_nor_erase_map *map = &params->erase_map;
const struct flash_info *info = nor->info; const struct flash_info *info = nor->info;
u8 i, erase_mask; u8 i, erase_mask;
...@@ -4229,17 +4236,12 @@ static int spi_nor_init_params(struct spi_nor *nor) ...@@ -4229,17 +4236,12 @@ static int spi_nor_init_params(struct spi_nor *nor)
if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) &&
!(info->flags & SPI_NOR_SKIP_SFDP)) { !(info->flags & SPI_NOR_SKIP_SFDP)) {
struct spi_nor_flash_parameter sfdp_params; struct spi_nor_flash_parameter sfdp_params;
struct spi_nor_erase_map prev_map;
memcpy(&sfdp_params, params, sizeof(sfdp_params)); memcpy(&sfdp_params, params, sizeof(sfdp_params));
memcpy(&prev_map, &nor->erase_map, sizeof(prev_map));
if (spi_nor_parse_sfdp(nor, &sfdp_params)) { if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
nor->addr_width = 0; nor->addr_width = 0;
nor->flags &= ~SNOR_F_4B_OPCODES; nor->flags &= ~SNOR_F_4B_OPCODES;
/* restore previous erase map */
memcpy(&nor->erase_map, &prev_map,
sizeof(nor->erase_map));
} else { } else {
memcpy(params, &sfdp_params, sizeof(*params)); memcpy(params, &sfdp_params, sizeof(*params));
} }
...@@ -4353,7 +4355,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map, ...@@ -4353,7 +4355,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
static int spi_nor_select_erase(struct spi_nor *nor, u32 wanted_size) static int spi_nor_select_erase(struct spi_nor *nor, u32 wanted_size)
{ {
struct spi_nor_erase_map *map = &nor->erase_map; struct spi_nor_erase_map *map = &nor->params.erase_map;
const struct spi_nor_erase_type *erase = NULL; const struct spi_nor_erase_type *erase = NULL;
struct mtd_info *mtd = &nor->mtd; struct mtd_info *mtd = &nor->mtd;
int i; int i;
......
...@@ -479,6 +479,8 @@ struct spi_nor; ...@@ -479,6 +479,8 @@ struct spi_nor;
* in the array, the higher priority. * in the array, the higher priority.
* @page_programs: page program capabilities ordered by priority: the * @page_programs: page program capabilities ordered by priority: the
* higher index in the array, the higher priority. * 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. * @quad_enable: enables SPI NOR quad mode.
*/ */
struct spi_nor_flash_parameter { struct spi_nor_flash_parameter {
...@@ -489,6 +491,8 @@ struct spi_nor_flash_parameter { ...@@ -489,6 +491,8 @@ struct spi_nor_flash_parameter {
struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
struct spi_nor_pp_command page_programs[SNOR_CMD_PP_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 (*quad_enable)(struct spi_nor *nor);
}; };
...@@ -519,7 +523,6 @@ struct flash_info; ...@@ -519,7 +523,6 @@ struct flash_info;
* @read_proto: the SPI protocol for read operations * @read_proto: the SPI protocol for read operations
* @write_proto: the SPI protocol for write operations * @write_proto: the SPI protocol for write operations
* @reg_proto the SPI protocol for read_reg/write_reg/erase operations * @reg_proto the SPI protocol for read_reg/write_reg/erase operations
* @erase_map: the erase map of the SPI NOR
* @prepare: [OPTIONAL] do some preparations for the * @prepare: [OPTIONAL] do some preparations for the
* read/write/erase/lock/unlock operations * read/write/erase/lock/unlock operations
* @unprepare: [OPTIONAL] do some post work after the * @unprepare: [OPTIONAL] do some post work after the
...@@ -562,7 +565,6 @@ struct spi_nor { ...@@ -562,7 +565,6 @@ struct spi_nor {
enum spi_nor_protocol reg_proto; enum spi_nor_protocol reg_proto;
bool sst_write_second; bool sst_write_second;
u32 flags; u32 flags;
struct spi_nor_erase_map erase_map;
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
...@@ -610,7 +612,7 @@ spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) ...@@ -610,7 +612,7 @@ spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor) static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
{ {
return !!nor->erase_map.uniform_erase_type; return !!nor->params.erase_map.uniform_erase_type;
} }
static inline void spi_nor_set_flash_node(struct spi_nor *nor, static inline void spi_nor_set_flash_node(struct spi_nor *nor,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment