diff options
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.patch | 181 |
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 0000000..bed44b8 --- /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 |