Add 4-byte address supports, so-that SPI-NOR chips
has > 16MiB should accessible.

Signed-off-by: Jagan Teki <ja...@openedev.com>
---
 drivers/mtd/spi-nor/m25p80.c  |  1 +
 drivers/mtd/spi-nor/spi-nor.c | 36 ++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spi-nor.h   |  6 +++++-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/m25p80.c b/drivers/mtd/spi-nor/m25p80.c
index 740d3f6..285fae5 100644
--- a/drivers/mtd/spi-nor/m25p80.c
+++ b/drivers/mtd/spi-nor/m25p80.c
@@ -31,6 +31,7 @@ static void m25p_addr2cmd(struct spi_nor *nor, unsigned int 
addr, u8 *cmd)
        cmd[1] = addr >> (nor->addr_width * 8 -  8);
        cmd[2] = addr >> (nor->addr_width * 8 - 16);
        cmd[3] = addr >> (nor->addr_width * 8 - 24);
+       cmd[4] = addr >> (nor->addr_width * 8 - 32);
 }
 
 static int m25p_cmdsz(struct spi_nor *nor)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 12e7cfe..103b68b 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -378,6 +378,36 @@ static int sst_write_bp(struct udevice *dev, loff_t to, 
size_t len,
 }
 #endif
 
+/* Enable/disable 4-byte addressing mode. */
+static int set_4byte(struct spi_nor *nor, const struct spi_nor_info *info,
+                    int enable)
+{
+       int status;
+       bool need_wren = false;
+       u8 cmd;
+
+       switch (JEDEC_MFR(info)) {
+       case SNOR_MFR_MICRON:
+               /* Some Micron need WREN command; all will accept it */
+               need_wren = true;
+       case SNOR_MFR_MACRONIX:
+       case SNOR_MFR_WINBOND:
+               if (need_wren)
+                       write_enable(nor);
+
+               cmd = enable ? SNOR_OP_EN4B : SNOR_OP_EX4B;
+               status = nor->write_reg(nor, cmd, NULL, 0);
+               if (need_wren)
+                       write_disable(nor);
+
+               return status;
+       default:
+               /* Spansion style */
+               nor->cmd_buf[0] = enable << 7;
+               return nor->write_reg(nor, SNOR_OP_BRWR, nor->cmd_buf, 1);
+       }
+}
+
 #ifdef CONFIG_SPI_NOR_MACRONIX
 static int macronix_quad_enable(struct spi_nor *nor)
 {
@@ -613,6 +643,12 @@ int spi_nor_scan(struct udevice *dev)
        }
 
        nor->addr_width = 3;
+       if (mtd->size > SNOR_16MB_BOUN) {
+               nor->addr_width = 4;
+               ret = set_4byte(nor, info, true);
+               if (ret)
+                       return ret;
+       }
 
        /* Dummy cycles for read */
        switch (nor->read_opcode) {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 4e5b3ba..ad573db 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -62,6 +62,10 @@
 #define SNOR_OP_BP             0x02    /* Byte program */
 #define SNOR_OP_AAI_WP         0xad    /* Auto addr increment word program */
 
+/* Used for Macronix and Winbond flashes. */
+#define SNOR_OP_EN4B           0xb7    /* Enter 4-byte mode */
+#define SNOR_OP_EX4B           0xe9    /* Exit 4-byte mode */
+
 /* Status Register bits. */
 #define SR_WIP                 BIT(0)  /* Write in progress */
 #define SR_WEL                 BIT(1)  /* Write enable latch */
@@ -83,7 +87,7 @@
 /* Flash timeout values */
 #define SNOR_READY_WAIT_PROG   (2 * CONFIG_SYS_HZ)
 #define SNOR_READY_WAIT_ERASE  (5 * CONFIG_SYS_HZ)
-#define SNOR_MAX_CMD_SIZE      4
+#define SNOR_MAX_CMD_SIZE      6
 #define SNOR_16MB_BOUN         0x1000000
 
 enum snor_option_flags {
-- 
2.7.4

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

Reply via email to