Winbond parts such as W25Q64FV and Spansion parts such as S25FL128S
support two status register protection bits. Implement sr_protect for
Winbond and Spansion devices.

 -------------------------------------------------------
 | SRP1 | SRP0 | Method   | Description                |
 -------------------------|-----------------------------
 | 0    | 0    | Software | Blocked until write enable |
 | 0    | 1    | Hardware | Blocked if WP pin is low   |
 | 1    | 0    | Power    | Blocked until power down   |
 | 1    | 1    | OTP      | Blocked permanently        |
 -------------------------------------------------------

Not all devices support OTP.

Signed-off-by: George McCollister <george.mccollis...@gmail.com>
---
 drivers/mtd/spi/sf_internal.h |  1 +
 drivers/mtd/spi/spi_flash.c   | 57 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 1b576e8..7a97fc4 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -82,6 +82,7 @@ enum spi_nor_option_flags {
 #define SR_BP1                         BIT(3)  /* Block protect 1 */
 #define SR_BP2                         BIT(4)  /* Block protect 2 */
 #define SR_SRP0                                BIT(7)  /* Status register 
protect 0 */
+#define SR_SRP1                                BIT(0)  /* Status register 
protect 1 */
 
 /* Flash timeout values */
 #define SPI_FLASH_PROG_TIMEOUT         (2 * CONFIG_SYS_HZ)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 392146b..80e67e6 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -874,6 +874,62 @@ int stm_sr_protect(struct spi_flash *flash, enum 
srp_method method)
 }
 #endif
 
+#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
+/*
+ * Set status register protection method for parts with two protection bits
+ *
+ * Returns negative on errors, 0 on success.
+ */
+int winbond_sr_protect(struct spi_flash *flash, enum srp_method method)
+{
+       u8 status_old[2], status_new[2];
+       u8 mask[2] = {SR_SRP0, SR_SRP1};
+       u8 val[2];
+       u8 cmd;
+       int ret;
+
+       ret = read_sr(flash, &status_old[0]);
+       if (ret < 0)
+               return ret;
+
+       ret = read_cr(flash, &status_old[1]);
+       if (ret < 0)
+               return ret;
+
+       switch (method) {
+       case SRP_SOFTWARE:
+               val[0] = 0;
+               val[1] = 0;
+               break;
+       case SRP_HARDWARE:
+               val[0] = SR_SRP0;
+               val[1] = 0;
+               break;
+       case SRP_POWER:
+               val[0] = 0;
+               val[1] = SR_SRP1;
+               break;
+       case SRP_OTP:
+               val[0] = SR_SRP0;
+               val[1] = SR_SRP1;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       status_new[0] = (status_old[0] & ~mask[0]) | val[0];
+       status_new[1] = (status_old[1] & ~mask[1]) | val[1];
+
+       cmd = CMD_WRITE_STATUS;
+       ret = spi_flash_write_common(flash, &cmd, 1, &status_new, 2);
+       if (ret) {
+               debug("SF: fail to write status register\n");
+               return ret;
+       }
+
+       return 0;
+}
+#endif
 
 #ifdef CONFIG_SPI_FLASH_MACRONIX
 static int macronix_quad_enable(struct spi_flash *flash)
@@ -1169,6 +1225,7 @@ int spi_flash_scan(struct spi_flash *flash)
                flash->flash_lock = stm_lock;
                flash->flash_unlock = stm_unlock;
                flash->flash_is_locked = stm_is_locked;
+               flash->sr_protect = winbond_sr_protect;
                break;
 #endif
        default:
-- 
2.9.3

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to