drv_spi.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-03-28 qiujingbao first version
  9. */
  10. #include "drv_spi.h"
  11. #define DBG_TAG "drv.spi"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. static struct cv1800_spi cv1800_spi_obj[] =
  15. {
  16. #ifdef BSP_USING_SPI
  17. {
  18. .spi_id = SPI2,
  19. .device_name = "spi2",
  20. .fifo_len = SPI_TXFTLR,
  21. },
  22. #endif
  23. };
  24. static struct spi_regs *get_spi_base(uint8_t spi_id)
  25. {
  26. struct spi_regs *spi_base = NULL;
  27. switch (spi_id)
  28. {
  29. case SPI0:
  30. spi_base = (struct spi_regs *)SPI0_BASE;
  31. break;
  32. case SPI1:
  33. spi_base = (struct spi_regs *)SPI1_BASE;
  34. break;
  35. case SPI2:
  36. spi_base = (struct spi_regs *)SPI2_BASE;
  37. break;
  38. case SPI3:
  39. spi_base = (struct spi_regs *)SPI3_BASE;
  40. break;
  41. }
  42. return spi_base;
  43. }
  44. static rt_err_t drv_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
  45. {
  46. rt_err_t ret = RT_EOK;
  47. struct cv1800_spi *spi_dev = RT_NULL;
  48. uint32_t mode;
  49. spi_dev = (struct cv1800_spi *)(device->bus->parent.user_data);
  50. spi_dev->data_width = configuration->data_width;
  51. /* disable spi */
  52. spi_enable(spi_dev->reg, 0);
  53. /* clear irq */
  54. spi_clear_irq(spi_dev->reg, SPI_IRQ_MSAK);
  55. /* set clk */
  56. ret = spi_set_frequency(spi_dev->reg, configuration->max_hz);
  57. if (ret)
  58. return ret;
  59. /* set mode */
  60. ret = gen_spi_mode(configuration, &mode);
  61. if (ret)
  62. return ret;
  63. spi_set_mode(spi_dev->reg, mode);
  64. /* set cs */
  65. spi_enable_cs(spi_dev->reg, 0x1);
  66. spi_enable(spi_dev->reg, 0x1);
  67. mode = mmio_read_32((uintptr_t)&spi_dev->reg->spi_ctrl0);
  68. LOG_D("mode: %x", mode);
  69. mode = mmio_read_32((uintptr_t)&spi_dev->reg->spi_baudr);
  70. LOG_D("spi_baudr: %x", mode);
  71. return ret;
  72. }
  73. int hw_spi_recv(struct cv1800_spi *dev) {
  74. uint32_t rever;
  75. uint32_t tem;
  76. int ret;
  77. rever = mmio_read_32((uintptr_t)&dev->reg->spi_rxflr);
  78. ret = (int)rever;
  79. while (rever)
  80. {
  81. tem = mmio_read_32((uintptr_t)&dev->reg->spi_dr);
  82. if (dev->recv_buf < dev->recv_end)
  83. {
  84. if (dev->data_width == 8)
  85. *(uint8_t *)(dev->recv_buf) = tem;
  86. else
  87. *(uint16_t *)(dev->recv_buf) = tem;
  88. }
  89. else
  90. {
  91. return 0;
  92. }
  93. rever--;
  94. dev->recv_buf += dev->data_width >> 3;
  95. }
  96. return ret;
  97. }
  98. int hw_spi_send(struct cv1800_spi *dev) {
  99. uint32_t txflr;
  100. uint32_t max;
  101. uint16_t value;
  102. txflr = mmio_read_32((uintptr_t)&dev->reg->spi_txflr);
  103. max = dev->fifo_len - txflr;
  104. while (max)
  105. {
  106. if (dev->send_end - dev->send_buf)
  107. {
  108. if (dev->data_width == 8)
  109. value = *(uint8_t *)(dev->send_buf);
  110. else
  111. value = *(uint16_t *)(dev->send_buf);
  112. }
  113. else
  114. {
  115. return 0;
  116. }
  117. mmio_write_32((uintptr_t)&dev->reg->spi_dr, value);
  118. dev->send_buf += dev->data_width >> 3;
  119. max--;
  120. }
  121. return 0;
  122. }
  123. static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) {
  124. int ret = 0;
  125. struct cv1800_spi *spi_dev;
  126. RT_ASSERT(device != RT_NULL);
  127. RT_ASSERT(device->bus != RT_NULL);
  128. RT_ASSERT(message != RT_NULL);
  129. spi_dev = (struct cv1800_spi *)(device->bus->parent.user_data);
  130. if (message->send_buf != RT_NULL)
  131. {
  132. spi_dev->send_buf = message->send_buf;
  133. spi_dev->send_end = (void *)((uint8_t *)spi_dev->send_buf + message->length);
  134. }
  135. if (message->recv_buf != RT_NULL)
  136. {
  137. spi_dev->recv_buf = message->recv_buf;
  138. spi_dev->recv_end = (void *)((uint8_t *)spi_dev->recv_buf + message->length);
  139. }
  140. /* if user use their cs */
  141. if (message->cs_take && device->cs_pin != PIN_NONE)
  142. rt_pin_write(device->cs_pin, PIN_LOW);
  143. if (message->send_buf)
  144. {
  145. while (spi_dev->send_buf != spi_dev->send_end)
  146. {
  147. hw_spi_send(spi_dev);
  148. }
  149. /* wait for complete */
  150. while (mmio_read_32((uintptr_t)&spi_dev->reg->spi_txflr)) {}
  151. ret = message->length;
  152. }
  153. if (message->recv_buf)
  154. {
  155. while (spi_dev->recv_buf != spi_dev->recv_end)
  156. {
  157. hw_spi_recv(spi_dev);
  158. }
  159. ret = message->length;
  160. }
  161. if (message->cs_release && device->cs_pin != PIN_NONE)
  162. rt_pin_write(device->cs_pin, PIN_HIGH);
  163. return ret;
  164. }
  165. const static struct rt_spi_ops drv_spi_ops =
  166. {
  167. drv_spi_configure,
  168. spixfer,
  169. };
  170. int rt_hw_spi_init(void)
  171. {
  172. rt_err_t ret = RT_EOK;
  173. struct spi_regs *reg = NULL;
  174. for (rt_size_t i = 0; i < sizeof(cv1800_spi_obj) / sizeof(struct cv1800_spi); i++) {
  175. /* set reg base addr */
  176. reg = get_spi_base(cv1800_spi_obj[i].spi_id);
  177. if (!reg)
  178. return -RT_ERROR;
  179. cv1800_spi_obj[i].reg = reg;
  180. cv1800_spi_obj[i].spi_bus.parent.user_data = &cv1800_spi_obj[i];
  181. /* register spix bus */
  182. ret = rt_spi_bus_register(&cv1800_spi_obj[i].spi_bus, cv1800_spi_obj[i].device_name, &drv_spi_ops);
  183. }
  184. return ret;
  185. }
  186. INIT_BOARD_EXPORT(rt_hw_spi_init);