0018-mtd-spi-nor-select-op-codes-and-SPI-NOR-protocols-by.patch 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. From a27dc343ea2de9283ca057fbcafa12a279a19b7b Mon Sep 17 00:00:00 2001
  2. From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
  3. Date: Fri, 8 Jan 2016 17:02:15 +0100
  4. Subject: [PATCH 18/33] mtd: spi-nor: select op codes and SPI NOR protocols by
  5. manufacturer
  6. This is a transitional patch to prepare the split by Manufacturer of the
  7. support of Single/Dual/Quad SPI modes.
  8. Indeed every QSPI NOR manufacturer (Spansion, Micron, Macronix, Winbond)
  9. supports Dual or Quad SPI modes on its way. Especially the Fast Read op
  10. code and the SPI NOR protocols to use are not quite the same depending on
  11. the manufacturer.
  12. For instance Quad commands can use either the SPI 1-1-4, 1-4-4 or 4-4-4
  13. protocol.
  14. This is why this patch will be completed by fixes for each manufacturer.
  15. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
  16. ---
  17. drivers/mtd/spi-nor/spi-nor.c | 110 ++++++++++++++++++++++++++++++++----------
  18. include/linux/mtd/spi-nor.h | 12 +++--
  19. 2 files changed, 92 insertions(+), 30 deletions(-)
  20. diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
  21. index 9ad2d40..889af12 100644
  22. --- a/drivers/mtd/spi-nor/spi-nor.c
  23. +++ b/drivers/mtd/spi-nor/spi-nor.c
  24. @@ -1172,17 +1172,61 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
  25. dev_err(nor->dev, "Macronix quad-read not enabled\n");
  26. return -EINVAL;
  27. }
  28. - return status;
  29. + /* Check whether Macronix QPI mode is enabled. */
  30. + if (nor->read_proto != SNOR_PROTO_4_4_4)
  31. + nor->read_proto = SNOR_PROTO_1_1_4;
  32. + break;
  33. +
  34. case SNOR_MFR_MICRON:
  35. - return 0;
  36. - default:
  37. + /* Check whether Micron Quad mode is enabled. */
  38. + if (nor->read_proto != SNOR_PROTO_4_4_4)
  39. + nor->read_proto = SNOR_PROTO_1_1_4;
  40. + break;
  41. +
  42. + case SNOR_MFR_SPANSION:
  43. status = spansion_quad_enable(nor);
  44. if (status) {
  45. dev_err(nor->dev, "Spansion quad-read not enabled\n");
  46. return -EINVAL;
  47. }
  48. - return status;
  49. + nor->read_proto = SNOR_PROTO_1_1_4;
  50. + break;
  51. +
  52. + default:
  53. + return -EINVAL;
  54. }
  55. +
  56. + nor->read_opcode = SPINOR_OP_READ_1_1_4;
  57. + return 0;
  58. +}
  59. +
  60. +static int set_dual_mode(struct spi_nor *nor, const struct flash_info *info)
  61. +{
  62. + switch (JEDEC_MFR(info)) {
  63. + case SNOR_MFR_MICRON:
  64. + /* Check whether Micron Dual mode is enabled. */
  65. + if (nor->read_proto != SNOR_PROTO_2_2_2)
  66. + nor->read_proto = SNOR_PROTO_1_1_2;
  67. + break;
  68. +
  69. + default:
  70. + nor->read_proto = SNOR_PROTO_1_1_2;
  71. + break;
  72. + }
  73. +
  74. + nor->read_opcode = SPINOR_OP_READ_1_1_2;
  75. + return 0;
  76. +}
  77. +
  78. +static int set_single_mode(struct spi_nor *nor, const struct flash_info *info)
  79. +{
  80. + switch (JEDEC_MFR(info)) {
  81. + default:
  82. + nor->read_proto = SNOR_PROTO_1_1_1;
  83. + break;
  84. + }
  85. +
  86. + return 0;
  87. }
  88. static int spi_nor_check(struct spi_nor *nor)
  89. @@ -1330,7 +1374,30 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
  90. if (info->flags & SPI_NOR_NO_FR)
  91. nor->flash_read = SPI_NOR_NORMAL;
  92. - /* Quad/Dual-read mode takes precedence over fast/normal */
  93. + /* Default commands */
  94. + if (nor->flash_read == SPI_NOR_NORMAL)
  95. + nor->read_opcode = SPINOR_OP_READ;
  96. + else
  97. + nor->read_opcode = SPINOR_OP_READ_FAST;
  98. +
  99. + nor->program_opcode = SPINOR_OP_PP;
  100. +
  101. + /*
  102. + * Quad/Dual-read mode takes precedence over fast/normal.
  103. + *
  104. + * Manufacturer specific modes are discovered when reading the JEDEC ID
  105. + * and are reported by the nor->read_proto value:
  106. + * - SNOR_PROTO_4_4_4 is either:
  107. + * + Micron Quad mode enabled
  108. + * + Macronix/Winbond QPI mode enabled
  109. + * - SNOR_PROTO_2_2_2 is either:
  110. + * + Micron Dual mode enabled
  111. + *
  112. + * The opcodes and the protocols are updated depending on the
  113. + * manufacturer.
  114. + * The read opcode and protocol should be updated by the relevant
  115. + * function when entering Quad or Dual mode.
  116. + */
  117. if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
  118. ret = set_quad_mode(nor, info);
  119. if (ret) {
  120. @@ -1339,30 +1406,21 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
  121. }
  122. nor->flash_read = SPI_NOR_QUAD;
  123. } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) {
  124. + ret = set_dual_mode(nor, info);
  125. + if (ret) {
  126. + dev_err(dev, "dual mode not supported\n");
  127. + return ret;
  128. + }
  129. nor->flash_read = SPI_NOR_DUAL;
  130. + } else if (info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) {
  131. + /* We may need to leave a Quad or Dual mode */
  132. + ret = set_single_mode(nor, info);
  133. + if (ret) {
  134. + dev_err(dev, "failed to switch back to single mode\n");
  135. + return ret;
  136. + }
  137. }
  138. - /* Default commands */
  139. - switch (nor->flash_read) {
  140. - case SPI_NOR_QUAD:
  141. - nor->read_opcode = SPINOR_OP_READ_1_1_4;
  142. - break;
  143. - case SPI_NOR_DUAL:
  144. - nor->read_opcode = SPINOR_OP_READ_1_1_2;
  145. - break;
  146. - case SPI_NOR_FAST:
  147. - nor->read_opcode = SPINOR_OP_READ_FAST;
  148. - break;
  149. - case SPI_NOR_NORMAL:
  150. - nor->read_opcode = SPINOR_OP_READ;
  151. - break;
  152. - default:
  153. - dev_err(dev, "No Read opcode defined\n");
  154. - return -EINVAL;
  155. - }
  156. -
  157. - nor->program_opcode = SPINOR_OP_PP;
  158. -
  159. if (info->addr_width)
  160. nor->addr_width = info->addr_width;
  161. else if (mtd->size > 0x1000000) {
  162. diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
  163. index 53932c8..89e3228 100644
  164. --- a/include/linux/mtd/spi-nor.h
  165. +++ b/include/linux/mtd/spi-nor.h
  166. @@ -42,8 +42,10 @@
  167. #define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
  168. #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
  169. #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
  170. -#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
  171. -#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
  172. +#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */
  173. +#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */
  174. +#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */
  175. +#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */
  176. #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
  177. #define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
  178. #define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
  179. @@ -57,8 +59,10 @@
  180. /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
  181. #define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
  182. #define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
  183. -#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
  184. -#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
  185. +#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual Output SPI) */
  186. +#define SPINOR_OP_READ4_1_2_2 0xbc /* Read data bytes (Dual I/O SPI) */
  187. +#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad Output SPI) */
  188. +#define SPINOR_OP_READ4_1_4_4 0xec /* Read data bytes (Quad I/O SPI) */
  189. #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
  190. #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
  191. --
  192. 2.8.1