layerscape: add 64b/32b target for ls1012ardb device
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.4 / 1105-mtd-spi-nor-add-DDR-quad-read-support.patch
diff --git a/target/linux/layerscape/patches-4.4/1105-mtd-spi-nor-add-DDR-quad-read-support.patch b/target/linux/layerscape/patches-4.4/1105-mtd-spi-nor-add-DDR-quad-read-support.patch
new file mode 100644 (file)
index 0000000..bed44b8
--- /dev/null
@@ -0,0 +1,181 @@
+From 924f021c0344554a4b61746e5c4dcfc91d618ce2 Mon Sep 17 00:00:00 2001
+From: Yunhui Cui <yunhui.cui@nxp.com>
+Date: Thu, 18 Feb 2016 16:41:53 +0800
+Subject: [PATCH 105/113] mtd: spi-nor: add DDR quad read support
+
+This patch adds the DDR quad read support by the following:
+
+  [1] add SPI_NOR_DDR_QUAD read mode.
+
+  [2] add DDR Quad read opcodes:
+    SPINOR_OP_READ_1_4_4_D / SPINOR_OP_READ4_1_4_4_D
+
+  [3] add set_ddr_quad_mode() to initialize for the DDR quad read.
+        Currently it only works for Spansion NOR.
+
+  [4] set dummy with 6 for Spansion family
+Test this patch for Spansion s25fl128s NOR flash.
+
+Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
+---
+ drivers/mtd/spi-nor/spi-nor.c |   53 ++++++++++++++++++++++++++++++++++++-----
+ include/linux/mtd/spi-nor.h   |    8 +++++--
+ 2 files changed, 53 insertions(+), 8 deletions(-)
+
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -73,7 +73,8 @@ struct flash_info {
+ #define       SECT_4K_PMC             0x10    /* SPINOR_OP_BE_4K_PMC works uniformly */
+ #define       SPI_NOR_DUAL_READ       0x20    /* Flash supports Dual Read */
+ #define       SPI_NOR_QUAD_READ       0x40    /* Flash supports Quad Read */
+-#define       USE_FSR                 0x80    /* use flag status register */
++#define SPI_NOR_DDR_QUAD_READ 0x80    /* Flash supports DDR Quad Read */
++#define       USE_FSR                 0x100   /* use flag status register */
+ };
+ #define JEDEC_MFR(info)       ((info)->id[0])
+@@ -144,13 +145,17 @@ static int read_cr(struct spi_nor *nor)
+  * It can be used to support more commands with
+  * different dummy cycle requirements.
+  */
+-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
++static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor,
++                      const struct flash_info *info)
+ {
+       switch (nor->flash_read) {
+       case SPI_NOR_FAST:
+       case SPI_NOR_DUAL:
+       case SPI_NOR_QUAD:
+               return 8;
++      case SPI_NOR_DDR_QUAD:
++              if (JEDEC_MFR(info) == SNOR_MFR_SPANSION)
++                      return 6;
+       case SPI_NOR_NORMAL:
+               return 0;
+       }
+@@ -797,7 +802,8 @@ static const struct flash_info spi_nor_i
+       { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
+       { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
+       { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
+-      { "s25fl128s",  INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
++      { "s25fl128s",  INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ
++                      | SPI_NOR_DDR_QUAD_READ) },
+       { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+       { "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+       { "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
+@@ -1186,6 +1192,23 @@ static int spansion_quad_enable(struct s
+       return 0;
+ }
++static int set_ddr_quad_mode(struct spi_nor *nor, const struct flash_info *info)
++{
++      int status;
++
++      switch (JEDEC_MFR(info)) {
++      case SNOR_MFR_SPANSION:
++              status = spansion_quad_enable(nor);
++              if (status) {
++                      dev_err(nor->dev, "Spansion DDR quad-read not enabled\n");
++                      return status;
++              }
++              return status;
++      default:
++              return -EINVAL;
++      }
++}
++
+ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
+ {
+       int status;
+@@ -1375,8 +1398,15 @@ int spi_nor_scan(struct spi_nor *nor, co
+       if (info->flags & SPI_NOR_NO_FR)
+               nor->flash_read = SPI_NOR_NORMAL;
+-      /* Quad/Dual-read mode takes precedence over fast/normal */
+-      if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
++      /* DDR Quad/Quad/Dual-read mode takes precedence over fast/normal */
++      if (mode == SPI_NOR_DDR_QUAD && info->flags & SPI_NOR_DDR_QUAD_READ) {
++              ret = set_ddr_quad_mode(nor, info);
++              if (ret) {
++                      dev_err(dev, "DDR quad mode not supported\n");
++                      return ret;
++              }
++              nor->flash_read = SPI_NOR_DDR_QUAD;
++      } else if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
+               ret = set_quad_mode(nor, info);
+               if (ret) {
+                       dev_err(dev, "quad mode not supported\n");
+@@ -1389,6 +1419,14 @@ int spi_nor_scan(struct spi_nor *nor, co
+       /* Default commands */
+       switch (nor->flash_read) {
++      case SPI_NOR_DDR_QUAD:
++              if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) { /* Spansion */
++                      nor->read_opcode = SPINOR_OP_READ_1_4_4_D;
++              } else {
++                      dev_err(dev, "DDR Quad Read is not supported.\n");
++                      return -EINVAL;
++              }
++              break;
+       case SPI_NOR_QUAD:
+               nor->read_opcode = SPINOR_OP_READ_1_1_4;
+               break;
+@@ -1416,6 +1454,9 @@ int spi_nor_scan(struct spi_nor *nor, co
+               if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
+                       /* Dedicated 4-byte command set */
+                       switch (nor->flash_read) {
++                      case SPI_NOR_DDR_QUAD:
++                              nor->read_opcode = SPINOR_OP_READ4_1_4_4_D;
++                              break;
+                       case SPI_NOR_QUAD:
+                               nor->read_opcode = SPINOR_OP_READ4_1_1_4;
+                               break;
+@@ -1445,7 +1486,7 @@ int spi_nor_scan(struct spi_nor *nor, co
+               return -EINVAL;
+       }
+-      nor->read_dummy = spi_nor_read_dummy_cycles(nor);
++      nor->read_dummy = spi_nor_read_dummy_cycles(nor, info);
+       dev_info(dev, "%s (%lld Kbytes)\n", info->name,
+                       (long long)mtd->size >> 10);
+--- a/include/linux/mtd/spi-nor.h
++++ b/include/linux/mtd/spi-nor.h
+@@ -30,10 +30,11 @@
+ /*
+  * Note on opcode nomenclature: some opcodes have a format like
+- * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
++ * SPINOR_OP_FUNCTION{4,}_x_y_z{_D}. The numbers x, y,and z stand for the number
+  * of I/O lines used for the opcode, address, and data (respectively). The
+  * FUNCTION has an optional suffix of '4', to represent an opcode which
+- * requires a 4-byte (32-bit) address.
++ * requires a 4-byte (32-bit) address. The suffix of 'D' stands for the
++ * DDR mode.
+  */
+ /* Flash opcodes. */
+@@ -44,6 +45,7 @@
+ #define SPINOR_OP_READ_FAST   0x0b    /* Read data bytes (high frequency) */
+ #define SPINOR_OP_READ_1_1_2  0x3b    /* Read data bytes (Dual SPI) */
+ #define SPINOR_OP_READ_1_1_4  0x6b    /* Read data bytes (Quad SPI) */
++#define SPINOR_OP_READ_1_4_4_D        0xed    /* Read data bytes (DDR Quad SPI) */
+ #define SPINOR_OP_PP          0x02    /* Page program (up to 256 bytes) */
+ #define SPINOR_OP_BE_4K               0x20    /* Erase 4KiB block */
+ #define SPINOR_OP_BE_4K_PMC   0xd7    /* Erase 4KiB block on PMC chips */
+@@ -59,6 +61,7 @@
+ #define SPINOR_OP_READ4_FAST  0x0c    /* Read data bytes (high frequency) */
+ #define SPINOR_OP_READ4_1_1_2 0x3c    /* Read data bytes (Dual SPI) */
+ #define SPINOR_OP_READ4_1_1_4 0x6c    /* Read data bytes (Quad SPI) */
++#define SPINOR_OP_READ4_1_4_4_D       0xee    /* Read data bytes (DDR Quad SPI) */
+ #define SPINOR_OP_PP_4B               0x12    /* Page program (up to 256 bytes) */
+ #define SPINOR_OP_SE_4B               0xdc    /* Sector erase (usually 64KiB) */
+@@ -107,6 +110,7 @@ enum read_mode {
+       SPI_NOR_FAST,
+       SPI_NOR_DUAL,
+       SPI_NOR_QUAD,
++      SPI_NOR_DDR_QUAD,
+ };
+ #define SPI_NOR_MAX_CMD_SIZE  8