diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index eb7bb596416b..93c9bc8931fc 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2521,6 +2521,34 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r) return left->size - right->size; } +/** + * spi_nor_sort_erase_mask() - sort erase mask + * @map: the erase map of the SPI NOR + * @erase_mask: the erase type mask to be sorted + * + * Replicate the sort done for the map's erase types in BFPT: sort the erase + * mask in ascending order with the smallest erase type size starting from + * BIT(0) in the sorted erase mask. + * + * Return: sorted erase mask. + */ +static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask) +{ + struct spi_nor_erase_type *erase_type = map->erase_type; + int i; + u8 sorted_erase_mask = 0; + + if (!erase_mask) + return 0; + + /* Replicate the sort done for the map's erase types. */ + for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) + if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx)) + sorted_erase_mask |= BIT(i); + + return sorted_erase_mask; +} + /** * spi_nor_regions_sort_erase_types() - sort erase types in each region * @map: the erase map of the SPI NOR @@ -2536,19 +2564,13 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r) static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map) { struct spi_nor_erase_region *region = map->regions; - struct spi_nor_erase_type *erase_type = map->erase_type; - int i; u8 region_erase_mask, sorted_erase_mask; while (region) { region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; - /* Replicate the sort done for the map's erase types. */ - sorted_erase_mask = 0; - for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) - if (erase_type[i].size && - region_erase_mask & BIT(erase_type[i].idx)) - sorted_erase_mask |= BIT(i); + sorted_erase_mask = spi_nor_sort_erase_mask(map, + region_erase_mask); /* Overwrite erase mask. */ region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) | @@ -2978,7 +3000,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, u64 offset; u32 region_count; int i, j; - u8 erase_type; + u8 erase_type, uniform_erase_type; region_count = SMPT_MAP_REGION_COUNT(*smpt); /* @@ -2991,7 +3013,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, return -ENOMEM; map->regions = region; - map->uniform_erase_type = 0xff; + uniform_erase_type = 0xff; offset = 0; /* Populate regions. */ for (i = 0; i < region_count; i++) { @@ -3006,12 +3028,15 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor, * Save the erase types that are supported in all regions and * can erase the entire flash memory. */ - map->uniform_erase_type &= erase_type; + uniform_erase_type &= erase_type; offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) + region[i].size; } + map->uniform_erase_type = spi_nor_sort_erase_mask(map, + uniform_erase_type); + spi_nor_region_mark_end(®ion[i - 1]); return 0;