@@ -1158,7 +1158,7 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
11581158
11591159static bool spi_nor_has_uniform_erase (const struct spi_nor * nor )
11601160{
1161- return !!nor -> params -> erase_map .uniform_erase_type ;
1161+ return !!nor -> params -> erase_map .uniform_region . erase_mask ;
11621162}
11631163
11641164static void spi_nor_set_4byte_opcodes (struct spi_nor * nor )
@@ -1542,24 +1542,22 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
15421542 const struct spi_nor_erase_type * erase ;
15431543 u32 rem ;
15441544 int i ;
1545- u8 erase_mask = region -> offset & SNOR_ERASE_TYPE_MASK ;
15461545
15471546 /*
15481547 * Erase types are ordered by size, with the smallest erase type at
15491548 * index 0.
15501549 */
15511550 for (i = SNOR_ERASE_TYPE_MAX - 1 ; i >= 0 ; i -- ) {
15521551 /* Does the erase region support the tested erase type? */
1553- if (!(erase_mask & BIT (i )))
1552+ if (!(region -> erase_mask & BIT (i )))
15541553 continue ;
15551554
15561555 erase = & map -> erase_type [i ];
15571556 if (!erase -> size )
15581557 continue ;
15591558
15601559 /* Alignment is not mandatory for overlaid regions */
1561- if (region -> offset & SNOR_OVERLAID_REGION &&
1562- region -> size <= len )
1560+ if (region -> overlaid && region -> size <= len )
15631561 return erase ;
15641562
15651563 /* Don't erase more than what the user has asked for. */
@@ -1574,59 +1572,6 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
15741572 return NULL ;
15751573}
15761574
1577- static u64 spi_nor_region_is_last (const struct spi_nor_erase_region * region )
1578- {
1579- return region -> offset & SNOR_LAST_REGION ;
1580- }
1581-
1582- static u64 spi_nor_region_end (const struct spi_nor_erase_region * region )
1583- {
1584- return (region -> offset & ~SNOR_ERASE_FLAGS_MASK ) + region -> size ;
1585- }
1586-
1587- /**
1588- * spi_nor_region_next() - get the next spi nor region
1589- * @region: pointer to a structure that describes a SPI NOR erase region
1590- *
1591- * Return: the next spi nor region or NULL if last region.
1592- */
1593- struct spi_nor_erase_region *
1594- spi_nor_region_next (struct spi_nor_erase_region * region )
1595- {
1596- if (spi_nor_region_is_last (region ))
1597- return NULL ;
1598- region ++ ;
1599- return region ;
1600- }
1601-
1602- /**
1603- * spi_nor_find_erase_region() - find the region of the serial flash memory in
1604- * which the offset fits
1605- * @map: the erase map of the SPI NOR
1606- * @addr: offset in the serial flash memory
1607- *
1608- * Return: a pointer to the spi_nor_erase_region struct, ERR_PTR(-errno)
1609- * otherwise.
1610- */
1611- static struct spi_nor_erase_region *
1612- spi_nor_find_erase_region (const struct spi_nor_erase_map * map , u64 addr )
1613- {
1614- struct spi_nor_erase_region * region = map -> regions ;
1615- u64 region_start = region -> offset & ~SNOR_ERASE_FLAGS_MASK ;
1616- u64 region_end = region_start + region -> size ;
1617-
1618- while (addr < region_start || addr >= region_end ) {
1619- region = spi_nor_region_next (region );
1620- if (!region )
1621- return ERR_PTR (- EINVAL );
1622-
1623- region_start = region -> offset & ~SNOR_ERASE_FLAGS_MASK ;
1624- region_end = region_start + region -> size ;
1625- }
1626-
1627- return region ;
1628- }
1629-
16301575/**
16311576 * spi_nor_init_erase_cmd() - initialize an erase command
16321577 * @region: pointer to a structure that describes a SPI NOR erase region
@@ -1649,7 +1594,7 @@ spi_nor_init_erase_cmd(const struct spi_nor_erase_region *region,
16491594 cmd -> opcode = erase -> opcode ;
16501595 cmd -> count = 1 ;
16511596
1652- if (region -> offset & SNOR_OVERLAID_REGION )
1597+ if (region -> overlaid )
16531598 cmd -> size = region -> size ;
16541599 else
16551600 cmd -> size = erase -> size ;
@@ -1693,44 +1638,36 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
16931638 struct spi_nor_erase_region * region ;
16941639 struct spi_nor_erase_command * cmd = NULL ;
16951640 u64 region_end ;
1641+ unsigned int i ;
16961642 int ret = - EINVAL ;
16971643
1698- region = spi_nor_find_erase_region ( map , addr );
1699- if ( IS_ERR ( region ))
1700- return PTR_ERR ( region ) ;
1644+ for ( i = 0 ; i < map -> n_regions && len ; i ++ ) {
1645+ region = & map -> regions [ i ];
1646+ region_end = region -> offset + region -> size ;
17011647
1702- region_end = spi_nor_region_end (region );
1703-
1704- while (len ) {
1705- erase = spi_nor_find_best_erase_type (map , region , addr , len );
1706- if (!erase )
1707- goto destroy_erase_cmd_list ;
1708-
1709- if (prev_erase != erase ||
1710- erase -> size != cmd -> size ||
1711- region -> offset & SNOR_OVERLAID_REGION ) {
1712- cmd = spi_nor_init_erase_cmd (region , erase );
1713- if (IS_ERR (cmd )) {
1714- ret = PTR_ERR (cmd );
1648+ while (len && addr >= region -> offset && addr < region_end ) {
1649+ erase = spi_nor_find_best_erase_type (map , region , addr ,
1650+ len );
1651+ if (!erase )
17151652 goto destroy_erase_cmd_list ;
1716- }
1717-
1718- list_add_tail (& cmd -> list , erase_list );
1719- } else {
1720- cmd -> count ++ ;
1721- }
17221653
1723- addr += cmd -> size ;
1724- len -= cmd -> size ;
1654+ if (prev_erase != erase || erase -> size != cmd -> size ||
1655+ region -> overlaid ) {
1656+ cmd = spi_nor_init_erase_cmd (region , erase );
1657+ if (IS_ERR (cmd )) {
1658+ ret = PTR_ERR (cmd );
1659+ goto destroy_erase_cmd_list ;
1660+ }
1661+
1662+ list_add_tail (& cmd -> list , erase_list );
1663+ } else {
1664+ cmd -> count ++ ;
1665+ }
17251666
1726- if (len && addr >= region_end ) {
1727- region = spi_nor_region_next (region );
1728- if (!region )
1729- goto destroy_erase_cmd_list ;
1730- region_end = spi_nor_region_end (region );
1667+ len -= cmd -> size ;
1668+ addr += cmd -> size ;
1669+ prev_erase = erase ;
17311670 }
1732-
1733- prev_erase = erase ;
17341671 }
17351672
17361673 return 0 ;
@@ -2468,12 +2405,11 @@ void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase)
24682405void spi_nor_init_uniform_erase_map (struct spi_nor_erase_map * map ,
24692406 u8 erase_mask , u64 flash_size )
24702407{
2471- /* Offset 0 with erase_mask and SNOR_LAST_REGION bit set */
2472- map -> uniform_region .offset = (erase_mask & SNOR_ERASE_TYPE_MASK ) |
2473- SNOR_LAST_REGION ;
2408+ map -> uniform_region .offset = 0 ;
24742409 map -> uniform_region .size = flash_size ;
2410+ map -> uniform_region .erase_mask = erase_mask ;
24752411 map -> regions = & map -> uniform_region ;
2476- map -> uniform_erase_type = erase_mask ;
2412+ map -> n_regions = 1 ;
24772413}
24782414
24792415int spi_nor_post_bfpt_fixups (struct spi_nor * nor ,
@@ -2560,7 +2496,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map)
25602496{
25612497 const struct spi_nor_erase_type * tested_erase , * erase = NULL ;
25622498 int i ;
2563- u8 uniform_erase_type = map -> uniform_erase_type ;
2499+ u8 uniform_erase_type = map -> uniform_region . erase_mask ;
25642500
25652501 /*
25662502 * Search for the biggest erase size, except for when compiled
@@ -2599,8 +2535,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map)
25992535 return NULL ;
26002536
26012537 /* Disable all other Sector Erase commands. */
2602- map -> uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK ;
2603- map -> uniform_erase_type |= BIT (erase - map -> erase_type );
2538+ map -> uniform_region .erase_mask = BIT (erase - map -> erase_type );
26042539 return erase ;
26052540}
26062541
@@ -3434,7 +3369,54 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
34343369 return info ;
34353370}
34363371
3437- static void spi_nor_set_mtd_info (struct spi_nor * nor )
3372+ static u32
3373+ spi_nor_get_region_erasesize (const struct spi_nor_erase_region * region ,
3374+ const struct spi_nor_erase_type * erase_type )
3375+ {
3376+ u8 i ;
3377+
3378+ if (region -> overlaid )
3379+ return region -> size ;
3380+
3381+ for (i = SNOR_ERASE_TYPE_MAX - 1 ; i >= 0 ; i -- ) {
3382+ if (region -> erase_mask & BIT (i ))
3383+ return erase_type [i ].size ;
3384+ }
3385+
3386+ return 0 ;
3387+ }
3388+
3389+ static int spi_nor_set_mtd_eraseregions (struct spi_nor * nor )
3390+ {
3391+ const struct spi_nor_erase_map * map = & nor -> params -> erase_map ;
3392+ const struct spi_nor_erase_region * region = map -> regions ;
3393+ struct mtd_erase_region_info * mtd_region ;
3394+ struct mtd_info * mtd = & nor -> mtd ;
3395+ u32 erasesize , i ;
3396+
3397+ mtd_region = devm_kcalloc (nor -> dev , map -> n_regions , sizeof (* mtd_region ),
3398+ GFP_KERNEL );
3399+ if (!mtd_region )
3400+ return - ENOMEM ;
3401+
3402+ for (i = 0 ; i < map -> n_regions ; i ++ ) {
3403+ erasesize = spi_nor_get_region_erasesize (& region [i ],
3404+ map -> erase_type );
3405+ if (!erasesize )
3406+ return - EINVAL ;
3407+
3408+ mtd_region [i ].erasesize = erasesize ;
3409+ mtd_region [i ].numblocks = div64_ul (region [i ].size , erasesize );
3410+ mtd_region [i ].offset = region [i ].offset ;
3411+ }
3412+
3413+ mtd -> numeraseregions = map -> n_regions ;
3414+ mtd -> eraseregions = mtd_region ;
3415+
3416+ return 0 ;
3417+ }
3418+
3419+ static int spi_nor_set_mtd_info (struct spi_nor * nor )
34383420{
34393421 struct mtd_info * mtd = & nor -> mtd ;
34403422 struct device * dev = nor -> dev ;
@@ -3465,6 +3447,11 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
34653447 mtd -> _resume = spi_nor_resume ;
34663448 mtd -> _get_device = spi_nor_get_device ;
34673449 mtd -> _put_device = spi_nor_put_device ;
3450+
3451+ if (!spi_nor_has_uniform_erase (nor ))
3452+ return spi_nor_set_mtd_eraseregions (nor );
3453+
3454+ return 0 ;
34683455}
34693456
34703457static int spi_nor_hw_reset (struct spi_nor * nor )
@@ -3555,7 +3542,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
35553542 return ret ;
35563543
35573544 /* No mtd_info fields should be used up to this point. */
3558- spi_nor_set_mtd_info (nor );
3545+ ret = spi_nor_set_mtd_info (nor );
3546+ if (ret )
3547+ return ret ;
35593548
35603549 dev_dbg (dev , "Manufacturer and device ID: %*phN\n" ,
35613550 SPI_NOR_MAX_ID_LEN , nor -> id );
0 commit comments