diff options
author | Takahiro Kuwano <Takahiro.Kuwano@infineon.com> | 2024-02-20 17:34:06 +0900 |
---|---|---|
committer | Tudor Ambarus <tudor.ambarus@linaro.org> | 2024-02-26 12:35:05 +0200 |
commit | 0e164238bb0752e341f01639438c35822d4488b2 (patch) | |
tree | 8a59d5df8530dfcd300d96e83bca6fcbdadf0156 /drivers/mtd | |
parent | a956502aa844a20a794a47f76c0f760f593fc97a (diff) |
mtd: spi-nor: core: rework struct spi_nor_erase_region
Encoding bitmask flags into offset worsen the code readability. The
erase type mask and flags should be stored in dedicated members. Also,
erase_map.uniform_erase_type can be removed as it is redundant.
Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Suggested-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Michael Walle <mwalle@kernel.org>
Link: https://lore.kernel.org/r/8e5e9e4081ed9f16ea9dce30693304a4b54d19b1.1708404584.git.Takahiro.Kuwano@infineon.com
[ta: remove spi_nor_region_end()]
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/spi-nor/core.c | 42 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/core.h | 28 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/debugfs.c | 13 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/sfdp.c | 30 |
4 files changed, 46 insertions, 67 deletions
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 4129764fad8c..d526e555e7b3 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1158,7 +1158,7 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode) static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) { - return !!nor->params->erase_map.uniform_erase_type; + return !!nor->params->erase_map.uniform_region.erase_mask; } static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) @@ -1542,7 +1542,6 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, const struct spi_nor_erase_type *erase; u32 rem; int i; - u8 erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; /* * Erase types are ordered by size, with the smallest erase type at @@ -1550,7 +1549,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, */ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { /* Does the erase region support the tested erase type? */ - if (!(erase_mask & BIT(i))) + if (!(region->erase_mask & BIT(i))) continue; erase = &map->erase_type[i]; @@ -1558,7 +1557,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, continue; /* Alignment is not mandatory for overlaid regions */ - if (region->offset & SNOR_OVERLAID_REGION && + if (region->flags & SNOR_OVERLAID_REGION && region->size <= len) return erase; @@ -1576,12 +1575,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, 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; + return region->flags & SNOR_LAST_REGION; } /** @@ -1612,16 +1606,14 @@ static struct spi_nor_erase_region * spi_nor_find_erase_region(const struct spi_nor_erase_map *map, u64 addr) { struct spi_nor_erase_region *region = map->regions; - u64 region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; - u64 region_end = region_start + region->size; + u64 region_end = region->offset + region->size; - while (addr < region_start || addr >= region_end) { + while (addr < region->offset || addr >= region_end) { region = spi_nor_region_next(region); if (!region) return ERR_PTR(-EINVAL); - region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; - region_end = region_start + region->size; + region_end = region->offset + region->size; } return region; @@ -1649,7 +1641,7 @@ spi_nor_init_erase_cmd(const struct spi_nor_erase_region *region, cmd->opcode = erase->opcode; cmd->count = 1; - if (region->offset & SNOR_OVERLAID_REGION) + if (region->flags & SNOR_OVERLAID_REGION) cmd->size = region->size; else cmd->size = erase->size; @@ -1699,7 +1691,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, if (IS_ERR(region)) return PTR_ERR(region); - region_end = spi_nor_region_end(region); + region_end = region->offset + region->size; while (len) { erase = spi_nor_find_best_erase_type(map, region, addr, len); @@ -1708,7 +1700,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, if (prev_erase != erase || erase->size != cmd->size || - region->offset & SNOR_OVERLAID_REGION) { + region->flags & SNOR_OVERLAID_REGION) { cmd = spi_nor_init_erase_cmd(region, erase); if (IS_ERR(cmd)) { ret = PTR_ERR(cmd); @@ -1727,7 +1719,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, region = spi_nor_region_next(region); if (!region) goto destroy_erase_cmd_list; - region_end = spi_nor_region_end(region); + region_end = region->offset + region->size; } prev_erase = erase; @@ -2468,12 +2460,11 @@ void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase) void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, u8 erase_mask, u64 flash_size) { - /* Offset 0 with erase_mask and SNOR_LAST_REGION bit set */ - map->uniform_region.offset = (erase_mask & SNOR_ERASE_TYPE_MASK) | - SNOR_LAST_REGION; + map->uniform_region.offset = 0; map->uniform_region.size = flash_size; + map->uniform_region.erase_mask = erase_mask; + map->uniform_region.flags = SNOR_LAST_REGION; map->regions = &map->uniform_region; - map->uniform_erase_type = erase_mask; } int spi_nor_post_bfpt_fixups(struct spi_nor *nor, @@ -2560,7 +2551,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map) { const struct spi_nor_erase_type *tested_erase, *erase = NULL; int i; - u8 uniform_erase_type = map->uniform_erase_type; + u8 uniform_erase_type = map->uniform_region.erase_mask; /* * Search for the biggest erase size, except for when compiled @@ -2599,8 +2590,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map) return NULL; /* Disable all other Sector Erase commands. */ - map->uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK; - map->uniform_erase_type |= BIT(erase - map->erase_type); + map->uniform_region.erase_mask = BIT(erase - map->erase_type); return erase; } diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index d36c0e072954..f68ae2fc4a1f 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -240,27 +240,25 @@ struct spi_nor_erase_command { /** * 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. + * @erase_mask: bitmask 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). + * @flags: flags to determine if this region is overlaid, if this + * region is the last in the SPI NOR flash memory */ struct spi_nor_erase_region { u64 offset; u64 size; + u8 erase_mask; + u8 flags; }; #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) +#define SNOR_LAST_REGION BIT(0) +#define SNOR_OVERLAID_REGION BIT(1) /** * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map @@ -273,17 +271,11 @@ struct spi_nor_erase_region { * 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; }; /** diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index 2dbda6b6938a..d20bbb531a88 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -147,16 +147,17 @@ static int spi_nor_params_show(struct seq_file *s, void *data) for (region = erase_map->regions; region; region = spi_nor_region_next(region)) { - u64 start = region->offset & ~SNOR_ERASE_FLAGS_MASK; - u64 flags = region->offset & SNOR_ERASE_FLAGS_MASK; + u64 start = region->offset; u64 end = start + region->size - 1; + u8 erase_mask = region->erase_mask; + u8 flags = region->flags; seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", start, end, - flags & BIT(0) ? '0' : ' ', - flags & BIT(1) ? '1' : ' ', - flags & BIT(2) ? '2' : ' ', - flags & BIT(3) ? '3' : ' ', + erase_mask & BIT(0) ? '0' : ' ', + erase_mask & BIT(1) ? '1' : ' ', + erase_mask & BIT(2) ? '2' : ' ', + erase_mask & BIT(3) ? '3' : ' ', flags & SNOR_OVERLAID_REGION ? "overlaid" : ""); } diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 57713de32832..3cf1db6e4026 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -389,17 +389,14 @@ static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask) static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map) { struct spi_nor_erase_region *region = map->regions; - u8 region_erase_mask, sorted_erase_mask; + u8 sorted_erase_mask; while (region) { - region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; - sorted_erase_mask = spi_nor_sort_erase_mask(map, - region_erase_mask); + region->erase_mask); /* Overwrite erase mask. */ - region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) | - sorted_erase_mask; + region->erase_mask = sorted_erase_mask; region = spi_nor_region_next(region); } @@ -554,8 +551,6 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, * selecting the uniform erase. */ spi_nor_regions_sort_erase_types(map); - map->uniform_erase_type = map->uniform_region.offset & - SNOR_ERASE_TYPE_MASK; /* Stop here if not JESD216 rev A or later. */ if (bfpt_header->length == BFPT_DWORD_MAX_JESD216) @@ -808,12 +803,12 @@ out: static void spi_nor_region_mark_end(struct spi_nor_erase_region *region) { - region->offset |= SNOR_LAST_REGION; + region->flags |= SNOR_LAST_REGION; } static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) { - region->offset |= SNOR_OVERLAID_REGION; + region->flags |= SNOR_OVERLAID_REGION; } /** @@ -875,9 +870,10 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, /* Populate regions. */ for (i = 0; i < region_count; i++) { j = i + 1; /* index for the region dword */ + region[i].offset = offset; region[i].size = SMPT_MAP_REGION_SIZE(smpt[j]); erase_type = SMPT_MAP_REGION_ERASE_TYPE(smpt[j]); - region[i].offset = offset | erase_type; + region[i].erase_mask = erase_type; spi_nor_region_check_overlay(®ion[i], erase, erase_type); @@ -893,21 +889,21 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, */ regions_erase_type |= erase_type; - offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) + - region[i].size; + offset = region[i].offset + region[i].size; } spi_nor_region_mark_end(®ion[i - 1]); - save_uniform_erase_type = map->uniform_erase_type; - map->uniform_erase_type = spi_nor_sort_erase_mask(map, - uniform_erase_type); + save_uniform_erase_type = map->uniform_region.erase_mask; + map->uniform_region.erase_mask = + spi_nor_sort_erase_mask(map, + uniform_erase_type); if (!regions_erase_type) { /* * Roll back to the previous uniform_erase_type mask, SMPT is * broken. */ - map->uniform_erase_type = save_uniform_erase_type; + map->uniform_region.erase_mask = save_uniform_erase_type; return -EINVAL; } |