0020-mtd-spi-nor-fix-support-of-Winbond-memories.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. From 96b232d03a0c4462eacf879ed80b0cfd235e65c4 Mon Sep 17 00:00:00 2001
  2. From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
  3. Date: Fri, 8 Jan 2016 17:02:17 +0100
  4. Subject: [PATCH 20/33] mtd: spi-nor: fix support of Winbond memories
  5. This patch fixes the support of Winbond memories. Indeed, before
  6. performing any Quad SPI command, the Quad Enable (QE) non-volatile bit
  7. MUST be set in the Status Register 2.
  8. According to the w25q16fw datasheet from Winbond:
  9. "When QE=1, the /WP pin becomes IO2 and /HOLD pin becomes IO3."
  10. Quad SPI instructions requires the bidirectional IO2 and IO3 pins.
  11. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
  12. ---
  13. drivers/mtd/spi-nor/spi-nor.c | 100 ++++++++++++++++++++++++++++++++++++++++++
  14. include/linux/mtd/spi-nor.h | 6 +++
  15. 2 files changed, 106 insertions(+)
  16. diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
  17. index 1b1f5a6..aa7d26d 100644
  18. --- a/drivers/mtd/spi-nor/spi-nor.c
  19. +++ b/drivers/mtd/spi-nor/spi-nor.c
  20. @@ -1166,6 +1166,40 @@ static int spansion_quad_enable(struct spi_nor *nor)
  21. return 0;
  22. }
  23. +static int winbond_quad_enable(struct spi_nor *nor)
  24. +{
  25. + int ret;
  26. + u8 sr2;
  27. +
  28. + ret = nor->read_reg(nor, SPINOR_OP_RDSR2_WINB, &sr2, 1);
  29. + if (ret < 0)
  30. + return ret;
  31. +
  32. + if (likely(sr2 & SR2_QUAD_EN_WINB))
  33. + return 0;
  34. + dev_warn(nor->dev, "Winbond Quad mode disabled, enable it\n");
  35. +
  36. + write_enable(nor);
  37. +
  38. + sr2 |= SR2_QUAD_EN_WINB;
  39. + ret = nor->write_reg(nor, SPINOR_OP_WRSR2_WINB, &sr2, 1);
  40. + if (ret < 0)
  41. + return ret;
  42. +
  43. + if (spi_nor_wait_till_ready(nor))
  44. + return -EIO;
  45. +
  46. + ret = nor->read_reg(nor, SPINOR_OP_RDSR2_WINB, &sr2, 1);
  47. + if (ret < 0)
  48. + return ret;
  49. + if (!(sr2 & SR2_QUAD_EN_WINB)) {
  50. + dev_err(nor->dev, "Winbond Quad bit not set\n");
  51. + return -EINVAL;
  52. + }
  53. +
  54. + return 0;
  55. +}
  56. +
  57. static int macronix_set_quad_mode(struct spi_nor *nor)
  58. {
  59. int status;
  60. @@ -1226,6 +1260,63 @@ static int macronix_set_single_mode(struct spi_nor *nor)
  61. return 0;
  62. }
  63. +static int winbond_set_quad_mode(struct spi_nor *nor)
  64. +{
  65. + int status;
  66. +
  67. + /* Check whether the QPI mode is enabled. */
  68. + if (nor->read_proto == SNOR_PROTO_4_4_4) {
  69. + /* Since the QPI mode is enabled, the Quad Enabled (QE)
  70. + * non-volatile bit is already set.
  71. + * If the Fast Read 1-4-4 (0xeb) were used, we should
  72. + * take care about the value M7-M0 written during
  73. + * dummy/mode cycles to avoid entering the continuous
  74. + * read mode by mistake.
  75. + * Also the Fast Read 1-1-4 (0x6b) op code is not
  76. + * supported in QPI mode.
  77. + * Hence the Fast Read 1-1-1 (0x0b) op code is chosen.
  78. + */
  79. + nor->read_opcode = SPINOR_OP_READ_FAST;
  80. + return 0;
  81. + }
  82. +
  83. + /*
  84. + * The QPI mode is disabled but we still need to set the QE bit:
  85. + * when QE=1, the /WP pin becomes IO2 and /HOLD pin becomes IO3.
  86. + * If the Fast Read 1-4-4 (0xeb) were used, we should take care
  87. + * about the value M7-M0 written during dummy/mode cycles to
  88. + * avoid entering the continuous read mode by mistake.
  89. + * Hence the Fast Read 1-1-4 (0x6b) op code is preferred.
  90. + */
  91. + status = winbond_quad_enable(nor);
  92. + if (status) {
  93. + dev_err(nor->dev, "Winbond quad-read nor enabled\n");
  94. + return status;
  95. + }
  96. + nor->read_proto = SNOR_PROTO_1_1_4;
  97. + nor->read_opcode = SPINOR_OP_READ_1_1_4;
  98. + return 0;
  99. +}
  100. +
  101. +/*
  102. + * For both Winbond Dual and Single modes, we don't care about the value of
  103. + * the Quad Enabled (QE) bit since the memory still replies to Dual or Single
  104. + * SPI commands.
  105. + */
  106. +
  107. +static int winbond_set_dual_mode(struct spi_nor *nor)
  108. +{
  109. + nor->read_proto = SNOR_PROTO_1_1_2;
  110. + nor->read_opcode = SPINOR_OP_READ_1_1_2;
  111. + return 0;
  112. +}
  113. +
  114. +static int winbond_set_single_mode(struct spi_nor *nor)
  115. +{
  116. + nor->read_proto = SNOR_PROTO_1_1_1;
  117. + return 0;
  118. +}
  119. +
  120. static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
  121. {
  122. int status;
  123. @@ -1234,6 +1325,9 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
  124. case SNOR_MFR_MACRONIX:
  125. return macronix_set_quad_mode(nor);
  126. + case SNOR_MFR_WINBOND:
  127. + return winbond_set_quad_mode(nor);
  128. +
  129. case SNOR_MFR_MICRON:
  130. /* Check whether Micron Quad mode is enabled. */
  131. if (nor->read_proto != SNOR_PROTO_4_4_4)
  132. @@ -1263,6 +1357,9 @@ static int set_dual_mode(struct spi_nor *nor, const struct flash_info *info)
  133. case SNOR_MFR_MACRONIX:
  134. return macronix_set_dual_mode(nor);
  135. + case SNOR_MFR_WINBOND:
  136. + return winbond_set_dual_mode(nor);
  137. +
  138. case SNOR_MFR_MICRON:
  139. /* Check whether Micron Dual mode is enabled. */
  140. if (nor->read_proto != SNOR_PROTO_2_2_2)
  141. @@ -1284,6 +1381,9 @@ static int set_single_mode(struct spi_nor *nor, const struct flash_info *info)
  142. case SNOR_MFR_MACRONIX:
  143. return macronix_set_single_mode(nor);
  144. + case SNOR_MFR_WINBOND:
  145. + return winbond_set_single_mode(nor);
  146. +
  147. default:
  148. nor->read_proto = SNOR_PROTO_1_1_1;
  149. break;
  150. diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
  151. index 89e3228..46343f5 100644
  152. --- a/include/linux/mtd/spi-nor.h
  153. +++ b/include/linux/mtd/spi-nor.h
  154. @@ -75,6 +75,12 @@
  155. #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
  156. #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
  157. +/* Used for Winbond flashes only. */
  158. +#define SPINOR_OP_RDSR2_WINB 0x35 /* Read status register 2 */
  159. +#define SPINOR_OP_WRSR2_WINB 0x31 /* Write status register 2 */
  160. +
  161. +#define SR2_QUAD_EN_WINB BIT(1) /* Quad Enable bit */
  162. +
  163. /* Used for Spansion flashes only. */
  164. #define SPINOR_OP_BRWR 0x17 /* Bank register write */
  165. --
  166. 2.8.1