diff options
author | Allen Xu <b45815@freescale.com> | 2014-03-14 16:18:25 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:58:00 -0400 |
commit | 2f73dd368a1cfdb9f33ead5a115907e16c253670 (patch) | |
tree | 5b21e77a1eb82c86028b58d158ea782a1268f728 | |
parent | a49ce1475f2a9943ec435cd5bc9e2d9606f5bf36 (diff) |
ENGR00303629-2 qspi: support SF25FL128S by enabling DDR Quad IO mode
Enalbe DDR Quad IO mode to support Spansion SF25FL128S NOR flash.
Signed-off-by: Allen Xu <b45815@freescale.com>
-rw-r--r-- | drivers/mtd/spi-nor/fsl-quadspi.c | 65 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 1 |
2 files changed, 53 insertions, 13 deletions
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 3904de65807b..4f8bc62761d6 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c | |||
@@ -193,6 +193,9 @@ | |||
193 | #define SEQID_DDR_QUAD_READ 12 | 193 | #define SEQID_DDR_QUAD_READ 12 |
194 | 194 | ||
195 | #define OPCODE_DDR_QUAD_READ 0x6d | 195 | #define OPCODE_DDR_QUAD_READ 0x6d |
196 | #define OPCODE_DDR_QUAD_IO_READ 0xed /*DDR IO read data bytes*/ | ||
197 | |||
198 | #define MFR_SPAN 0x01 | ||
196 | 199 | ||
197 | enum fsl_qspi_devtype { | 200 | enum fsl_qspi_devtype { |
198 | FSL_QUADSPI_VYBRID, | 201 | FSL_QUADSPI_VYBRID, |
@@ -235,6 +238,7 @@ struct fsl_qspi { | |||
235 | u32 nor_num; | 238 | u32 nor_num; |
236 | u32 clk_rate; | 239 | u32 clk_rate; |
237 | unsigned int chip_base_addr; /* We may support two chips. */ | 240 | unsigned int chip_base_addr; /* We may support two chips. */ |
241 | bool ddr_io_mode; | ||
238 | }; | 242 | }; |
239 | 243 | ||
240 | static inline int is_vybrid_qspi(struct fsl_qspi *q) | 244 | static inline int is_vybrid_qspi(struct fsl_qspi *q) |
@@ -392,23 +396,47 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) | |||
392 | /* DDR QUAD read */ | 396 | /* DDR QUAD read */ |
393 | lut_base = SEQID_DDR_QUAD_READ * 4; | 397 | lut_base = SEQID_DDR_QUAD_READ * 4; |
394 | 398 | ||
395 | if (q->nor_size <= SZ_16M) { | 399 | /*DDR QUAD IO read mode*/ |
396 | cmd = OPCODE_DDR_QUAD_READ; | 400 | if (q->ddr_io_mode) { |
397 | addrlen = ADDR24BIT; | 401 | |
398 | dummy = 8; | 402 | if (q->nor_size <= SZ_16M) { |
399 | } else { | 403 | cmd = OPCODE_DDR_QUAD_IO_READ; |
400 | cmd = OPCODE_DDR_QUAD_READ; | 404 | addrlen = ADDR24BIT; |
401 | addrlen = ADDR32BIT; | 405 | dummy = 3; |
402 | dummy = 6; | 406 | } else { |
403 | } | 407 | cmd = OPCODE_DDR_QUAD_IO_READ; |
408 | addrlen = ADDR32BIT; | ||
409 | dummy = 7; | ||
410 | } | ||
404 | 411 | ||
405 | writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR_DDR, PAD1, addrlen), | 412 | writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR_DDR, PAD4, addrlen), |
406 | base + QUADSPI_LUT(lut_base)); | 413 | base + QUADSPI_LUT(lut_base)); |
407 | writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ_DDR, PAD4, rxfifo), | 414 | writel(LUT0(MODE_DDR, PAD1, 4) | LUT1(DUMMY, PAD1, dummy), |
408 | base + QUADSPI_LUT(lut_base + 1)); | 415 | base + QUADSPI_LUT(lut_base + 1)); |
409 | writel(LUT0(JMP_ON_CS, PAD1, 0), | 416 | writel(LUT0(READ_DDR, PAD4, rxfifo) | LUT1(JMP_ON_CS, PAD1, 0), |
410 | base + QUADSPI_LUT(lut_base + 2)); | 417 | base + QUADSPI_LUT(lut_base + 2)); |
411 | 418 | ||
419 | /*Extended DDR QUAD read mode*/ | ||
420 | } else { | ||
421 | |||
422 | if (q->nor_size <= SZ_16M) { | ||
423 | cmd = OPCODE_DDR_QUAD_READ; | ||
424 | addrlen = ADDR24BIT; | ||
425 | dummy = 8; | ||
426 | } else { | ||
427 | cmd = OPCODE_DDR_QUAD_READ; | ||
428 | addrlen = ADDR32BIT; | ||
429 | dummy = 6; | ||
430 | } | ||
431 | |||
432 | writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR_DDR, PAD1, addrlen), | ||
433 | base + QUADSPI_LUT(lut_base)); | ||
434 | writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ_DDR, PAD4, rxfifo), | ||
435 | base + QUADSPI_LUT(lut_base + 1)); | ||
436 | writel(LUT0(JMP_ON_CS, PAD1, 0), | ||
437 | base + QUADSPI_LUT(lut_base + 2)); | ||
438 | } | ||
439 | |||
412 | fsl_qspi_lock_lut(q); | 440 | fsl_qspi_lock_lut(q); |
413 | } | 441 | } |
414 | 442 | ||
@@ -441,7 +469,9 @@ static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) | |||
441 | case OPCODE_BRWR: | 469 | case OPCODE_BRWR: |
442 | return SEQID_BRWR; | 470 | return SEQID_BRWR; |
443 | case OPCODE_DDR_QUAD_READ: | 471 | case OPCODE_DDR_QUAD_READ: |
472 | case OPCODE_DDR_QUAD_IO_READ: | ||
444 | return SEQID_DDR_QUAD_READ; | 473 | return SEQID_DDR_QUAD_READ; |
474 | |||
445 | default: | 475 | default: |
446 | dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd); | 476 | dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd); |
447 | break; | 477 | break; |
@@ -865,6 +895,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
865 | bool has_second_chip = false; | 895 | bool has_second_chip = false; |
866 | const struct of_device_id *of_id = | 896 | const struct of_device_id *of_id = |
867 | of_match_device(fsl_qspi_dt_ids, &pdev->dev); | 897 | of_match_device(fsl_qspi_dt_ids, &pdev->dev); |
898 | u8 jedec_mfr_id; | ||
868 | 899 | ||
869 | q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); | 900 | q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); |
870 | if (!q) | 901 | if (!q) |
@@ -976,6 +1007,11 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
976 | if (!id) | 1007 | if (!id) |
977 | goto map_failed; | 1008 | goto map_failed; |
978 | 1009 | ||
1010 | /*get the NOR chip manufacture id*/ | ||
1011 | jedec_mfr_id = (*(u32 *)(id->driver_data)) >> 16; | ||
1012 | if (MFR_SPAN == jedec_mfr_id) | ||
1013 | q->ddr_io_mode = true; | ||
1014 | |||
979 | ret = of_property_read_u32(np, "spi-max-frequency", | 1015 | ret = of_property_read_u32(np, "spi-max-frequency", |
980 | &q->clk_rate); | 1016 | &q->clk_rate); |
981 | if (ret < 0) | 1017 | if (ret < 0) |
@@ -1014,7 +1050,10 @@ static int fsl_qspi_probe(struct platform_device *pdev) | |||
1014 | nor->page_size = q->devtype_data->txfifo; | 1050 | nor->page_size = q->devtype_data->txfifo; |
1015 | 1051 | ||
1016 | /* Set DDR QUAD READ, we will remove the hardcode in future.*/ | 1052 | /* Set DDR QUAD READ, we will remove the hardcode in future.*/ |
1017 | nor->read_opcode = OPCODE_DDR_QUAD_READ; | 1053 | if (q->ddr_io_mode) |
1054 | nor->read_opcode = OPCODE_DDR_QUAD_IO_READ; | ||
1055 | else | ||
1056 | nor->read_opcode = OPCODE_DDR_QUAD_READ; | ||
1018 | 1057 | ||
1019 | i++; | 1058 | i++; |
1020 | } | 1059 | } |
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 84330077b4c0..1353cffc68b4 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
@@ -500,6 +500,7 @@ const struct spi_device_id spi_nor_ids[] = { | |||
500 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 500 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
501 | { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | 501 | { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, |
502 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, | 502 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, |
503 | { "s25fl128s", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, | ||
503 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 504 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
504 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 505 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
505 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, | 506 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, |