1105-mtd-spi-nor-add-DDR-quad-read-support.patch 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. From 924f021c0344554a4b61746e5c4dcfc91d618ce2 Mon Sep 17 00:00:00 2001
  2. From: Yunhui Cui <yunhui.cui@nxp.com>
  3. Date: Thu, 18 Feb 2016 16:41:53 +0800
  4. Subject: [PATCH 105/113] mtd: spi-nor: add DDR quad read support
  5. This patch adds the DDR quad read support by the following:
  6. [1] add SPI_NOR_DDR_QUAD read mode.
  7. [2] add DDR Quad read opcodes:
  8. SPINOR_OP_READ_1_4_4_D / SPINOR_OP_READ4_1_4_4_D
  9. [3] add set_ddr_quad_mode() to initialize for the DDR quad read.
  10. Currently it only works for Spansion NOR.
  11. [4] set dummy with 6 for Spansion family
  12. Test this patch for Spansion s25fl128s NOR flash.
  13. Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
  14. ---
  15. drivers/mtd/spi-nor/spi-nor.c | 53 ++++++++++++++++++++++++++++++++++++-----
  16. include/linux/mtd/spi-nor.h | 8 +++++--
  17. 2 files changed, 53 insertions(+), 8 deletions(-)
  18. --- a/drivers/mtd/spi-nor/spi-nor.c
  19. +++ b/drivers/mtd/spi-nor/spi-nor.c
  20. @@ -73,7 +73,8 @@ struct flash_info {
  21. #define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */
  22. #define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */
  23. #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */
  24. -#define USE_FSR 0x80 /* use flag status register */
  25. +#define SPI_NOR_DDR_QUAD_READ 0x80 /* Flash supports DDR Quad Read */
  26. +#define USE_FSR 0x100 /* use flag status register */
  27. #define SPI_NOR_HAS_LOCK 0x100 /* Flash supports lock/unlock via SR */
  28. };
  29. @@ -145,13 +146,17 @@ static int read_cr(struct spi_nor *nor)
  30. * It can be used to support more commands with
  31. * different dummy cycle requirements.
  32. */
  33. -static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
  34. +static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor,
  35. + const struct flash_info *info)
  36. {
  37. switch (nor->flash_read) {
  38. case SPI_NOR_FAST:
  39. case SPI_NOR_DUAL:
  40. case SPI_NOR_QUAD:
  41. return 8;
  42. + case SPI_NOR_DDR_QUAD:
  43. + if (JEDEC_MFR(info) == SNOR_MFR_SPANSION)
  44. + return 6;
  45. case SPI_NOR_NORMAL:
  46. return 0;
  47. }
  48. @@ -805,7 +810,8 @@ static const struct flash_info spi_nor_i
  49. { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
  50. { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
  51. { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
  52. - { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
  53. + { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ
  54. + | SPI_NOR_DDR_QUAD_READ) },
  55. { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
  56. { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
  57. { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
  58. @@ -1201,6 +1207,23 @@ static int spansion_quad_enable(struct s
  59. return 0;
  60. }
  61. +static int set_ddr_quad_mode(struct spi_nor *nor, const struct flash_info *info)
  62. +{
  63. + int status;
  64. +
  65. + switch (JEDEC_MFR(info)) {
  66. + case SNOR_MFR_SPANSION:
  67. + status = spansion_quad_enable(nor);
  68. + if (status) {
  69. + dev_err(nor->dev, "Spansion DDR quad-read not enabled\n");
  70. + return status;
  71. + }
  72. + return status;
  73. + default:
  74. + return -EINVAL;
  75. + }
  76. +}
  77. +
  78. static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
  79. {
  80. int status;
  81. @@ -1391,8 +1414,15 @@ int spi_nor_scan(struct spi_nor *nor, co
  82. if (info->flags & SPI_NOR_NO_FR)
  83. nor->flash_read = SPI_NOR_NORMAL;
  84. - /* Quad/Dual-read mode takes precedence over fast/normal */
  85. - if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
  86. + /* DDR Quad/Quad/Dual-read mode takes precedence over fast/normal */
  87. + if (mode == SPI_NOR_DDR_QUAD && info->flags & SPI_NOR_DDR_QUAD_READ) {
  88. + ret = set_ddr_quad_mode(nor, info);
  89. + if (ret) {
  90. + dev_err(dev, "DDR quad mode not supported\n");
  91. + return ret;
  92. + }
  93. + nor->flash_read = SPI_NOR_DDR_QUAD;
  94. + } else if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
  95. ret = set_quad_mode(nor, info);
  96. if (ret) {
  97. dev_err(dev, "quad mode not supported\n");
  98. @@ -1405,6 +1435,14 @@ int spi_nor_scan(struct spi_nor *nor, co
  99. /* Default commands */
  100. switch (nor->flash_read) {
  101. + case SPI_NOR_DDR_QUAD:
  102. + if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) { /* Spansion */
  103. + nor->read_opcode = SPINOR_OP_READ_1_4_4_D;
  104. + } else {
  105. + dev_err(dev, "DDR Quad Read is not supported.\n");
  106. + return -EINVAL;
  107. + }
  108. + break;
  109. case SPI_NOR_QUAD:
  110. nor->read_opcode = SPINOR_OP_READ_1_1_4;
  111. break;
  112. @@ -1432,6 +1470,9 @@ int spi_nor_scan(struct spi_nor *nor, co
  113. if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
  114. /* Dedicated 4-byte command set */
  115. switch (nor->flash_read) {
  116. + case SPI_NOR_DDR_QUAD:
  117. + nor->read_opcode = SPINOR_OP_READ4_1_4_4_D;
  118. + break;
  119. case SPI_NOR_QUAD:
  120. nor->read_opcode = SPINOR_OP_READ4_1_1_4;
  121. break;
  122. @@ -1461,7 +1502,7 @@ int spi_nor_scan(struct spi_nor *nor, co
  123. return -EINVAL;
  124. }
  125. - nor->read_dummy = spi_nor_read_dummy_cycles(nor);
  126. + nor->read_dummy = spi_nor_read_dummy_cycles(nor, info);
  127. dev_info(dev, "%s (%lld Kbytes)\n", info->name,
  128. (long long)mtd->size >> 10);
  129. --- a/include/linux/mtd/spi-nor.h
  130. +++ b/include/linux/mtd/spi-nor.h
  131. @@ -30,10 +30,11 @@
  132. /*
  133. * Note on opcode nomenclature: some opcodes have a format like
  134. - * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
  135. + * SPINOR_OP_FUNCTION{4,}_x_y_z{_D}. The numbers x, y,and z stand for the number
  136. * of I/O lines used for the opcode, address, and data (respectively). The
  137. * FUNCTION has an optional suffix of '4', to represent an opcode which
  138. - * requires a 4-byte (32-bit) address.
  139. + * requires a 4-byte (32-bit) address. The suffix of 'D' stands for the
  140. + * DDR mode.
  141. */
  142. /* Flash opcodes. */
  143. @@ -44,6 +45,7 @@
  144. #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
  145. #define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
  146. #define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
  147. +#define SPINOR_OP_READ_1_4_4_D 0xed /* Read data bytes (DDR Quad SPI) */
  148. #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
  149. #define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
  150. #define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
  151. @@ -59,6 +61,7 @@
  152. #define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
  153. #define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
  154. #define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
  155. +#define SPINOR_OP_READ4_1_4_4_D 0xee /* Read data bytes (DDR Quad SPI) */
  156. #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
  157. #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
  158. @@ -107,6 +110,7 @@ enum read_mode {
  159. SPI_NOR_FAST,
  160. SPI_NOR_DUAL,
  161. SPI_NOR_QUAD,
  162. + SPI_NOR_DDR_QUAD,
  163. };
  164. #define SPI_NOR_MAX_CMD_SIZE 8