mtd: spi-nor: core: rework struct spi_nor_erase_region
authorTakahiro Kuwano <Takahiro.Kuwano@infineon.com>
Tue, 20 Feb 2024 08:34:06 +0000 (17:34 +0900)
committerTudor Ambarus <tudor.ambarus@linaro.org>
Mon, 26 Feb 2024 10:35:05 +0000 (12:35 +0200)
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>
drivers/mtd/spi-nor/core.c
drivers/mtd/spi-nor/core.h
drivers/mtd/spi-nor/debugfs.c
drivers/mtd/spi-nor/sfdp.c

index 4129764fad8cf5faaeb7763b2576805dee1ebf78..d526e555e7b3bbc2085eff1a2da524f5b562c7ca 100644 (file)
@@ -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;
 }
 
index d36c0e0729548b79970d713c391ceeea47911bfc..f68ae2fc4a1fe29164c9ada4a430654d8262ebcf 100644 (file)
@@ -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;
 };
 
 /**
index 2dbda6b6938abd9caceff084a7421e0ec46ea033..d20bbb531a880e705b214c46aedb995b58c4fffa 100644 (file)
@@ -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" : "");
        }
 
index 57713de3283278970c5d125bde422c36dfd71b5e..3cf1db6e4026d862f585889fd0574a8b3d33dea4 100644 (file)
@@ -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(&region[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(&region[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;
        }