@@ -2751,6 +2751,20 @@ CBFS (Coreboot Filesystem) support
Timeout for waiting until spi transfer completed.
default: (CONFIG_SYS_HZ/100) /* 10 ms */
+ CONFIG_SPI_NOR_PROTECTION_STM
+ Enable the built-in protection mechanism provided by the
+ BP2, BP1 and BP0 bits from the status register present
+ on ST-Micro flashes such as M25P32. Please refer to the
+ M25P32 datasheet to understand how to program these bits
+ in order to protect a selected region of the SPI NOR flash.
+ This same bit protection programming model applies to SPI
+ NOR flashes from other manufacturers such as:
+ - Micron M25P32
+ - SST SST25VF032B
+ In order to program the bit protection bits of the status
+ register the spi_flash_cmd_write_status() function can be
+ used.
+
- FPGA Support: CONFIG_FPGA
Enables FPGA subsystem.
@@ -264,6 +264,84 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
return ret;
}
+#ifdef CONFIG_SPI_NOR_PROTECTION_STM
+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;
+
+ 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;
+ }
}
offset += erase_size;
@@ -256,12 +256,14 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
}
#endif
+#if !defined(CONFIG_SPI_NOR_PROTECTION_STM)
/* Flash powers up read-only, so clear BP# bits */
#if defined(CONFIG_SPI_FLASH_ATMEL) || \
defined(CONFIG_SPI_FLASH_MACRONIX) || \
defined(CONFIG_SPI_FLASH_SST)
spi_flash_cmd_write_status(flash, 0);
#endif
+#endif
return 0;
}