spi-altera-core.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Altera SPI driver
  4. *
  5. * Copyright (C) 2008 Thomas Chou <[email protected]>
  6. *
  7. * Based on spi_s3c24xx.c, which is:
  8. * Copyright (c) 2006 Ben Dooks
  9. * Copyright (c) 2006 Simtec Electronics
  10. * Ben Dooks <[email protected]>
  11. */
  12. #include <linux/errno.h>
  13. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/spi/altera.h>
  16. #include <linux/spi/spi.h>
  17. #include <linux/io.h>
  18. #include <linux/of.h>
  19. #define DRV_NAME "spi_altera"
  20. #define ALTERA_SPI_RXDATA 0
  21. #define ALTERA_SPI_TXDATA 4
  22. #define ALTERA_SPI_STATUS 8
  23. #define ALTERA_SPI_CONTROL 12
  24. #define ALTERA_SPI_SLAVE_SEL 20
  25. #define ALTERA_SPI_STATUS_ROE_MSK 0x8
  26. #define ALTERA_SPI_STATUS_TOE_MSK 0x10
  27. #define ALTERA_SPI_STATUS_TMT_MSK 0x20
  28. #define ALTERA_SPI_STATUS_TRDY_MSK 0x40
  29. #define ALTERA_SPI_STATUS_RRDY_MSK 0x80
  30. #define ALTERA_SPI_STATUS_E_MSK 0x100
  31. #define ALTERA_SPI_CONTROL_IROE_MSK 0x8
  32. #define ALTERA_SPI_CONTROL_ITOE_MSK 0x10
  33. #define ALTERA_SPI_CONTROL_ITRDY_MSK 0x40
  34. #define ALTERA_SPI_CONTROL_IRRDY_MSK 0x80
  35. #define ALTERA_SPI_CONTROL_IE_MSK 0x100
  36. #define ALTERA_SPI_CONTROL_SSO_MSK 0x400
  37. static int altr_spi_writel(struct altera_spi *hw, unsigned int reg,
  38. unsigned int val)
  39. {
  40. int ret;
  41. ret = regmap_write(hw->regmap, hw->regoff + reg, val);
  42. if (ret)
  43. dev_err(hw->dev, "fail to write reg 0x%x val 0x%x: %d\n",
  44. reg, val, ret);
  45. return ret;
  46. }
  47. static int altr_spi_readl(struct altera_spi *hw, unsigned int reg,
  48. unsigned int *val)
  49. {
  50. int ret;
  51. ret = regmap_read(hw->regmap, hw->regoff + reg, val);
  52. if (ret)
  53. dev_err(hw->dev, "fail to read reg 0x%x: %d\n", reg, ret);
  54. return ret;
  55. }
  56. static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
  57. {
  58. return spi_master_get_devdata(sdev->master);
  59. }
  60. static void altera_spi_set_cs(struct spi_device *spi, bool is_high)
  61. {
  62. struct altera_spi *hw = altera_spi_to_hw(spi);
  63. if (is_high) {
  64. hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
  65. altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
  66. altr_spi_writel(hw, ALTERA_SPI_SLAVE_SEL, 0);
  67. } else {
  68. altr_spi_writel(hw, ALTERA_SPI_SLAVE_SEL,
  69. BIT(spi->chip_select));
  70. hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
  71. altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
  72. }
  73. }
  74. static void altera_spi_tx_word(struct altera_spi *hw)
  75. {
  76. unsigned int txd = 0;
  77. if (hw->tx) {
  78. switch (hw->bytes_per_word) {
  79. case 1:
  80. txd = hw->tx[hw->count];
  81. break;
  82. case 2:
  83. txd = (hw->tx[hw->count * 2]
  84. | (hw->tx[hw->count * 2 + 1] << 8));
  85. break;
  86. case 4:
  87. txd = (hw->tx[hw->count * 4]
  88. | (hw->tx[hw->count * 4 + 1] << 8)
  89. | (hw->tx[hw->count * 4 + 2] << 16)
  90. | (hw->tx[hw->count * 4 + 3] << 24));
  91. break;
  92. }
  93. }
  94. altr_spi_writel(hw, ALTERA_SPI_TXDATA, txd);
  95. }
  96. static void altera_spi_rx_word(struct altera_spi *hw)
  97. {
  98. unsigned int rxd;
  99. altr_spi_readl(hw, ALTERA_SPI_RXDATA, &rxd);
  100. if (hw->rx) {
  101. switch (hw->bytes_per_word) {
  102. case 1:
  103. hw->rx[hw->count] = rxd;
  104. break;
  105. case 2:
  106. hw->rx[hw->count * 2] = rxd;
  107. hw->rx[hw->count * 2 + 1] = rxd >> 8;
  108. break;
  109. case 4:
  110. hw->rx[hw->count * 4] = rxd;
  111. hw->rx[hw->count * 4 + 1] = rxd >> 8;
  112. hw->rx[hw->count * 4 + 2] = rxd >> 16;
  113. hw->rx[hw->count * 4 + 3] = rxd >> 24;
  114. break;
  115. }
  116. }
  117. hw->count++;
  118. }
  119. static int altera_spi_txrx(struct spi_master *master,
  120. struct spi_device *spi, struct spi_transfer *t)
  121. {
  122. struct altera_spi *hw = spi_master_get_devdata(master);
  123. u32 val;
  124. hw->tx = t->tx_buf;
  125. hw->rx = t->rx_buf;
  126. hw->count = 0;
  127. hw->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
  128. hw->len = t->len / hw->bytes_per_word;
  129. if (hw->irq >= 0) {
  130. /* enable receive interrupt */
  131. hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
  132. altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
  133. /* send the first byte */
  134. altera_spi_tx_word(hw);
  135. return 1;
  136. }
  137. while (hw->count < hw->len) {
  138. altera_spi_tx_word(hw);
  139. for (;;) {
  140. altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
  141. if (val & ALTERA_SPI_STATUS_RRDY_MSK)
  142. break;
  143. cpu_relax();
  144. }
  145. altera_spi_rx_word(hw);
  146. }
  147. spi_finalize_current_transfer(master);
  148. return 0;
  149. }
  150. irqreturn_t altera_spi_irq(int irq, void *dev)
  151. {
  152. struct spi_master *master = dev;
  153. struct altera_spi *hw = spi_master_get_devdata(master);
  154. altera_spi_rx_word(hw);
  155. if (hw->count < hw->len) {
  156. altera_spi_tx_word(hw);
  157. } else {
  158. /* disable receive interrupt */
  159. hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
  160. altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
  161. spi_finalize_current_transfer(master);
  162. }
  163. return IRQ_HANDLED;
  164. }
  165. EXPORT_SYMBOL_GPL(altera_spi_irq);
  166. void altera_spi_init_master(struct spi_master *master)
  167. {
  168. struct altera_spi *hw = spi_master_get_devdata(master);
  169. u32 val;
  170. master->transfer_one = altera_spi_txrx;
  171. master->set_cs = altera_spi_set_cs;
  172. /* program defaults into the registers */
  173. hw->imr = 0; /* disable spi interrupts */
  174. altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
  175. altr_spi_writel(hw, ALTERA_SPI_STATUS, 0); /* clear status reg */
  176. altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
  177. if (val & ALTERA_SPI_STATUS_RRDY_MSK)
  178. altr_spi_readl(hw, ALTERA_SPI_RXDATA, &val); /* flush rxdata */
  179. }
  180. EXPORT_SYMBOL_GPL(altera_spi_init_master);
  181. MODULE_LICENSE("GPL");