0026-mtd-spi-nor-configure-the-number-of-dummy-clock-cycl.patch 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. From 7b411f38f7882fdf9f5607bc75deb940a7aaa480 Mon Sep 17 00:00:00 2001
  2. From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
  3. Date: Fri, 8 Jan 2016 17:10:53 +0100
  4. Subject: [PATCH 26/33] mtd: spi-nor: configure the number of dummy clock
  5. cycles on Spansion memories
  6. On Spansion memories, the number of dummy clock cycles to be used during
  7. Fast Read commands is configured through the 2bit latency code (LC). These
  8. bits are non-volatile inside the Configuration Register.
  9. To avoid breaking the configuration expected at reset by some bootloaders,
  10. we'd rather read the latency code and set the nor->read_dummy value
  11. accordingly than update those non-volatile bits.
  12. Since the Quad Enable non-volatile bit can be read at the same time from
  13. the Control Register, we now check its value to avoid some calls of the
  14. spansion_quad_enable() function when they are not needed.
  15. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
  16. ---
  17. drivers/mtd/spi-nor/spi-nor.c | 159 ++++++++++++++++++++++++++++++++++++------
  18. 1 file changed, 137 insertions(+), 22 deletions(-)
  19. diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
  20. index 55a1d74..654209a 100644
  21. --- a/drivers/mtd/spi-nor/spi-nor.c
  22. +++ b/drivers/mtd/spi-nor/spi-nor.c
  23. @@ -1687,47 +1687,162 @@ static int micron_set_single_mode(struct spi_nor *nor)
  24. return micron_set_dummy_cycles(nor, read_dummy);
  25. }
  26. -static int spansion_set_quad_mode(struct spi_nor *nor)
  27. +static inline int spansion_get_config(struct spi_nor *nor,
  28. + bool *quad_enabled,
  29. + u8 *latency_code)
  30. {
  31. - int status;
  32. + int cr;
  33. - status = spansion_quad_enable(nor);
  34. - if (status) {
  35. - dev_err(nor->dev, "Spansion quad-read not enabled\n");
  36. + cr = read_cr(nor);
  37. + if (cr < 0) {
  38. + dev_err(nor->dev,
  39. + "error while reading the configuration register\n");
  40. + return cr;
  41. + }
  42. +
  43. + if (quad_enabled)
  44. + *quad_enabled = !!(cr & CR_QUAD_EN_SPAN);
  45. +
  46. + if (latency_code)
  47. + *latency_code = (u8)((cr & GENMASK(7, 6)) >> 6);
  48. +
  49. + return 0;
  50. +}
  51. +
  52. +static int spansion_set_dummy_cycles(struct spi_nor *nor, u8 latency_code)
  53. +{
  54. + /* SDR dummy cycles */
  55. + switch (nor->read_opcode) {
  56. + case SPINOR_OP_READ:
  57. + case SPINOR_OP_READ4:
  58. + nor->read_dummy = 0;
  59. + break;
  60. +
  61. + case SPINOR_OP_READ_FAST:
  62. + case SPINOR_OP_READ_1_1_2:
  63. + case SPINOR_OP_READ_1_1_4:
  64. + case SPINOR_OP_READ4_FAST:
  65. + case SPINOR_OP_READ4_1_1_2:
  66. + case SPINOR_OP_READ4_1_1_4:
  67. + nor->read_dummy = (latency_code == 3) ? 0 : 8;
  68. + break;
  69. +
  70. + case SPINOR_OP_READ_1_2_2:
  71. + case SPINOR_OP_READ4_1_2_2:
  72. + switch (latency_code) {
  73. + default:
  74. + case 0:
  75. + case 3:
  76. + nor->read_dummy = 4;
  77. + break;
  78. + case 1:
  79. + nor->read_dummy = 5;
  80. + break;
  81. + case 2:
  82. + nor->read_dummy = 6;
  83. + break;
  84. + }
  85. + break;
  86. +
  87. +
  88. + case SPINOR_OP_READ_1_4_4:
  89. + case SPINOR_OP_READ4_1_4_4:
  90. + switch (latency_code) {
  91. + default:
  92. + case 0:
  93. + case 1:
  94. + nor->read_dummy = 4;
  95. + break;
  96. + case 2:
  97. + nor->read_dummy = 5;
  98. + break;
  99. + case 3:
  100. + nor->read_dummy = 1;
  101. + break;
  102. + }
  103. +
  104. + default:
  105. return -EINVAL;
  106. }
  107. +
  108. + return 0;
  109. +}
  110. +
  111. +static int spansion_set_quad_mode(struct spi_nor *nor)
  112. +{
  113. + bool quad_enabled;
  114. + u8 latency_code;
  115. + int ret;
  116. +
  117. + /*
  118. + * The QUAD bit of Configuration Register must be set (CR Bit1=1) for
  119. + * using any Quad SPI command.
  120. + */
  121. + ret = spansion_get_config(nor, &quad_enabled, &latency_code);
  122. + if (ret)
  123. + return ret;
  124. +
  125. + /* The Quad mode should be enabled ... */
  126. + if (!quad_enabled) {
  127. + /* ... if not try to enable it. */
  128. + dev_warn(nor->dev, "Spansion Quad mode disabled, enable it\n");
  129. + ret = spansion_quad_enable(nor);
  130. + if (ret)
  131. + return ret;
  132. + }
  133. +
  134. + /*
  135. + * Don't use the Fast Read Quad I/O (0xeb / 0xec) commands as their
  136. + * number of dummy cycles can not be set to a multiple of 8: some SPI
  137. + * controllers, especially those relying on the m25p80 driver, expect
  138. + * the number of dummy cycles to be a multiple of 8.
  139. + * Also when using a Fast Read Quad I/O command, the memory checks the
  140. + * value of the first mode/dummy cycles to decice whether it enters or
  141. + * leaves the Countinuous Read mode. We should never enter the
  142. + * Countinuous Read mode as the spi-nor framework doesn't support it.
  143. + * For all these reason, we'd rather use the Fast Read Quad Output
  144. + * 1-1-4 (0x6b / 0x6c) commands instead.
  145. + */
  146. nor->read_proto = SNOR_PROTO_1_1_4;
  147. nor->read_opcode = SPINOR_OP_READ_1_1_4;
  148. - nor->read_dummy = 8;
  149. - return 0;
  150. + return spansion_set_dummy_cycles(nor, latency_code);
  151. }
  152. static int spansion_set_dual_mode(struct spi_nor *nor)
  153. {
  154. + u8 latency_code;
  155. + int ret;
  156. +
  157. + /* We don't care about the quad mode status */
  158. + ret = spansion_get_config(nor, NULL, &latency_code);
  159. + if (ret)
  160. + return ret;
  161. +
  162. + /*
  163. + * Don't use the Fast Read Dual I/O (0xbb / 0xbc) commands as their
  164. + * number of dummy cycles can not bet set to a multiple of 8: some SPI
  165. + * controllers, especially those relying on the m25p80 driver, expect
  166. + * the number of dummy cycles to be a multiple of 8.
  167. + * For this reason, w'd rather use the Fast Read Dual Output 1-1-2
  168. + * (0x3b / 0x3c) commands instead.
  169. + */
  170. nor->read_proto = SNOR_PROTO_1_1_2;
  171. nor->read_opcode = SPINOR_OP_READ_1_1_2;
  172. - nor->read_dummy = 8;
  173. - return 0;
  174. + return spansion_set_dummy_cycles(nor, latency_code);
  175. }
  176. static int spansion_set_single_mode(struct spi_nor *nor)
  177. {
  178. - u8 read_dummy;
  179. -
  180. - switch (nor->read_opcode) {
  181. - case SPINOR_OP_READ:
  182. - case SPINOR_OP_READ4:
  183. - read_dummy = 0;
  184. - break;
  185. + u8 latency_code;
  186. + int ret;
  187. - default:
  188. - read_dummy = 8;
  189. - break;
  190. - }
  191. + /* We don't care about the quad mode status */
  192. + ret = spansion_get_config(nor, NULL, &latency_code);
  193. + if (ret)
  194. + return ret;
  195. nor->read_proto = SNOR_PROTO_1_1_1;
  196. - nor->read_dummy = read_dummy;
  197. - return 0;
  198. + return spansion_set_dummy_cycles(nor, latency_code);
  199. }
  200. static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
  201. --
  202. 2.8.1