spi-realtek-rtl.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/module.h>
  3. #include <linux/platform_device.h>
  4. #include <linux/mod_devicetable.h>
  5. #include <linux/spi/spi.h>
  6. struct rtspi {
  7. void __iomem *base;
  8. };
  9. /* SPI Flash Configuration Register */
  10. #define RTL_SPI_SFCR 0x00
  11. #define RTL_SPI_SFCR_RBO BIT(28)
  12. #define RTL_SPI_SFCR_WBO BIT(27)
  13. /* SPI Flash Control and Status Register */
  14. #define RTL_SPI_SFCSR 0x08
  15. #define RTL_SPI_SFCSR_CSB0 BIT(31)
  16. #define RTL_SPI_SFCSR_CSB1 BIT(30)
  17. #define RTL_SPI_SFCSR_RDY BIT(27)
  18. #define RTL_SPI_SFCSR_CS BIT(24)
  19. #define RTL_SPI_SFCSR_LEN_MASK ~(0x03 << 28)
  20. #define RTL_SPI_SFCSR_LEN1 (0x00 << 28)
  21. #define RTL_SPI_SFCSR_LEN4 (0x03 << 28)
  22. /* SPI Flash Data Register */
  23. #define RTL_SPI_SFDR 0x0c
  24. #define REG(x) (rtspi->base + x)
  25. static void rt_set_cs(struct spi_device *spi, bool active)
  26. {
  27. struct rtspi *rtspi = spi_controller_get_devdata(spi->controller);
  28. u32 value;
  29. /* CS0 bit is active low */
  30. value = readl(REG(RTL_SPI_SFCSR));
  31. if (active)
  32. value |= RTL_SPI_SFCSR_CSB0;
  33. else
  34. value &= ~RTL_SPI_SFCSR_CSB0;
  35. writel(value, REG(RTL_SPI_SFCSR));
  36. }
  37. static void set_size(struct rtspi *rtspi, int size)
  38. {
  39. u32 value;
  40. value = readl(REG(RTL_SPI_SFCSR));
  41. value &= RTL_SPI_SFCSR_LEN_MASK;
  42. if (size == 4)
  43. value |= RTL_SPI_SFCSR_LEN4;
  44. else if (size == 1)
  45. value |= RTL_SPI_SFCSR_LEN1;
  46. writel(value, REG(RTL_SPI_SFCSR));
  47. }
  48. static inline void wait_ready(struct rtspi *rtspi)
  49. {
  50. while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))
  51. cpu_relax();
  52. }
  53. static void send4(struct rtspi *rtspi, const u32 *buf)
  54. {
  55. wait_ready(rtspi);
  56. set_size(rtspi, 4);
  57. writel(*buf, REG(RTL_SPI_SFDR));
  58. }
  59. static void send1(struct rtspi *rtspi, const u8 *buf)
  60. {
  61. wait_ready(rtspi);
  62. set_size(rtspi, 1);
  63. writel(buf[0] << 24, REG(RTL_SPI_SFDR));
  64. }
  65. static void rcv4(struct rtspi *rtspi, u32 *buf)
  66. {
  67. wait_ready(rtspi);
  68. set_size(rtspi, 4);
  69. *buf = readl(REG(RTL_SPI_SFDR));
  70. }
  71. static void rcv1(struct rtspi *rtspi, u8 *buf)
  72. {
  73. wait_ready(rtspi);
  74. set_size(rtspi, 1);
  75. *buf = readl(REG(RTL_SPI_SFDR)) >> 24;
  76. }
  77. static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
  78. struct spi_transfer *xfer)
  79. {
  80. struct rtspi *rtspi = spi_controller_get_devdata(ctrl);
  81. void *rx_buf;
  82. const void *tx_buf;
  83. int cnt;
  84. tx_buf = xfer->tx_buf;
  85. rx_buf = xfer->rx_buf;
  86. cnt = xfer->len;
  87. if (tx_buf) {
  88. while (cnt >= 4) {
  89. send4(rtspi, tx_buf);
  90. tx_buf += 4;
  91. cnt -= 4;
  92. }
  93. while (cnt) {
  94. send1(rtspi, tx_buf);
  95. tx_buf++;
  96. cnt--;
  97. }
  98. } else if (rx_buf) {
  99. while (cnt >= 4) {
  100. rcv4(rtspi, rx_buf);
  101. rx_buf += 4;
  102. cnt -= 4;
  103. }
  104. while (cnt) {
  105. rcv1(rtspi, rx_buf);
  106. rx_buf++;
  107. cnt--;
  108. }
  109. }
  110. spi_finalize_current_transfer(ctrl);
  111. return 0;
  112. }
  113. static void init_hw(struct rtspi *rtspi)
  114. {
  115. u32 value;
  116. /* Turn on big-endian byte ordering */
  117. value = readl(REG(RTL_SPI_SFCR));
  118. value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;
  119. writel(value, REG(RTL_SPI_SFCR));
  120. value = readl(REG(RTL_SPI_SFCSR));
  121. /* Permanently disable CS1, since it's never used */
  122. value |= RTL_SPI_SFCSR_CSB1;
  123. /* Select CS0 for use */
  124. value &= RTL_SPI_SFCSR_CS;
  125. writel(value, REG(RTL_SPI_SFCSR));
  126. }
  127. static int realtek_rtl_spi_probe(struct platform_device *pdev)
  128. {
  129. struct spi_controller *ctrl;
  130. struct rtspi *rtspi;
  131. int err;
  132. ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*rtspi));
  133. if (!ctrl) {
  134. dev_err(&pdev->dev, "Error allocating SPI controller\n");
  135. return -ENOMEM;
  136. }
  137. platform_set_drvdata(pdev, ctrl);
  138. rtspi = spi_controller_get_devdata(ctrl);
  139. rtspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
  140. if (IS_ERR(rtspi->base)) {
  141. dev_err(&pdev->dev, "Could not map SPI register address");
  142. return -ENOMEM;
  143. }
  144. init_hw(rtspi);
  145. ctrl->dev.of_node = pdev->dev.of_node;
  146. ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX;
  147. ctrl->set_cs = rt_set_cs;
  148. ctrl->transfer_one = transfer_one;
  149. err = devm_spi_register_controller(&pdev->dev, ctrl);
  150. if (err) {
  151. dev_err(&pdev->dev, "Could not register SPI controller\n");
  152. return -ENODEV;
  153. }
  154. return 0;
  155. }
  156. static const struct of_device_id realtek_rtl_spi_of_ids[] = {
  157. { .compatible = "realtek,rtl8380-spi" },
  158. { .compatible = "realtek,rtl8382-spi" },
  159. { .compatible = "realtek,rtl8391-spi" },
  160. { .compatible = "realtek,rtl8392-spi" },
  161. { .compatible = "realtek,rtl8393-spi" },
  162. { /* sentinel */ }
  163. };
  164. MODULE_DEVICE_TABLE(of, realtek_rtl_spi_of_ids);
  165. static struct platform_driver realtek_rtl_spi_driver = {
  166. .probe = realtek_rtl_spi_probe,
  167. .driver = {
  168. .name = "realtek-rtl-spi",
  169. .of_match_table = realtek_rtl_spi_of_ids,
  170. },
  171. };
  172. module_platform_driver(realtek_rtl_spi_driver);
  173. MODULE_LICENSE("GPL v2");
  174. MODULE_AUTHOR("Bert Vermeulen <[email protected]>");
  175. MODULE_DESCRIPTION("Realtek RTL SPI driver");