Skip to content

Commit 3011fe9

Browse files
committed
mtd: spi-nor: fix selection of uniform erase type in flexible conf
There are uniform, non-uniform and flexible erase flash configurations. The non-uniform erase types, are the erase types that can _not_ erase the entire flash by their own. As the code was, in case flashes had flexible erase capabilities (support both uniform and non-uniform erase types in the same flash configuration) and supported multiple uniform erase type sizes, the code did not sort the uniform erase types, and could select a wrong erase type size. Sort the uniform erase mask in case of flexible erase flash configurations, in order to select the best uniform erase type size. Uniform, non-uniform, and flexible configurations with just a valid uniform erase type, are not affected by this change. Uniform erase tested on mx25l3273fm2i-08g and sst26vf064B-104i/sn. Non uniform erase tested on sst26vf064B-104i/sn. Fixes: 5390a8d ("mtd: spi-nor: add support to non-uniform SFDP SPI NOR flash memories") Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> (cherry picked from commit e8828ec) Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
1 parent 75d2a97 commit 3011fe9

1 file changed

Lines changed: 36 additions & 11 deletions

File tree

drivers/mtd/spi-nor/spi-nor.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,6 +2469,34 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
24692469
return left->size - right->size;
24702470
}
24712471

2472+
/**
2473+
* spi_nor_sort_erase_mask() - sort erase mask
2474+
* @map: the erase map of the SPI NOR
2475+
* @erase_mask: the erase type mask to be sorted
2476+
*
2477+
* Replicate the sort done for the map's erase types in BFPT: sort the erase
2478+
* mask in ascending order with the smallest erase type size starting from
2479+
* BIT(0) in the sorted erase mask.
2480+
*
2481+
* Return: sorted erase mask.
2482+
*/
2483+
static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask)
2484+
{
2485+
struct spi_nor_erase_type *erase_type = map->erase_type;
2486+
int i;
2487+
u8 sorted_erase_mask = 0;
2488+
2489+
if (!erase_mask)
2490+
return 0;
2491+
2492+
/* Replicate the sort done for the map's erase types. */
2493+
for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
2494+
if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx))
2495+
sorted_erase_mask |= BIT(i);
2496+
2497+
return sorted_erase_mask;
2498+
}
2499+
24722500
/**
24732501
* spi_nor_regions_sort_erase_types() - sort erase types in each region
24742502
* @map: the erase map of the SPI NOR
@@ -2484,19 +2512,13 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
24842512
static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
24852513
{
24862514
struct spi_nor_erase_region *region = map->regions;
2487-
struct spi_nor_erase_type *erase_type = map->erase_type;
2488-
int i;
24892515
u8 region_erase_mask, sorted_erase_mask;
24902516

24912517
while (region) {
24922518
region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK;
24932519

2494-
/* Replicate the sort done for the map's erase types. */
2495-
sorted_erase_mask = 0;
2496-
for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
2497-
if (erase_type[i].size &&
2498-
region_erase_mask & BIT(erase_type[i].idx))
2499-
sorted_erase_mask |= BIT(i);
2520+
sorted_erase_mask = spi_nor_sort_erase_mask(map,
2521+
region_erase_mask);
25002522

25012523
/* Overwrite erase mask. */
25022524
region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) |
@@ -2926,7 +2948,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
29262948
u64 offset;
29272949
u32 region_count;
29282950
int i, j;
2929-
u8 erase_type;
2951+
u8 erase_type, uniform_erase_type;
29302952

29312953
region_count = SMPT_MAP_REGION_COUNT(*smpt);
29322954
/*
@@ -2939,7 +2961,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
29392961
return -ENOMEM;
29402962
map->regions = region;
29412963

2942-
map->uniform_erase_type = 0xff;
2964+
uniform_erase_type = 0xff;
29432965
offset = 0;
29442966
/* Populate regions. */
29452967
for (i = 0; i < region_count; i++) {
@@ -2954,12 +2976,15 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
29542976
* Save the erase types that are supported in all regions and
29552977
* can erase the entire flash memory.
29562978
*/
2957-
map->uniform_erase_type &= erase_type;
2979+
uniform_erase_type &= erase_type;
29582980

29592981
offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
29602982
region[i].size;
29612983
}
29622984

2985+
map->uniform_erase_type = spi_nor_sort_erase_mask(map,
2986+
uniform_erase_type);
2987+
29632988
spi_nor_region_mark_end(&region[i - 1]);
29642989

29652990
return 0;

0 commit comments

Comments
 (0)