}
#endif
+/**
+ * read_sr3() - Read status register 3 unique to newer Winbond flashes
+ * @nor: pointer to a 'struct spi_nor'
+ */
+static int read_sr3(struct spi_nor *nor)
+{
+ int ret;
+ u8 val;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR3, &val, 1);
+ if (ret < 0) {
+ dev_dbg(nor->dev, "error %d reading SR3\n", ret);
+ return ret;
+ }
+
+ return val;
+}
+
/*
* Write status register 1 byte
* Returns negative if error occurred.
return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1);
}
+/**
+ * write_sr3() - Write status register 3 unique to newer Winbond flashes
+ * @nor: pointer to a 'struct spi_nor'
+ * @val: value to be written into SR3
+ */
+static int write_sr3(struct spi_nor *nor, u8 val)
+{
+ nor->cmd_buf[0] = val;
+ return nor->write_reg(nor, SPINOR_OP_WRSR3, nor->cmd_buf, 1);
+}
+
/*
* Set write enable latch with Write Enable command.
* Returns negative if error occurred.
write_enable(nor);
write_sr(nor, 0);
spi_nor_wait_till_ready(nor);
+
+ /*
+ * Some Winbond SPI NORs have special SR3 register which is
+ * used among other things to control whether non-standard
+ * "Individual Block/Sector Write Protection" (WPS bit)
+ * locking scheme is activated. This non-standard locking
+ * scheme is not supported by either U-Boot or Linux SPI
+ * NOR stack so make sure it is disabled, otherwise the
+ * SPI NOR may appear locked for no obvious reason.
+ */
+ if (JEDEC_MFR(nor->info) == SNOR_MFR_WINBOND) {
+ err = read_sr3(nor);
+ if (err > 0 && err & SR3_WPS) {
+ write_enable(nor);
+ write_sr3(nor, err & ~SR3_WPS);
+ write_disable(nor);
+ }
+ }
}
if (nor->quad_enable) {
#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
#define SPINOR_OP_RDSR2 0x3f /* Read status register 2 */
#define SPINOR_OP_WRSR2 0x3e /* Write status register 2 */
+#define SPINOR_OP_RDSR3 0x15 /* Read status register 3 */
+#define SPINOR_OP_WRSR3 0x11 /* Write status register 3 */
#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */
*/
#define SNOR_FLASH_CNT_MAX 2
+/* Status Register 3 bits. */
+#define SR3_WPS BIT(2)
+
/* For Cypress flash. */
#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */
#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */