123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- 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 SPI_NOR_HAS_LOCK 0x100 /* Flash supports lock/unlock via SR */
- };
-
- @@ -145,13 +146,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;
- }
- @@ -805,7 +810,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) },
- @@ -1201,6 +1207,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;
- @@ -1391,8 +1414,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");
- @@ -1405,6 +1435,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;
- @@ -1432,6 +1470,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;
- @@ -1461,7 +1502,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
|