ch56x_spi.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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. * 2022-07-30 Emuzit first version
  9. */
  10. #include <rthw.h>
  11. #include <rtdebug.h>
  12. #include <drivers/spi.h>
  13. #include <drivers/pin.h>
  14. #include "ch56x_spi.h"
  15. #include "ch56x_sys.h"
  16. #if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1)
  17. #error "Please define at least one SPIx"
  18. #endif
  19. struct spi_bus
  20. {
  21. struct rt_spi_bus parent;
  22. volatile struct spi_registers *reg_base;
  23. irq_number_t irqn;
  24. char *name;
  25. rt_base_t sck_pin;
  26. rt_base_t mosi_pin;
  27. rt_base_t miso_pin;
  28. };
  29. #ifdef BSP_USING_SPI0
  30. static struct spi_bus spi_bus_0 =
  31. {
  32. .reg_base = (struct spi_registers *)SPI0_REG_BASE,
  33. .irqn = SPI0_IRQn,
  34. .name = SPI0_BUS_NAME,
  35. .sck_pin = SPI0_SCK_PIN,
  36. .mosi_pin = SPI0_MOSI_PIN,
  37. .miso_pin = SPI0_MISO_PIN,
  38. };
  39. #endif
  40. #ifdef BSP_USING_SPI1
  41. static struct spi_bus spi_bus_1 =
  42. {
  43. .reg_base = (struct spi_registers *)SPI1_REG_BASE,
  44. .irqn = SPI1_IRQn,
  45. .name = SPI1_BUS_NAME,
  46. .sck_pin = SPI1_SCK_PIN,
  47. .mosi_pin = SPI1_MOSI_PIN,
  48. .miso_pin = SPI1_MISO_PIN,
  49. };
  50. #endif
  51. static uint8_t _spi_pin_config(struct rt_spi_device *device, struct rt_spi_configuration *config)
  52. {
  53. struct spi_bus *spi_bus = (struct spi_bus *)device->bus;
  54. uint8_t mode;
  55. /* RT_SPI_3WIRE means SI/SO pin shared */
  56. mode = config->mode & (RT_SPI_MASTER | RT_SPI_SLAVE | RT_SPI_3WIRE);
  57. if (mode == RT_SPI_MASTER)
  58. {
  59. mode = RB_SPI_MOSI_OE | RB_SPI_SCK_OE;
  60. rt_pin_mode(spi_bus->mosi_pin, PIN_MODE_OUTPUT);
  61. rt_pin_mode(spi_bus->sck_pin, PIN_MODE_OUTPUT);
  62. }
  63. else if (mode == RT_SPI_SLAVE)
  64. {
  65. mode = RB_SPI_MISO_OE | RB_SPI_MODE_SLAVE;
  66. rt_pin_mode(spi_bus->miso_pin, PIN_MODE_OUTPUT);
  67. }
  68. else if (mode == RT_SPI_MASTER | RT_SPI_3WIRE)
  69. {
  70. mode = RB_SPI_2WIRE_MOD | RB_SPI_MISO_OE | RB_SPI_SCK_OE;
  71. rt_pin_mode(spi_bus->miso_pin, PIN_MODE_INPUT);
  72. rt_pin_mode(spi_bus->sck_pin, PIN_MODE_OUTPUT);
  73. }
  74. else
  75. {
  76. mode = RB_SPI_2WIRE_MOD | RB_SPI_MISO_OE | RB_SPI_MODE_SLAVE;
  77. rt_pin_mode(spi_bus->miso_pin, PIN_MODE_INPUT);
  78. }
  79. return mode;
  80. }
  81. static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *config)
  82. {
  83. volatile struct spi_registers *sxreg;
  84. struct rt_spi_device *owner;
  85. union _spi_ctrl_mod ctrl_mod;
  86. uint8_t mode;
  87. uint32_t Fsys;
  88. uint32_t div;
  89. rt_base_t cs_pin;
  90. int inactive;
  91. RT_ASSERT(device != RT_NULL);
  92. /* ch56x SPI supports only 8-bit data */
  93. if (config->data_width != 8)
  94. return -RT_EINVAL;
  95. ctrl_mod.reg = _spi_pin_config(device, config);
  96. /* ch56x SPI supports only mode 0 & mode 3 */
  97. mode = config->mode & (RT_SPI_CPOL | RT_SPI_CPHA);
  98. if (mode == RT_SPI_MODE_0)
  99. ctrl_mod.mst_sck_mod = MST_SCK_MOD_0;
  100. else if (mode == RT_SPI_MODE_3)
  101. ctrl_mod.mst_sck_mod = MST_SCK_MOD_3;
  102. else
  103. return -RT_EINVAL;
  104. /* CLOCK_DIV is 8-bit, reject excessively low max_hz */
  105. Fsys = sys_hclk_get();
  106. if (config->max_hz < Fsys / 255)
  107. return -RT_EINVAL;
  108. /* minimum allowable CLOCK_DIV is 2 */
  109. div = (Fsys + config->max_hz - 1) / config->max_hz;
  110. if (div < 2)
  111. div = 2;
  112. sxreg = ((struct spi_bus *)device->bus)->reg_base;
  113. sxreg->CLOCK_DIV = div;
  114. mode = config->mode & (RT_SPI_MSB | RT_SPI_LSB);
  115. sxreg->CTRL_CFG.reg = (mode == RT_SPI_MSB) ? 0 : RB_SPI_BIT_ORDER;
  116. sxreg->INTER_EN.reg = 0;
  117. ctrl_mod.all_clear = 1;
  118. sxreg->CTRL_MOD.reg = ctrl_mod.reg;
  119. ctrl_mod.all_clear = 0;
  120. sxreg->CTRL_MOD.reg = ctrl_mod.reg;
  121. mode = config->mode & (RT_SPI_MASTER | RT_SPI_SLAVE);
  122. if (mode == RT_SPI_MASTER)
  123. {
  124. /* get bus owner before this configure */
  125. owner = device->bus->owner;
  126. if (owner && owner != device)
  127. {
  128. /* make sure predecessor's CS is deactived */
  129. inactive = (owner->config.mode & RT_SPI_CS_HIGH) ? PIN_LOW : PIN_HIGH;
  130. cs_pin = (rt_base_t)owner->parent.user_data;
  131. rt_pin_write(cs_pin, inactive);
  132. }
  133. /* bus owner is maintained by upper layer, do not update here */
  134. inactive = (config->mode & RT_SPI_CS_HIGH) ? PIN_LOW : PIN_HIGH;
  135. cs_pin = (rt_base_t)device->parent.user_data;
  136. rt_pin_write(cs_pin, inactive);
  137. rt_pin_mode(cs_pin, PIN_MODE_OUTPUT);
  138. }
  139. /* `config` is actually `device->config` : spi_core.c */
  140. //device->config = *config;
  141. return RT_EOK;
  142. }
  143. /**
  144. * @brief Transfer SPI data for single message.
  145. * Message traversing is done by rt_spi_message().
  146. *
  147. * @param device is pointer to the rt_spi_device device.
  148. *
  149. * @param message is a link list for data/control information,
  150. * only the first entry is processed.
  151. * Note: ch56x can't do SPI send & recv at the same time.
  152. *
  153. * @return `message->length1 if successful, 0 otherwise.
  154. */
  155. static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  156. {
  157. struct spi_bus *spi_bus = (struct spi_bus *)device->bus;
  158. volatile struct spi_registers *sxreg = spi_bus->reg_base;
  159. union _spi_ctrl_mod ctrl_mod;
  160. uint8_t *data;
  161. uint32_t size;
  162. rt_base_t cs_pin;
  163. int cs_high;
  164. size = message->length;
  165. if (size == 0 || size > 4095)
  166. return 0;
  167. ctrl_mod.reg = sxreg->CTRL_MOD.reg | RB_SPI_ALL_CLEAR;
  168. /* ch56x can't do SPI send & recv at the same time */
  169. if (message->send_buf && !message->recv_buf)
  170. {
  171. data = (uint8_t *)message->send_buf;
  172. ctrl_mod.fifo_dir = SPI_FIFO_DIR_OUTPUT;
  173. }
  174. else if (!message->send_buf && message->recv_buf)
  175. {
  176. data = (uint8_t *)message->recv_buf;
  177. ctrl_mod.fifo_dir = SPI_FIFO_DIR_INPUT;
  178. }
  179. else
  180. {
  181. return 0;
  182. }
  183. sxreg->CTRL_MOD.reg = ctrl_mod.reg;
  184. ctrl_mod.all_clear = 0;
  185. sxreg->CTRL_MOD.reg = ctrl_mod.reg;
  186. /* set MISO pin direction to match xfer if shared SI/SO pin */
  187. if (device->config.mode & RT_SPI_3WIRE)
  188. {
  189. rt_base_t mode = message->send_buf ? PIN_MODE_OUTPUT : PIN_MODE_INPUT;
  190. rt_pin_mode(spi_bus->miso_pin, mode);
  191. }
  192. cs_pin = (rt_base_t)device->parent.user_data;
  193. cs_high = device->config.mode & RT_SPI_CS_HIGH;
  194. if (message->cs_take)
  195. {
  196. /* take/activate CS */
  197. rt_pin_write(cs_pin, cs_high ? PIN_HIGH : PIN_LOW);
  198. }
  199. sxreg->TOTAL_COUNT = size;
  200. if (size > SPI_FIFO_SIZE)
  201. {
  202. sxreg->DMA_BIG = (uint32_t)data;
  203. sxreg->DMA_END = (uint32_t)(data + size);
  204. sxreg->CTRL_CFG.dma_enable = 1;
  205. /* mark no need to read FIFO */
  206. size = 0;
  207. }
  208. else
  209. {
  210. if (message->send_buf)
  211. {
  212. /* keep sending, won't overflow */
  213. while (size)
  214. {
  215. sxreg->FIFO = *data++;
  216. size--;
  217. }
  218. }
  219. }
  220. /* wait for transfer done */
  221. while (sxreg->TOTAL_COUNT > 0);
  222. /* disable DMA, anyway */
  223. sxreg->CTRL_CFG.dma_enable = 0;
  224. /* non-DMA recv => read data from FIFO */
  225. if (size > 0)
  226. {
  227. while (size--)
  228. *data++ = sxreg->FIFO;
  229. }
  230. /* set MISO as input after xfer if shared SI/SO pin */
  231. if (device->config.mode & RT_SPI_3WIRE)
  232. {
  233. rt_pin_mode(spi_bus->miso_pin, PIN_MODE_INPUT);
  234. }
  235. if (message->cs_release)
  236. {
  237. /* release/deactivate CS */
  238. rt_pin_write(cs_pin, cs_high ? PIN_LOW : PIN_HIGH);
  239. }
  240. return message->length;
  241. }
  242. static const struct rt_spi_ops spi_ops =
  243. {
  244. .configure = spi_configure,
  245. .xfer = spi_xfer,
  246. };
  247. static int rt_hw_spi_init(void)
  248. {
  249. struct spi_bus *devices[2];
  250. rt_err_t res, ret = RT_EOK;
  251. int n = 0;
  252. #ifdef BSP_USING_SPI1
  253. devices[n++] = &spi_bus_1;
  254. #endif
  255. #ifdef BSP_USING_SPI0
  256. devices[n++] = &spi_bus_0;
  257. #endif
  258. while (--n >= 0)
  259. {
  260. struct spi_bus *spi_bus = devices[n];
  261. sys_clk_off_by_irqn(spi_bus->irqn, SYS_SLP_CLK_ON);
  262. res = rt_spi_bus_register(&spi_bus->parent, spi_bus->name, &spi_ops);
  263. if (res != RT_EOK)
  264. {
  265. ret = res;
  266. }
  267. };
  268. return ret;
  269. }
  270. INIT_DEVICE_EXPORT(rt_hw_spi_init);