diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/spi/sf_internal.h | 9 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_ops.c | 14 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_probe.c | 13 |
3 files changed, 34 insertions, 2 deletions
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index ac493f1f76..8793f1865a 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -176,6 +176,15 @@ int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs); /* Program the status register */ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws); +/* Lock stmicro spi flash region */ +int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); + +/* Unlock stmicro spi flash region */ +int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); + +/* Check if a stmicro spi flash region is completely locked */ +int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); + /* Read the config register */ int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc); 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; diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index c000c53274..bc05d30221 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -182,6 +182,19 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, flash->read = spi_flash_cmd_read_ops; #endif + /* lock hooks are flash specific - assign them based on idcode0 */ + switch (idcode[0]) { +#ifdef CONFIG_SPI_FLASH_STMICRO + case SPI_FLASH_CFI_MFR_STMICRO: + flash->flash_lock = stm_lock; + flash->flash_unlock = stm_unlock; + flash->flash_is_locked = stm_is_locked; +#endif + break; + default: + debug("SF: Lock ops not supported for %02x flash\n", idcode[0]); + } + /* Compute the flash size */ flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; /* |