Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'spi-nor/for-6.9' into mtd/next

SPI NOR gets the non uniform erase code cleaned. We stopped using
bitmasks for erase types and flags, and instead introduced dedicated
members. We then passed the SPI NOR erase map to MTD. Users can now
determine the erase regions and make informed decisions on partitions
size.

+128 -165
+3
Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
··· 52 52 minItems: 1 53 53 maxItems: 2 54 54 55 + interrupts: 56 + maxItems: 1 57 + 55 58 m25p,fast-read: 56 59 type: boolean 57 60 description:
+88 -99
drivers/mtd/spi-nor/core.c
··· 1158 1158 1159 1159 static bool spi_nor_has_uniform_erase(const struct spi_nor *nor) 1160 1160 { 1161 - return !!nor->params->erase_map.uniform_erase_type; 1161 + return !!nor->params->erase_map.uniform_region.erase_mask; 1162 1162 } 1163 1163 1164 1164 static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) ··· 1542 1542 const struct spi_nor_erase_type *erase; 1543 1543 u32 rem; 1544 1544 int i; 1545 - u8 erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; 1546 1545 1547 1546 /* 1548 1547 * Erase types are ordered by size, with the smallest erase type at ··· 1549 1550 */ 1550 1551 for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { 1551 1552 /* Does the erase region support the tested erase type? */ 1552 - if (!(erase_mask & BIT(i))) 1553 + if (!(region->erase_mask & BIT(i))) 1553 1554 continue; 1554 1555 1555 1556 erase = &map->erase_type[i]; ··· 1557 1558 continue; 1558 1559 1559 1560 /* Alignment is not mandatory for overlaid regions */ 1560 - if (region->offset & SNOR_OVERLAID_REGION && 1561 - region->size <= len) 1561 + if (region->overlaid && region->size <= len) 1562 1562 return erase; 1563 1563 1564 1564 /* Don't erase more than what the user has asked for. */ ··· 1570 1572 } 1571 1573 1572 1574 return NULL; 1573 - } 1574 - 1575 - static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region) 1576 - { 1577 - return region->offset & SNOR_LAST_REGION; 1578 - } 1579 - 1580 - static u64 spi_nor_region_end(const struct spi_nor_erase_region *region) 1581 - { 1582 - return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size; 1583 - } 1584 - 1585 - /** 1586 - * spi_nor_region_next() - get the next spi nor region 1587 - * @region: pointer to a structure that describes a SPI NOR erase region 1588 - * 1589 - * Return: the next spi nor region or NULL if last region. 1590 - */ 1591 - struct spi_nor_erase_region * 1592 - spi_nor_region_next(struct spi_nor_erase_region *region) 1593 - { 1594 - if (spi_nor_region_is_last(region)) 1595 - return NULL; 1596 - region++; 1597 - return region; 1598 - } 1599 - 1600 - /** 1601 - * spi_nor_find_erase_region() - find the region of the serial flash memory in 1602 - * which the offset fits 1603 - * @map: the erase map of the SPI NOR 1604 - * @addr: offset in the serial flash memory 1605 - * 1606 - * Return: a pointer to the spi_nor_erase_region struct, ERR_PTR(-errno) 1607 - * otherwise. 1608 - */ 1609 - static struct spi_nor_erase_region * 1610 - spi_nor_find_erase_region(const struct spi_nor_erase_map *map, u64 addr) 1611 - { 1612 - struct spi_nor_erase_region *region = map->regions; 1613 - u64 region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; 1614 - u64 region_end = region_start + region->size; 1615 - 1616 - while (addr < region_start || addr >= region_end) { 1617 - region = spi_nor_region_next(region); 1618 - if (!region) 1619 - return ERR_PTR(-EINVAL); 1620 - 1621 - region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; 1622 - region_end = region_start + region->size; 1623 - } 1624 - 1625 - return region; 1626 1575 } 1627 1576 1628 1577 /** ··· 1594 1649 cmd->opcode = erase->opcode; 1595 1650 cmd->count = 1; 1596 1651 1597 - if (region->offset & SNOR_OVERLAID_REGION) 1652 + if (region->overlaid) 1598 1653 cmd->size = region->size; 1599 1654 else 1600 1655 cmd->size = erase->size; ··· 1638 1693 struct spi_nor_erase_region *region; 1639 1694 struct spi_nor_erase_command *cmd = NULL; 1640 1695 u64 region_end; 1696 + unsigned int i; 1641 1697 int ret = -EINVAL; 1642 1698 1643 - region = spi_nor_find_erase_region(map, addr); 1644 - if (IS_ERR(region)) 1645 - return PTR_ERR(region); 1699 + for (i = 0; i < map->n_regions && len; i++) { 1700 + region = &map->regions[i]; 1701 + region_end = region->offset + region->size; 1646 1702 1647 - region_end = spi_nor_region_end(region); 1648 - 1649 - while (len) { 1650 - erase = spi_nor_find_best_erase_type(map, region, addr, len); 1651 - if (!erase) 1652 - goto destroy_erase_cmd_list; 1653 - 1654 - if (prev_erase != erase || 1655 - erase->size != cmd->size || 1656 - region->offset & SNOR_OVERLAID_REGION) { 1657 - cmd = spi_nor_init_erase_cmd(region, erase); 1658 - if (IS_ERR(cmd)) { 1659 - ret = PTR_ERR(cmd); 1703 + while (len && addr >= region->offset && addr < region_end) { 1704 + erase = spi_nor_find_best_erase_type(map, region, addr, 1705 + len); 1706 + if (!erase) 1660 1707 goto destroy_erase_cmd_list; 1708 + 1709 + if (prev_erase != erase || erase->size != cmd->size || 1710 + region->overlaid) { 1711 + cmd = spi_nor_init_erase_cmd(region, erase); 1712 + if (IS_ERR(cmd)) { 1713 + ret = PTR_ERR(cmd); 1714 + goto destroy_erase_cmd_list; 1715 + } 1716 + 1717 + list_add_tail(&cmd->list, erase_list); 1718 + } else { 1719 + cmd->count++; 1661 1720 } 1662 1721 1663 - list_add_tail(&cmd->list, erase_list); 1664 - } else { 1665 - cmd->count++; 1722 + len -= cmd->size; 1723 + addr += cmd->size; 1724 + prev_erase = erase; 1666 1725 } 1667 - 1668 - addr += cmd->size; 1669 - len -= cmd->size; 1670 - 1671 - if (len && addr >= region_end) { 1672 - region = spi_nor_region_next(region); 1673 - if (!region) 1674 - goto destroy_erase_cmd_list; 1675 - region_end = spi_nor_region_end(region); 1676 - } 1677 - 1678 - prev_erase = erase; 1679 1726 } 1680 1727 1681 1728 return 0; ··· 2405 2468 void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, 2406 2469 u8 erase_mask, u64 flash_size) 2407 2470 { 2408 - /* Offset 0 with erase_mask and SNOR_LAST_REGION bit set */ 2409 - map->uniform_region.offset = (erase_mask & SNOR_ERASE_TYPE_MASK) | 2410 - SNOR_LAST_REGION; 2471 + map->uniform_region.offset = 0; 2411 2472 map->uniform_region.size = flash_size; 2473 + map->uniform_region.erase_mask = erase_mask; 2412 2474 map->regions = &map->uniform_region; 2413 - map->uniform_erase_type = erase_mask; 2475 + map->n_regions = 1; 2414 2476 } 2415 2477 2416 2478 int spi_nor_post_bfpt_fixups(struct spi_nor *nor, ··· 2496 2560 { 2497 2561 const struct spi_nor_erase_type *tested_erase, *erase = NULL; 2498 2562 int i; 2499 - u8 uniform_erase_type = map->uniform_erase_type; 2563 + u8 uniform_erase_type = map->uniform_region.erase_mask; 2500 2564 2501 2565 /* 2502 2566 * Search for the biggest erase size, except for when compiled ··· 2535 2599 return NULL; 2536 2600 2537 2601 /* Disable all other Sector Erase commands. */ 2538 - map->uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK; 2539 - map->uniform_erase_type |= BIT(erase - map->erase_type); 2602 + map->uniform_region.erase_mask = BIT(erase - map->erase_type); 2540 2603 return erase; 2541 2604 } 2542 2605 ··· 3369 3434 return info; 3370 3435 } 3371 3436 3372 - static void spi_nor_set_mtd_info(struct spi_nor *nor) 3437 + static u32 3438 + spi_nor_get_region_erasesize(const struct spi_nor_erase_region *region, 3439 + const struct spi_nor_erase_type *erase_type) 3440 + { 3441 + u8 i; 3442 + 3443 + if (region->overlaid) 3444 + return region->size; 3445 + 3446 + for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { 3447 + if (region->erase_mask & BIT(i)) 3448 + return erase_type[i].size; 3449 + } 3450 + 3451 + return 0; 3452 + } 3453 + 3454 + static int spi_nor_set_mtd_eraseregions(struct spi_nor *nor) 3455 + { 3456 + const struct spi_nor_erase_map *map = &nor->params->erase_map; 3457 + const struct spi_nor_erase_region *region = map->regions; 3458 + struct mtd_erase_region_info *mtd_region; 3459 + struct mtd_info *mtd = &nor->mtd; 3460 + u32 erasesize, i; 3461 + 3462 + mtd_region = devm_kcalloc(nor->dev, map->n_regions, sizeof(*mtd_region), 3463 + GFP_KERNEL); 3464 + if (!mtd_region) 3465 + return -ENOMEM; 3466 + 3467 + for (i = 0; i < map->n_regions; i++) { 3468 + erasesize = spi_nor_get_region_erasesize(&region[i], 3469 + map->erase_type); 3470 + if (!erasesize) 3471 + return -EINVAL; 3472 + 3473 + mtd_region[i].erasesize = erasesize; 3474 + mtd_region[i].numblocks = div64_ul(region[i].size, erasesize); 3475 + mtd_region[i].offset = region[i].offset; 3476 + } 3477 + 3478 + mtd->numeraseregions = map->n_regions; 3479 + mtd->eraseregions = mtd_region; 3480 + 3481 + return 0; 3482 + } 3483 + 3484 + static int spi_nor_set_mtd_info(struct spi_nor *nor) 3373 3485 { 3374 3486 struct mtd_info *mtd = &nor->mtd; 3375 3487 struct device *dev = nor->dev; ··· 3447 3465 mtd->_resume = spi_nor_resume; 3448 3466 mtd->_get_device = spi_nor_get_device; 3449 3467 mtd->_put_device = spi_nor_put_device; 3468 + 3469 + if (!spi_nor_has_uniform_erase(nor)) 3470 + return spi_nor_set_mtd_eraseregions(nor); 3471 + 3472 + return 0; 3450 3473 } 3451 3474 3452 3475 static int spi_nor_hw_reset(struct spi_nor *nor) ··· 3542 3555 return ret; 3543 3556 3544 3557 /* No mtd_info fields should be used up to this point. */ 3545 - spi_nor_set_mtd_info(nor); 3558 + ret = spi_nor_set_mtd_info(nor); 3559 + if (ret) 3560 + return ret; 3546 3561 3547 3562 dev_dbg(dev, "Manufacturer and device ID: %*phN\n", 3548 3563 SPI_NOR_MAX_ID_LEN, nor->id);
+9 -21
drivers/mtd/spi-nor/core.h
··· 240 240 /** 241 241 * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region 242 242 * @offset: the offset in the data array of erase region start. 243 - * LSB bits are used as a bitmask encoding flags to 244 - * determine if this region is overlaid, if this region is 245 - * the last in the SPI NOR flash memory and to indicate 246 - * all the supported erase commands inside this region. 247 - * The erase types are sorted in ascending order with the 248 - * smallest Erase Type size being at BIT(0). 249 243 * @size: the size of the region in bytes. 244 + * @erase_mask: bitmask to indicate all the supported erase commands 245 + * inside this region. The erase types are sorted in 246 + * ascending order with the smallest Erase Type size being 247 + * at BIT(0). 248 + * @overlaid: determine if this region is overlaid. 250 249 */ 251 250 struct spi_nor_erase_region { 252 251 u64 offset; 253 252 u64 size; 253 + u8 erase_mask; 254 + bool overlaid; 254 255 }; 255 256 256 257 #define SNOR_ERASE_TYPE_MAX 4 257 - #define SNOR_ERASE_TYPE_MASK GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0) 258 - 259 - #define SNOR_LAST_REGION BIT(4) 260 - #define SNOR_OVERLAID_REGION BIT(5) 261 - 262 - #define SNOR_ERASE_FLAGS_MAX 6 263 - #define SNOR_ERASE_FLAGS_MASK GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0) 264 258 265 259 /** 266 260 * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map ··· 267 273 * The erase types are sorted in ascending order, with the 268 274 * smallest Erase Type size being the first member in the 269 275 * erase_type array. 270 - * @uniform_erase_type: bitmask encoding erase types that can erase the 271 - * entire memory. This member is completed at init by 272 - * uniform and non-uniform SPI NOR flash memories if they 273 - * support at least one erase type that can erase the 274 - * entire memory. 276 + * @n_regions: number of erase regions. 275 277 */ 276 278 struct spi_nor_erase_map { 277 279 struct spi_nor_erase_region *regions; 278 280 struct spi_nor_erase_region uniform_region; 279 281 struct spi_nor_erase_type erase_type[SNOR_ERASE_TYPE_MAX]; 280 - u8 uniform_erase_type; 282 + unsigned int n_regions; 281 283 }; 282 284 283 285 /** ··· 665 675 void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size, 666 676 u8 opcode); 667 677 void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase); 668 - struct spi_nor_erase_region * 669 - spi_nor_region_next(struct spi_nor_erase_region *region); 670 678 void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, 671 679 u8 erase_mask, u64 flash_size); 672 680
+12 -14
drivers/mtd/spi-nor/debugfs.c
··· 78 78 struct spi_nor *nor = s->private; 79 79 struct spi_nor_flash_parameter *params = nor->params; 80 80 struct spi_nor_erase_map *erase_map = &params->erase_map; 81 - struct spi_nor_erase_region *region; 81 + struct spi_nor_erase_region *region = erase_map->regions; 82 82 const struct flash_info *info = nor->info; 83 83 char buf[16], *str; 84 - int i; 84 + unsigned int i; 85 85 86 86 seq_printf(s, "name\t\t%s\n", info->name); 87 87 seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id); ··· 142 142 } 143 143 144 144 seq_puts(s, "\nsector map\n"); 145 - seq_puts(s, " region (in hex) | erase mask | flags\n"); 145 + seq_puts(s, " region (in hex) | erase mask | overlaid\n"); 146 146 seq_puts(s, " ------------------+------------+----------\n"); 147 - for (region = erase_map->regions; 148 - region; 149 - region = spi_nor_region_next(region)) { 150 - u64 start = region->offset & ~SNOR_ERASE_FLAGS_MASK; 151 - u64 flags = region->offset & SNOR_ERASE_FLAGS_MASK; 152 - u64 end = start + region->size - 1; 147 + for (i = 0; i < erase_map->n_regions; i++) { 148 + u64 start = region[i].offset; 149 + u64 end = start + region[i].size - 1; 150 + u8 erase_mask = region[i].erase_mask; 153 151 154 152 seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", 155 153 start, end, 156 - flags & BIT(0) ? '0' : ' ', 157 - flags & BIT(1) ? '1' : ' ', 158 - flags & BIT(2) ? '2' : ' ', 159 - flags & BIT(3) ? '3' : ' ', 160 - flags & SNOR_OVERLAID_REGION ? "overlaid" : ""); 154 + erase_mask & BIT(0) ? '0' : ' ', 155 + erase_mask & BIT(1) ? '1' : ' ', 156 + erase_mask & BIT(2) ? '2' : ' ', 157 + erase_mask & BIT(3) ? '3' : ' ', 158 + region[i].overlaid ? "yes" : "no"); 161 159 } 162 160 163 161 return 0;
+16 -31
drivers/mtd/spi-nor/sfdp.c
··· 389 389 static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map) 390 390 { 391 391 struct spi_nor_erase_region *region = map->regions; 392 - u8 region_erase_mask, sorted_erase_mask; 392 + u8 sorted_erase_mask; 393 + unsigned int i; 393 394 394 - while (region) { 395 - region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; 396 - 397 - sorted_erase_mask = spi_nor_sort_erase_mask(map, 398 - region_erase_mask); 395 + for (i = 0; i < map->n_regions; i++) { 396 + sorted_erase_mask = 397 + spi_nor_sort_erase_mask(map, region[i].erase_mask); 399 398 400 399 /* Overwrite erase mask. */ 401 - region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) | 402 - sorted_erase_mask; 403 - 404 - region = spi_nor_region_next(region); 400 + region[i].erase_mask = sorted_erase_mask; 405 401 } 406 402 } 407 403 ··· 550 554 * selecting the uniform erase. 551 555 */ 552 556 spi_nor_regions_sort_erase_types(map); 553 - map->uniform_erase_type = map->uniform_region.offset & 554 - SNOR_ERASE_TYPE_MASK; 555 557 556 558 /* Stop here if not JESD216 rev A or later. */ 557 559 if (bfpt_header->length == BFPT_DWORD_MAX_JESD216) ··· 800 806 return ret; 801 807 } 802 808 803 - static void spi_nor_region_mark_end(struct spi_nor_erase_region *region) 804 - { 805 - region->offset |= SNOR_LAST_REGION; 806 - } 807 - 808 - static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) 809 - { 810 - region->offset |= SNOR_OVERLAID_REGION; 811 - } 812 - 813 809 /** 814 810 * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid 815 811 * @region: pointer to a structure that describes a SPI NOR erase region ··· 817 833 if (!(erase[i].size && erase_type & BIT(erase[i].idx))) 818 834 continue; 819 835 if (region->size & erase[i].size_mask) { 820 - spi_nor_region_mark_overlay(region); 836 + region->overlaid = true; 821 837 return; 822 838 } 823 839 } ··· 852 868 if (!region) 853 869 return -ENOMEM; 854 870 map->regions = region; 871 + map->n_regions = region_count; 855 872 856 873 uniform_erase_type = 0xff; 857 874 regions_erase_type = 0; ··· 860 875 /* Populate regions. */ 861 876 for (i = 0; i < region_count; i++) { 862 877 j = i + 1; /* index for the region dword */ 878 + region[i].offset = offset; 863 879 region[i].size = SMPT_MAP_REGION_SIZE(smpt[j]); 864 880 erase_type = SMPT_MAP_REGION_ERASE_TYPE(smpt[j]); 865 - region[i].offset = offset | erase_type; 881 + region[i].erase_mask = erase_type; 866 882 867 883 spi_nor_region_check_overlay(&region[i], erase, erase_type); 868 884 ··· 879 893 */ 880 894 regions_erase_type |= erase_type; 881 895 882 - offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) + 883 - region[i].size; 896 + offset = region[i].offset + region[i].size; 884 897 } 885 - spi_nor_region_mark_end(&region[i - 1]); 886 898 887 - save_uniform_erase_type = map->uniform_erase_type; 888 - map->uniform_erase_type = spi_nor_sort_erase_mask(map, 889 - uniform_erase_type); 899 + save_uniform_erase_type = map->uniform_region.erase_mask; 900 + map->uniform_region.erase_mask = 901 + spi_nor_sort_erase_mask(map, 902 + uniform_erase_type); 890 903 891 904 if (!regions_erase_type) { 892 905 /* 893 906 * Roll back to the previous uniform_erase_type mask, SMPT is 894 907 * broken. 895 908 */ 896 - map->uniform_erase_type = save_uniform_erase_type; 909 + map->uniform_region.erase_mask = save_uniform_erase_type; 897 910 return -EINVAL; 898 911 } 899 912