@@ -1158,7 +1158,7 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
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,24 +1542,22 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
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
1548
* index 0.
1550
1549
*/
1551
1550
for (i = SNOR_ERASE_TYPE_MAX - 1 ; i >= 0 ; i -- ) {
1552
1551
/* Does the erase region support the tested erase type? */
1553
- if (!(erase_mask & BIT (i )))
1552
+ if (!(region -> erase_mask & BIT (i )))
1554
1553
continue ;
1555
1554
1556
1555
erase = & map -> erase_type [i ];
1557
1556
if (!erase -> size )
1558
1557
continue ;
1559
1558
1560
1559
/* 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 )
1563
1561
return erase ;
1564
1562
1565
1563
/* 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,
1574
1572
return NULL ;
1575
1573
}
1576
1574
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
-
1630
1575
/**
1631
1576
* spi_nor_init_erase_cmd() - initialize an erase command
1632
1577
* @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,
1649
1594
cmd -> opcode = erase -> opcode ;
1650
1595
cmd -> count = 1 ;
1651
1596
1652
- if (region -> offset & SNOR_OVERLAID_REGION )
1597
+ if (region -> overlaid )
1653
1598
cmd -> size = region -> size ;
1654
1599
else
1655
1600
cmd -> size = erase -> size ;
@@ -1693,44 +1638,36 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
1693
1638
struct spi_nor_erase_region * region ;
1694
1639
struct spi_nor_erase_command * cmd = NULL ;
1695
1640
u64 region_end ;
1641
+ unsigned int i ;
1696
1642
int ret = - EINVAL ;
1697
1643
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 ;
1701
1647
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 )
1715
1652
goto destroy_erase_cmd_list ;
1716
- }
1717
-
1718
- list_add_tail (& cmd -> list , erase_list );
1719
- } else {
1720
- cmd -> count ++ ;
1721
- }
1722
1653
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
+ }
1725
1666
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 ;
1731
1670
}
1732
-
1733
- prev_erase = erase ;
1734
1671
}
1735
1672
1736
1673
return 0 ;
@@ -2468,12 +2405,11 @@ void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase)
2468
2405
void spi_nor_init_uniform_erase_map (struct spi_nor_erase_map * map ,
2469
2406
u8 erase_mask , u64 flash_size )
2470
2407
{
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 ;
2474
2409
map -> uniform_region .size = flash_size ;
2410
+ map -> uniform_region .erase_mask = erase_mask ;
2475
2411
map -> regions = & map -> uniform_region ;
2476
- map -> uniform_erase_type = erase_mask ;
2412
+ map -> n_regions = 1 ;
2477
2413
}
2478
2414
2479
2415
int spi_nor_post_bfpt_fixups (struct spi_nor * nor ,
@@ -2560,7 +2496,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map)
2560
2496
{
2561
2497
const struct spi_nor_erase_type * tested_erase , * erase = NULL ;
2562
2498
int i ;
2563
- u8 uniform_erase_type = map -> uniform_erase_type ;
2499
+ u8 uniform_erase_type = map -> uniform_region . erase_mask ;
2564
2500
2565
2501
/*
2566
2502
* 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)
2599
2535
return NULL ;
2600
2536
2601
2537
/* 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 );
2604
2539
return erase ;
2605
2540
}
2606
2541
@@ -3434,7 +3369,54 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
3434
3369
return info ;
3435
3370
}
3436
3371
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 )
3438
3420
{
3439
3421
struct mtd_info * mtd = & nor -> mtd ;
3440
3422
struct device * dev = nor -> dev ;
@@ -3465,6 +3447,11 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
3465
3447
mtd -> _resume = spi_nor_resume ;
3466
3448
mtd -> _get_device = spi_nor_get_device ;
3467
3449
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 ;
3468
3455
}
3469
3456
3470
3457
static int spi_nor_hw_reset (struct spi_nor * nor )
@@ -3555,7 +3542,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
3555
3542
return ret ;
3556
3543
3557
3544
/* 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 ;
3559
3548
3560
3549
dev_dbg (dev , "Manufacturer and device ID: %*phN\n" ,
3561
3550
SPI_NOR_MAX_ID_LEN , nor -> id );
0 commit comments