2
0

102-spi-img-spfi-Implement-dual-and-quad-mode.patch 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. From cd2a6af51553d38072cd31699b58d16ca6176ef5 Mon Sep 17 00:00:00 2001
  2. From: Ionela Voinescu <[email protected]>
  3. Date: Thu, 2 Feb 2017 16:46:14 +0000
  4. Subject: spi: img-spfi: Implement dual and quad mode
  5. For dual and quad modes to work the SPFI controller needs
  6. to have information about command/address/dummy bytes in the
  7. transaction register. This information is not relevant for
  8. single mode, and therefore it can have any value in the
  9. allowed range. Therefore, for any read or write transfers of less
  10. than 8 bytes (cmd = 1 byte, addr up to 7 bytes), SPFI will be
  11. configured, but not enabled (unless it is the last transfer in
  12. the queue). The transfer will be enabled by the subsequent tranfer.
  13. A pending transfer is determined by the content of the transaction
  14. register: if command part is set and tsize is not.
  15. This way we ensure that for dual and quad transactions
  16. the command request size will apear in the command/address part
  17. of the transaction register, while the data size will be in
  18. tsize, all data being sent/received in the same transaction (as
  19. set up in the transaction register).
  20. Signed-off-by: Ionela Voinescu <[email protected]>
  21. Signed-off-by: Ezequiel Garcia <[email protected]>
  22. ---
  23. drivers/spi/spi-img-spfi.c | 96 ++++++++++++++++++++++++++++++++++++++++------
  24. 1 file changed, 85 insertions(+), 11 deletions(-)
  25. --- a/drivers/spi/spi-img-spfi.c
  26. +++ b/drivers/spi/spi-img-spfi.c
  27. @@ -36,7 +36,8 @@
  28. #define SPFI_CONTROL_SOFT_RESET BIT(11)
  29. #define SPFI_CONTROL_SEND_DMA BIT(10)
  30. #define SPFI_CONTROL_GET_DMA BIT(9)
  31. -#define SPFI_CONTROL_SE BIT(8)
  32. +#define SPFI_CONTROL_SE BIT(8)
  33. +#define SPFI_CONTROL_TX_RX BIT(1)
  34. #define SPFI_CONTROL_TMODE_SHIFT 5
  35. #define SPFI_CONTROL_TMODE_MASK 0x7
  36. #define SPFI_CONTROL_TMODE_SINGLE 0
  37. @@ -47,6 +48,10 @@
  38. #define SPFI_TRANSACTION 0x18
  39. #define SPFI_TRANSACTION_TSIZE_SHIFT 16
  40. #define SPFI_TRANSACTION_TSIZE_MASK 0xffff
  41. +#define SPFI_TRANSACTION_CMD_SHIFT 13
  42. +#define SPFI_TRANSACTION_CMD_MASK 0x7
  43. +#define SPFI_TRANSACTION_ADDR_SHIFT 10
  44. +#define SPFI_TRANSACTION_ADDR_MASK 0x7
  45. #define SPFI_PORT_STATE 0x1c
  46. #define SPFI_PORT_STATE_DEV_SEL_SHIFT 20
  47. @@ -83,6 +88,7 @@
  48. */
  49. #define SPFI_32BIT_FIFO_SIZE 64
  50. #define SPFI_8BIT_FIFO_SIZE 16
  51. +#define SPFI_DATA_REQUEST_MAX_SIZE 8
  52. struct img_spfi {
  53. struct device *dev;
  54. @@ -99,6 +105,8 @@ struct img_spfi {
  55. struct dma_chan *tx_ch;
  56. bool tx_dma_busy;
  57. bool rx_dma_busy;
  58. +
  59. + bool complete;
  60. };
  61. static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
  62. @@ -115,9 +123,11 @@ static inline void spfi_start(struct img
  63. {
  64. u32 val;
  65. - val = spfi_readl(spfi, SPFI_CONTROL);
  66. - val |= SPFI_CONTROL_SPFI_EN;
  67. - spfi_writel(spfi, val, SPFI_CONTROL);
  68. + if (spfi->complete) {
  69. + val = spfi_readl(spfi, SPFI_CONTROL);
  70. + val |= SPFI_CONTROL_SPFI_EN;
  71. + spfi_writel(spfi, val, SPFI_CONTROL);
  72. + }
  73. }
  74. static inline void spfi_reset(struct img_spfi *spfi)
  75. @@ -130,12 +140,21 @@ static int spfi_wait_all_done(struct img
  76. {
  77. unsigned long timeout = jiffies + msecs_to_jiffies(50);
  78. + if (!(spfi->complete))
  79. + return 0;
  80. +
  81. while (time_before(jiffies, timeout)) {
  82. u32 status = spfi_readl(spfi, SPFI_INTERRUPT_STATUS);
  83. if (status & SPFI_INTERRUPT_ALLDONETRIG) {
  84. spfi_writel(spfi, SPFI_INTERRUPT_ALLDONETRIG,
  85. SPFI_INTERRUPT_CLEAR);
  86. + /*
  87. + * Disable SPFI for it not to interfere with
  88. + * pending transactions
  89. + */
  90. + spfi_writel(spfi, spfi_readl(spfi, SPFI_CONTROL)
  91. + & ~SPFI_CONTROL_SPFI_EN, SPFI_CONTROL);
  92. return 0;
  93. }
  94. cpu_relax();
  95. @@ -441,9 +460,32 @@ static void img_spfi_config(struct spi_m
  96. struct spi_transfer *xfer)
  97. {
  98. struct img_spfi *spfi = spi_master_get_devdata(spi->master);
  99. - u32 val, div;
  100. + u32 val, div, transact;
  101. + bool is_pending;
  102. /*
  103. + * For read or write transfers of less than 8 bytes (cmd = 1 byte,
  104. + * addr up to 7 bytes), SPFI will be configured, but not enabled
  105. + * (unless it is the last transfer in the queue).The transfer will
  106. + * be enabled by the subsequent transfer.
  107. + * A pending transfer is determined by the content of the
  108. + * transaction register: if command part is set and tsize
  109. + * is not
  110. + */
  111. + transact = spfi_readl(spfi, SPFI_TRANSACTION);
  112. + is_pending = ((transact >> SPFI_TRANSACTION_CMD_SHIFT) &
  113. + SPFI_TRANSACTION_CMD_MASK) &&
  114. + (!((transact >> SPFI_TRANSACTION_TSIZE_SHIFT) &
  115. + SPFI_TRANSACTION_TSIZE_MASK));
  116. +
  117. + /* If there are no pending transactions it's OK to soft reset */
  118. + if (!is_pending) {
  119. + /* Start the transaction from a known (reset) state */
  120. + spfi_reset(spfi);
  121. + }
  122. +
  123. + /*
  124. + * Before anything else, set up parameters.
  125. * output = spfi_clk * (BITCLK / 512), where BITCLK must be a
  126. * power of 2 up to 128
  127. */
  128. @@ -456,20 +498,52 @@ static void img_spfi_config(struct spi_m
  129. val |= div << SPFI_DEVICE_PARAMETER_BITCLK_SHIFT;
  130. spfi_writel(spfi, val, SPFI_DEVICE_PARAMETER(spi->chip_select));
  131. - spfi_writel(spfi, xfer->len << SPFI_TRANSACTION_TSIZE_SHIFT,
  132. - SPFI_TRANSACTION);
  133. + if (!list_is_last(&xfer->transfer_list, &master->cur_msg->transfers) &&
  134. + /*
  135. + * For duplex mode (both the tx and rx buffers are !NULL) the
  136. + * CMD, ADDR, and DUMMY byte parts of the transaction register
  137. + * should always be 0 and therefore the pending transfer
  138. + * technique cannot be used.
  139. + */
  140. + (xfer->tx_buf) && (!xfer->rx_buf) &&
  141. + (xfer->len <= SPFI_DATA_REQUEST_MAX_SIZE) && !is_pending) {
  142. + transact = (1 & SPFI_TRANSACTION_CMD_MASK) <<
  143. + SPFI_TRANSACTION_CMD_SHIFT;
  144. + transact |= ((xfer->len - 1) & SPFI_TRANSACTION_ADDR_MASK) <<
  145. + SPFI_TRANSACTION_ADDR_SHIFT;
  146. + spfi->complete = false;
  147. + } else {
  148. + spfi->complete = true;
  149. + if (is_pending) {
  150. + /* Keep setup from pending transfer */
  151. + transact |= ((xfer->len & SPFI_TRANSACTION_TSIZE_MASK) <<
  152. + SPFI_TRANSACTION_TSIZE_SHIFT);
  153. + } else {
  154. + transact = ((xfer->len & SPFI_TRANSACTION_TSIZE_MASK) <<
  155. + SPFI_TRANSACTION_TSIZE_SHIFT);
  156. + }
  157. + }
  158. + spfi_writel(spfi, transact, SPFI_TRANSACTION);
  159. val = spfi_readl(spfi, SPFI_CONTROL);
  160. val &= ~(SPFI_CONTROL_SEND_DMA | SPFI_CONTROL_GET_DMA);
  161. - if (xfer->tx_buf)
  162. + /*
  163. + * We set up send DMA for pending transfers also, as
  164. + * those are always send transfers
  165. + */
  166. + if ((xfer->tx_buf) || is_pending)
  167. val |= SPFI_CONTROL_SEND_DMA;
  168. - if (xfer->rx_buf)
  169. + if (xfer->tx_buf)
  170. + val |= SPFI_CONTROL_TX_RX;
  171. + if (xfer->rx_buf) {
  172. val |= SPFI_CONTROL_GET_DMA;
  173. + val &= ~SPFI_CONTROL_TX_RX;
  174. + }
  175. val &= ~(SPFI_CONTROL_TMODE_MASK << SPFI_CONTROL_TMODE_SHIFT);
  176. - if (xfer->tx_nbits == SPI_NBITS_DUAL &&
  177. + if (xfer->tx_nbits == SPI_NBITS_DUAL ||
  178. xfer->rx_nbits == SPI_NBITS_DUAL)
  179. val |= SPFI_CONTROL_TMODE_DUAL << SPFI_CONTROL_TMODE_SHIFT;
  180. - else if (xfer->tx_nbits == SPI_NBITS_QUAD &&
  181. + else if (xfer->tx_nbits == SPI_NBITS_QUAD ||
  182. xfer->rx_nbits == SPI_NBITS_QUAD)
  183. val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT;
  184. val |= SPFI_CONTROL_SE;