diff options
author | Alison Wang <b18965@freescale.com> | 2017-05-19 02:33:06 (GMT) |
---|---|---|
committer | Xie Xiaobo <xiaobo.xie@nxp.com> | 2017-09-25 07:25:33 (GMT) |
commit | ec3c0dcf7e4c5c23341313bdaf4588204efc6b7c (patch) | |
tree | 6f45c327141aea25ab76935e64b4d0a6ae839467 /drivers/mtd | |
parent | 1952ca9b29b1ef96bed5c1e587265ac828f961d7 (diff) | |
download | linux-ec3c0dcf7e4c5c23341313bdaf4588204efc6b7c.tar.xz |
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>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3f19e8f..8e0d048 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -75,7 +75,8 @@ struct flash_info { #define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ #define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ #define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ -#define USE_FSR BIT(7) /* use flag status register */ +#define USE_FSR BIT(13) /* use flag status register */ +#define SPI_NOR_DDR_QUAD_READ BIT(13) /* Flash supports DDR Quad Read */ #define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ #define SPI_NOR_HAS_TB BIT(9) /* * Flash SR has Top/Bottom (TB) protect @@ -169,6 +170,8 @@ static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) case SPI_NOR_DUAL: case SPI_NOR_QUAD: return 8; + case SPI_NOR_DDR_QUAD: + return 6; case SPI_NOR_NORMAL: return 0; } @@ -1068,7 +1071,8 @@ static const struct flash_info spi_nor_ids[] = { { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, { "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, 0)}, - { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | 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) }, { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)}, { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, @@ -1517,6 +1521,24 @@ static int spansion_quad_enable(struct spi_nor *nor) 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; @@ -1666,7 +1688,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) ret &= SPI_NOR_MICRON_WRITE_ENABLE; write_enable(nor); - write_sr(nor, ret) + write_sr(nor, ret); } if (EXT_ID(info) == SPINOR_S25FS_FAMILY_ID) { @@ -1751,9 +1773,15 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) /* Some devices cannot do fast-read, no matter what DT tells us */ 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"); @@ -1766,6 +1794,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) /* Default commands */ 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_READ_1_1_4; break; |