aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTudor Ambarus <tudor.ambarus@microchip.com>2018-11-26 12:45:44 +0000
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-11-28 09:00:00 +0100
commitdc92843159a7d01e37cf68750745333e944a9e55 (patch)
tree74f5e717685aafca4ccabd0c8e818a40da2843ff /drivers
parentLinux 4.20-rc4 (diff)
downloadlinux-dev-dc92843159a7d01e37cf68750745333e944a9e55.tar.xz
linux-dev-dc92843159a7d01e37cf68750745333e944a9e55.zip
mtd: spi-nor: fix erase_type array to indicate current map conf
BFPT advertises all the erase types supported by all the possible map configurations. Mask out the erase types that are not supported by the current map configuration. Backward compatibility test done on sst26vf064b. Fixes: b038e8e3be72 ("mtd: spi-nor: parse SFDP Sector Map Parameter Table") Reported-by: Alexander Sverdlin <alexander.sverdlin@nokia.com> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> Tested-by: Alexander Sverdlin <alexander.sverdlin@nokia.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 93c9bc8931fc..1fdd2834fbcb 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2995,12 +2995,13 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
const u32 *smpt)
{
struct spi_nor_erase_map *map = &nor->erase_map;
- const struct spi_nor_erase_type *erase = map->erase_type;
+ struct spi_nor_erase_type *erase = map->erase_type;
struct spi_nor_erase_region *region;
u64 offset;
u32 region_count;
int i, j;
- u8 erase_type, uniform_erase_type;
+ u8 uniform_erase_type, save_uniform_erase_type;
+ u8 erase_type, regions_erase_type;
region_count = SMPT_MAP_REGION_COUNT(*smpt);
/*
@@ -3014,6 +3015,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
map->regions = region;
uniform_erase_type = 0xff;
+ regions_erase_type = 0;
offset = 0;
/* Populate regions. */
for (i = 0; i < region_count; i++) {
@@ -3030,13 +3032,38 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
*/
uniform_erase_type &= erase_type;
+ /*
+ * regions_erase_type mask will indicate all the erase types
+ * supported in this configuration map.
+ */
+ regions_erase_type |= erase_type;
+
offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
region[i].size;
}
+ save_uniform_erase_type = map->uniform_erase_type;
map->uniform_erase_type = 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;
+ return -EINVAL;
+ }
+
+ /*
+ * BFPT advertises all the erase types supported by all the possible
+ * map configurations. Mask out the erase types that are not supported
+ * by the current map configuration.
+ */
+ for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+ if (!(regions_erase_type & BIT(erase[i].idx)))
+ spi_nor_set_erase_type(&erase[i], 0, 0xFF);
+
spi_nor_region_mark_end(&region[i - 1]);
return 0;