sf: stmicro: added support for sector lock interfaces.
Change-Id: I1269114da41f5f343619ee6fce7cac1261a509da
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index 3f814de..985880a 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -46,6 +46,8 @@
#define CMD_M25PXX_DP 0xb9 /* Deep Power-down */
#define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */
#define CMD_M25PXX_EN4BYTEADDR 0xb7 /* Enter 4-byte address mode */
+#define CMD_M25PXX_RDLR 0xe8 /* Read Lock Register */
+#define CMD_M25PXX_WRLR 0xe5 /* Write Lock Register */
#define STM_ID_M25P16 0x15
#define STM_ID_M25P20 0x12
@@ -198,6 +200,29 @@
return -1;
}
+static u8 *stmicro_set_cmd_addr(struct stmicro_spi_flash *stm, u8 *cmd,
+ u32 addr)
+{
+ unsigned long page_addr = addr / stm->params->page_size;
+
+ switch (stm->params->addr_cycles) {
+ case 4:
+ *cmd++ = page_addr >> 16;
+ *cmd++ = page_addr >> 8;
+ *cmd++ = page_addr;
+ *cmd++ = addr % stm->params->page_size;
+ break;
+ case 3:
+ default:
+ *cmd++ = page_addr >> 8;
+ *cmd++ = page_addr;
+ *cmd++ = addr % stm->params->page_size;
+ break;
+ }
+
+ return cmd;
+}
+
static int stmicro_read_fast(struct spi_flash *flash,
u32 offset, size_t len, void *buf)
{
@@ -431,6 +456,88 @@
spi_release_bus(flash->spi);
return ret;
}
+
+static int stmicro_read_lock(struct spi_flash *flash, u32 offset, int *lock)
+{
+ u8 cmd[5];
+ u8 data;
+ int ret;
+ struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+
+ ret = spi_claim_bus(flash->spi);
+ if (ret)
+ return ret;
+
+ cmd[0] = CMD_M25PXX_RDLR;
+ stmicro_set_cmd_addr(stm, &cmd[1], offset);
+ ret = spi_flash_cmd_read(flash->spi, cmd, 1 + stm->params->addr_cycles,
+ &data, 1);
+ if (ret < 0) {
+ debug("SF: STMicro Read Lock register failed\n");
+ return ret;
+ }
+
+ spi_release_bus(flash->spi);
+ *lock = data;
+
+ return 0;
+}
+
+static int stmicro_write_lock(struct spi_flash *flash, u32 offset, int lock)
+{
+ u8 cmd[5];
+ u8 data = lock;
+ int ret;
+ struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+
+ ret = spi_claim_bus(flash->spi);
+ if (ret)
+ return ret;
+
+ ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0);
+ if (ret < 0) {
+ debug("SF: Write Enable failed\n");
+ return ret;
+ }
+
+ cmd[0] = CMD_M25PXX_WRLR;
+ stmicro_set_cmd_addr(stm, &cmd[1], offset);
+ ret = spi_flash_cmd_write(flash->spi, cmd, 1 + stm->params->addr_cycles,
+ &data, 1);
+ if (ret < 0) {
+ debug("SF: STMicro Write Lock register failed\n");
+ return ret;
+ }
+
+ spi_release_bus(flash->spi);
+
+ return 0;
+}
+
+static int stmicro_lock(struct spi_flash *flash, u32 offset, size_t len,
+ int lock)
+{
+ int ret;
+ u32 cur;
+ u32 end;
+ u32 sector_size;
+ struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
+
+ sector_size
+ = (u32)stm->params->page_size * stm->params->pages_per_sector;
+ cur = (offset / sector_size) * sector_size;
+ end = offset + len;
+
+ while (cur < end) {
+ ret = stmicro_write_lock(flash, cur, lock);
+ if (ret)
+ return ret;
+
+ cur += sector_size;
+ }
+
+ return 0;
+}
#endif
struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
@@ -466,6 +573,9 @@
stm->flash.read = stmicro_read_fast;
#ifdef CONFIG_SPI_FLASH_PROTECTION
stm->flash.protect = stmicro_protect;
+ stm->flash.read_lock = stmicro_read_lock;
+ stm->flash.write_lock = stmicro_write_lock;
+ stm->flash.lock = stmicro_lock;
#endif
stm->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;