[U-Boot] [PATCH 1/5] spi_sf: Skip the erasing of protected sectors

Otavio Salvador otavio.salvador at ossystems.com.br
Fri Sep 4 17:24:09 CEST 2015


On Thu, Sep 3, 2015 at 6:35 AM, Jagan Teki <jteki at openedev.com> wrote:
> On 2 September 2015 at 20:11, Otavio Salvador <otavio at ossystems.com.br> wrote:
>> Many SPI flashes have protection bits (BP2, BP1 and BP0) in the
>> status register that can protect selected regions of the SPI NOR.
>>
>> Take these bits into account when performing erase operations,
>> making sure that the protected areas are skipped.
>>
>> Introduce the CONFIG_SPI_NOR_PROTECTION option that can be selected
>> by systems that want to protect selected regions of SPI NOR flash.
>>
>> Signed-off-by: Otavio Salvador <otavio at ossystems.com.br>
>> ---
>>
>>  README                     |  4 ++
>>  drivers/mtd/spi/sf_ops.c   | 91 ++++++++++++++++++++++++++++++++++++++++++++--
>>  drivers/mtd/spi/sf_probe.c |  2 +
>>  3 files changed, 94 insertions(+), 3 deletions(-)
>>
>> diff --git a/README b/README
>> index 1acc355..18d61a6 100644
>> --- a/README
>> +++ b/README
>> @@ -2751,6 +2751,10 @@ CBFS (Coreboot Filesystem) support
>>                 Timeout for waiting until spi transfer completed.
>>                 default: (CONFIG_SYS_HZ/100)     /* 10 ms */
>>
>> +               CONFIG_SPI_NOR_PROTECTION
>> +               Enable the built-in protection mechanism provided by the
>> +               BP2, BP1 and BP0 bits from the status register.
>
> Does these bits specific for micron flash?

They seem to be generic. I tested this on two part numbers from
different vendors: Micron M25P32 and SST25VF032B. In this case the
protection bits (BP) have the same meaning/layout.

If you prefer we can call this option CONFIG_SPI_NOR_PROTECTION_STM in
case we have SPI NOR flashes with a different BP bits structure as
done in the kernel.

>> +
>>  - FPGA Support: CONFIG_FPGA
>>
>>                 Enables FPGA subsystem.
>> diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
>> index 900ec1f..a7a07f9 100644
>> --- a/drivers/mtd/spi/sf_ops.c
>> +++ b/drivers/mtd/spi/sf_ops.c
>> @@ -264,6 +264,84 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
>>         return ret;
>>  }
>>
>> +#ifdef CONFIG_SPI_NOR_PROTECTION
>> +static int is_protected(struct spi_flash *flash, u32 offset)
>> +{
>> +       int total_sector, ret, protected_sector;
>> +       bool *protected;
>> +       u8 sr;
>> +
>> +       total_sector = flash->size / flash->erase_size;
>> +       protected = calloc(1, total_sector);
>> +       if (!protected)
>> +               return -ENOMEM;
>> +
>> +       ret = spi_flash_cmd_read_status(flash, &sr);
>> +       if (ret < 0)
>> +               goto free_protected;
>> +
>> +       /* Extract the protection bits: BP2, BP1 and BP0 */
>> +       sr = (sr & 0x1c) >> 2;
>
> Does this masking specific to particular flash part or it's generic
> way, please elaborate.

Seems to be generic.

>> +
>> +       switch (sr) {
>> +       case 0:
>> +               protected_sector = 0;
>> +       break;
>> +
>> +       case 1:
>> +               protected_sector = total_sector / 64;
>> +       break;
>> +
>> +       case 2:
>> +               protected_sector = total_sector / 32;
>> +       break;
>> +
>> +       case 3:
>> +               protected_sector = total_sector / 16;
>> +       break;
>> +
>> +       case 4:
>> +               protected_sector = total_sector / 8;
>> +       break;
>> +
>> +       case 5:
>> +               protected_sector = total_sector / 4;
>> +       break;
>> +
>> +       case 6:
>> +               protected_sector = total_sector / 2;
>> +       break;
>> +
>> +       case 7:
>> +               protected_sector = total_sector;
>> +       break;
>> +
>> +       default:
>> +               ret = -EINVAL;
>> +               goto free_protected;
>> +       }
>> +
>> +       while (protected_sector) {
>> +               protected[total_sector - protected_sector] = 1;
>> +               protected_sector--;
>> +       }
>> +
>> +       if (protected[offset/flash->erase_size])
>> +               return 1;
>> +       else
>> +               return 0;
>> +
>> +free_protected:
>> +       free(protected);
>> +       return ret;
>> +}
>> +#else
>> +static int is_protected(struct spi_flash *flash, u32 offset)
>> +{
>> +       return 0;
>> +}
>> +#endif
>> +
>>  int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
>>  {
>>         u32 erase_size, erase_addr;
>> @@ -294,10 +372,17 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
>>                 debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
>>                       cmd[2], cmd[3], erase_addr);
>>
>> -               ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
>> -               if (ret < 0) {
>> -                       debug("SF: erase failed\n");
>> +               if (is_protected(flash, offset) > 0) {
>> +                       printf("Skipping to erase protected offset 0x%x\n",
>> +                              offset);
>>                         break;
>> +               } else {
>> +                       ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
>> +                                                    NULL, 0);
>> +                       if (ret < 0) {
>> +                               debug("SF: erase failed\n");
>> +                               break;
>> +                       }
>
> So this seems to be locking sector area which is been protected, why
> it's needed on erase? why can't we do it while probe? any side

We do not want to erase a sector that is protected, so that's why we
skip it during the erase process.

> effects. and also do we have any way to unlock the protected sectors?
> does that really a need?

Yes, we can lock and unlock sectors using the
spi_flash_cmd_write_status() function. Please see patch 5/5.


-- 
Otavio Salvador                             O.S. Systems
http://www.ossystems.com.br        http://code.ossystems.com.br
Mobile: +55 (53) 9981-7854            Mobile: +1 (347) 903-9750


More information about the U-Boot mailing list