sf: Fix quad bit set for micron devices
authorJagan Teki <jteki@openedev.com>
Mon, 14 Dec 2015 12:45:39 +0000 (18:15 +0530)
committerJagan Teki <jteki@openedev.com>
Wed, 13 Jan 2016 13:17:26 +0000 (18:47 +0530)
Setting up quad bit for micron devices need to do the
same way as other flash devices like spansion, winbond
etc does using enhanced volatile config register so this
patch adds this support instead of printing "QEB is volatile"

Cc: Simon Glass <sjg@chromium.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Peter Pan <peterpandong@micron.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
Signed-off-by: Jagan Teki <jteki@openedev.com>
drivers/mtd/spi/sf_internal.h
drivers/mtd/spi/spi_flash.c

index 561abc3..55ba81e 100644 (file)
@@ -77,6 +77,7 @@ enum spi_nor_option_flags {
 #define CMD_WRITE_DISABLE              0x04
 #define CMD_WRITE_ENABLE               0x06
 #define CMD_QUAD_PAGE_PROGRAM          0x32
+#define CMD_WRITE_EVCR                 0x61
 
 /* Read commands */
 #define CMD_READ_ARRAY_SLOW            0x03
@@ -90,6 +91,7 @@ enum spi_nor_option_flags {
 #define CMD_READ_STATUS1               0x35
 #define CMD_READ_CONFIG                        0x35
 #define CMD_FLAG_STATUS                        0x70
+#define CMD_READ_EVCR                  0x65
 
 /* Bank addr access commands */
 #ifdef CONFIG_SPI_FLASH_BAR
@@ -104,6 +106,7 @@ enum spi_nor_option_flags {
 #define STATUS_QEB_WINSPAN             BIT(1)
 #define STATUS_QEB_MXIC                        BIT(6)
 #define STATUS_PEC                     BIT(7)
+#define STATUS_QEB_MICRON              BIT(7)
 #define SR_BP0                         BIT(2)  /* Block protect 0 */
 #define SR_BP1                         BIT(3)  /* Block protect 1 */
 #define SR_BP2                         BIT(4)  /* Block protect 2 */
index e4b8ce9..d9124c5 100644 (file)
@@ -111,6 +111,37 @@ static int write_cr(struct spi_flash *flash, u8 wc)
 }
 #endif
 
+#ifdef CONFIG_SPI_FLASH_STMICRO
+static int read_evcr(struct spi_flash *flash, u8 *evcr)
+{
+       int ret;
+       const u8 cmd = CMD_READ_EVCR;
+
+       ret = spi_flash_read_common(flash, &cmd, 1, evcr, 1);
+       if (ret < 0) {
+               debug("SF: error reading EVCR\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int write_evcr(struct spi_flash *flash, u8 evcr)
+{
+       u8 cmd;
+       int ret;
+
+       cmd = CMD_WRITE_EVCR;
+       ret = spi_flash_write_common(flash, &cmd, 1, &evcr, 1);
+       if (ret < 0) {
+               debug("SF: error while writing EVCR register\n");
+               return ret;
+       }
+
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_SPI_FLASH_BAR
 static int spi_flash_write_bar(struct spi_flash *flash, u32 offset)
 {
@@ -843,6 +874,34 @@ static int spansion_quad_enable(struct spi_flash *flash)
 }
 #endif
 
+#ifdef CONFIG_SPI_FLASH_STMICRO
+static int micron_quad_enable(struct spi_flash *flash)
+{
+       u8 qeb_status;
+       int ret;
+
+       ret = read_evcr(flash, &qeb_status);
+       if (ret < 0)
+               return ret;
+
+       if (!(qeb_status & STATUS_QEB_MICRON))
+               return 0;
+
+       ret = write_evcr(flash, qeb_status & ~STATUS_QEB_MICRON);
+       if (ret < 0)
+               return ret;
+
+       /* read EVCR and check it */
+       ret = read_evcr(flash, &qeb_status);
+       if (!(ret >= 0 && !(qeb_status & STATUS_QEB_MICRON))) {
+               printf("SF: Micron EVCR Quad bit not clear\n");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+#endif
+
 static int set_quad_mode(struct spi_flash *flash, u8 idcode0)
 {
        switch (idcode0) {
@@ -857,8 +916,7 @@ static int set_quad_mode(struct spi_flash *flash, u8 idcode0)
 #endif
 #ifdef CONFIG_SPI_FLASH_STMICRO
        case SPI_FLASH_CFI_MFR_STMICRO:
-               debug("SF: QEB is volatile for %02x flash\n", idcode0);
-               return 0;
+               return micron_quad_enable(flash);
 #endif
        default:
                printf("SF: Need set QEB func for %02x flash\n", idcode0);