summaryrefslogtreecommitdiff
path: root/drivers/mtd/spi/sf_ops.c
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@freescale.com>2015-11-05 12:43:42 -0200
committerTom Rini <trini@konsulko.com>2015-11-05 16:47:06 -0500
commitc3c016cf75360c2a0d0a065b64b438aaf7720576 (patch)
tree4152dc73b153374e211552a472daa21de5d6f0a9 /drivers/mtd/spi/sf_ops.c
parent41b358d7a7c9f29eca4a439fba0ae679100a9ad5 (diff)
sf: Add SPI NOR protection mechanism
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. Tested on a mx6qsabresd: => sf probe SF: Detected M25P32 with page size 256 Bytes, erase size 64 KiB, total 4 MiB => sf protect lock 0x3f0000 0x10000 => sf erase 0x3f0000 0x10000 offset 0x3f0000 is protected and cannot be erased SF: 65536 bytes @ 0x3f0000 Erased: ERROR => sf protect unlock 0x3f0000 0x10000 => sf erase 0x3f0000 0x10000 SF: 65536 bytes @ 0x3f0000 Erased: OK Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com> [re-worked to fit the lock common to dm and non-dm] Signed-off-by: Jagan Teki <jteki@openedev.com> Reviewed-by: Tom Rini <trini@konsulko.com> Reviewed-by: Heiko Schocher <hs@denx.de> Reviewed-by: Jagan Teki <jteki@openedev.com>
Diffstat (limited to 'drivers/mtd/spi/sf_ops.c')
-rw-r--r--drivers/mtd/spi/sf_ops.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index 6c87ba60fd..d8324645b2 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -268,6 +268,11 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
return -1;
}
+ if (flash->flash_is_locked(flash, offset, len) > 0) {
+ printf("offset 0x%x is protected and cannot be erased\n", offset);
+ return -EINVAL;
+ }
+
cmd[0] = flash->erase_cmd;
while (len) {
erase_addr = offset;
@@ -310,6 +315,11 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
page_size = flash->page_size;
+ if (flash->flash_is_locked(flash, offset, len) > 0) {
+ printf("offset 0x%x is protected and cannot be written\n", offset);
+ return -EINVAL;
+ }
+
cmd[0] = flash->write_cmd;
for (actual = 0; actual < len; actual += chunk_len) {
write_addr = offset;
@@ -589,7 +599,7 @@ static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs,
/*
* Return 1 if the entire region is locked, 0 otherwise
*/
-static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, u32 len,
+static int stm_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len,
u8 sr)
{
loff_t lock_offs;
@@ -607,7 +617,7 @@ static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, u32 len,
* Returns 1 if entire region is locked, 0 if any portion is unlocked, and
* negative on errors.
*/
-int stm_is_locked(struct spi_flash *flash, loff_t ofs, u32 len)
+int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len)
{
int status;
u8 sr;