aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-4.4/1105-mtd-spi-nor-add-DDR-quad-read-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-4.4/1105-mtd-spi-nor-add-DDR-quad-read-support.patch')
-rw-r--r--target/linux/layerscape/patches-4.4/1105-mtd-spi-nor-add-DDR-quad-read-support.patch181
1 files changed, 181 insertions, 0 deletions
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
index 0000000000..bed44b8783
--- /dev/null
+++ b/target/linux/layerscape/patches-4.4/1105-mtd-spi-nor-add-DDR-quad-read-support.patch
@@ -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