[U-Boot] [PATCH 4/5] sf: Add status register protect for Winbond

George McCollister george.mccollister at gmail.com
Mon Oct 10 20:58:00 CEST 2016


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.mccollister at 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



More information about the U-Boot mailing list