drv_spi.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Email: opensource_embedded@phytium.com.cn
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2022-11-10 liqiaozhong first commit
  11. * 2023-03-08 liqiaozhong support 4 spis and qspi working together
  12. *
  13. */
  14. #include"rtconfig.h"
  15. #include <rtthread.h>
  16. #include <rtdevice.h>
  17. #include "interrupt.h"
  18. #define LOG_TAG "spi_drv"
  19. #include "drv_log.h"
  20. #include <string.h>
  21. #include "fparameters.h"
  22. #include "fcpu_info.h"
  23. #include "fkernel.h"
  24. #include "ftypes.h"
  25. #ifdef RT_USING_SMART
  26. #include <ioremap.h>
  27. #endif
  28. #include <dfs_file.h>
  29. #include "fspim.h"
  30. #include "fspim_hw.h" /* include low-level header file for internal probe */
  31. #include "drv_spi.h"
  32. /************************** Constant Definitions *****************************/
  33. /**************************** Type Definitions *******************************/
  34. /************************** Variable Definitions *****************************/
  35. typedef struct
  36. {
  37. struct rt_spi_bus spi_bus;
  38. FSpim spim_instance;
  39. const char *name;
  40. } phytium_spi_bus;
  41. static struct rt_event rx_done_event;
  42. /***************** Macros (Inline Functions) Definitions *********************/
  43. #define EVENT_RX_DONE (1 << 1)
  44. /*******************************Api Functions*********************************/
  45. static rt_err_t spim_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
  46. static rt_uint32_t spim_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
  47. static FError FSpimSetupInterrupt(FSpim *instance_p)
  48. {
  49. FASSERT(instance_p);
  50. FSpimConfig *config_p = &instance_p->config;
  51. uintptr base_addr = config_p->base_addr;
  52. u32 cpu_id = 0;
  53. GetCpuId(&cpu_id);
  54. LOG_D("cpu_id is %d, irq_num is %d\n", cpu_id, config_p->irq_num);
  55. config_p->irq_prority = 0xd0;
  56. rt_hw_interrupt_set_target_cpus(config_p->irq_num, cpu_id);
  57. rt_hw_interrupt_set_priority(config_p->irq_num, config_p->irq_prority);
  58. /* register intr callback */
  59. rt_hw_interrupt_install(config_p->irq_num,
  60. FSpimInterruptHandler,
  61. instance_p,
  62. NULL);
  63. /* enable tx fifo overflow / rx overflow / rx full */
  64. FSpimMaskIrq(base_addr, FSPIM_IMR_ALL_BITS);
  65. /* enable irq */
  66. rt_hw_interrupt_umask(config_p->irq_num);
  67. return FSPIM_SUCCESS;
  68. }
  69. static void rt_ft_send_event_done(void *instance_p, void *param)
  70. {
  71. FASSERT(instance_p);
  72. rt_event_send(&rx_done_event, EVENT_RX_DONE);
  73. return;
  74. }
  75. static const struct rt_spi_ops spim_ops =
  76. {
  77. .configure = spim_configure,
  78. .xfer = spim_xfer
  79. };
  80. static rt_err_t spim_configure(struct rt_spi_device *device,
  81. struct rt_spi_configuration *configuration)
  82. {
  83. FError ret = FSPIM_SUCCESS;
  84. RT_ASSERT(device != RT_NULL);
  85. RT_ASSERT(configuration != RT_NULL);
  86. phytium_spi_bus *user_data_cfg = device->parent.user_data;
  87. FSpimConfig input_cfg = *FSpimLookupConfig(user_data_cfg->spim_instance.config.instance_id);
  88. #ifdef RT_USING_SMART
  89. input_cfg.base_addr = (uintptr)rt_ioremap((void *)input_cfg.base_addr, 0x1000);
  90. #endif
  91. FSpimConfig *set_input_cfg = &input_cfg;
  92. /* set fspim device according to configuration */
  93. if (configuration->mode & RT_SPI_CPOL)
  94. {
  95. set_input_cfg->cpol = FSPIM_CPOL_HIGH;
  96. }
  97. else
  98. {
  99. set_input_cfg->cpol = FSPIM_CPOL_LOW;
  100. }
  101. if (configuration->mode & RT_SPI_CPHA)
  102. {
  103. set_input_cfg->cpha = FSPIM_CPHA_2_EDGE;
  104. }
  105. else
  106. {
  107. set_input_cfg->cpha = FSPIM_CPHA_1_EDGE;
  108. }
  109. if (configuration->data_width == 8)
  110. {
  111. set_input_cfg->n_bytes = FSPIM_1_BYTE;
  112. }
  113. else if (configuration->data_width == 16)
  114. {
  115. set_input_cfg->n_bytes = FSPIM_2_BYTE;
  116. }
  117. /* send spi_cfg to RT-Thread sys */
  118. ret = FSpimCfgInitialize(&user_data_cfg->spim_instance, &input_cfg);
  119. if (FSPIM_SUCCESS != ret)
  120. {
  121. return -RT_ERROR;
  122. }
  123. /* irq setting */
  124. ret = FSpimSetupInterrupt(&user_data_cfg->spim_instance);
  125. if (FSPIM_SUCCESS != ret)
  126. {
  127. return -RT_ERROR;
  128. }
  129. FSpimRegisterIntrruptHandler(&user_data_cfg->spim_instance, FSPIM_INTR_EVT_RX_DONE, rt_ft_send_event_done, NULL);
  130. return ret;
  131. }
  132. static rt_uint32_t spim_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  133. {
  134. RT_ASSERT(device != RT_NULL);
  135. RT_ASSERT(device->parent.user_data != RT_NULL);
  136. RT_ASSERT(message != RT_NULL);
  137. rt_size_t message_length;
  138. rt_uint8_t *recv_buf;
  139. const rt_uint8_t *send_buf;
  140. /* recv spi_cfg from RT-Thread sys */
  141. phytium_spi_bus *user_data_xfer = device->parent.user_data;
  142. FSpim *xfer_spim_instance = &user_data_xfer->spim_instance;
  143. FError tx_rx_result = FSPIM_SUCCESS;
  144. message_length = message->length;
  145. recv_buf = message->recv_buf;
  146. send_buf = message->send_buf;
  147. if (message->cs_take)
  148. {
  149. FSpimSetChipSelection(xfer_spim_instance, TRUE);
  150. }
  151. if (message_length > 0)
  152. {
  153. if (send_buf == RT_NULL && recv_buf != RT_NULL)
  154. {
  155. /* receive message */
  156. tx_rx_result = FSpimTransferByInterrupt(xfer_spim_instance, RT_NULL, recv_buf, message_length);
  157. }
  158. else if (send_buf != RT_NULL && recv_buf == RT_NULL)
  159. {
  160. /* send message */
  161. tx_rx_result = FSpimTransferByInterrupt(xfer_spim_instance, send_buf, RT_NULL, message_length);
  162. }
  163. else if (send_buf != RT_NULL && recv_buf != RT_NULL)
  164. {
  165. /* not supported yet */
  166. rt_kprintf("Do not support the situation that send_buf and recv_buf both not equal to 0.");
  167. }
  168. }
  169. if (FSPIM_SUCCESS != tx_rx_result)
  170. {
  171. rt_kprintf("FSpimTransferByInterrupt() fail!!!");
  172. message_length = 0;
  173. }
  174. if (rt_event_recv(&rx_done_event, (EVENT_RX_DONE),
  175. (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR),
  176. RT_WAITING_FOREVER, RT_NULL) != RT_EOK)
  177. {
  178. rt_kprintf("Wait rx timeout!!!\n");
  179. message_length = 0;
  180. }
  181. if (message->cs_release)
  182. {
  183. FSpimSetChipSelection(xfer_spim_instance, FALSE);
  184. }
  185. return message_length;
  186. }
  187. static int spi_init(phytium_spi_bus *phytium_spi)
  188. {
  189. rt_spi_bus_register(&phytium_spi->spi_bus, phytium_spi->name, &spim_ops);
  190. RT_ASSERT((struct rt_spi_device *)rt_device_find(phytium_spi->name));
  191. return 0;
  192. }
  193. #ifdef RT_USING_SPIM0
  194. static phytium_spi_bus spi0_bus;
  195. #endif
  196. #ifdef RT_USING_SPIM1
  197. static phytium_spi_bus spi1_bus;
  198. #endif
  199. #ifdef RT_USING_SPIM2
  200. static phytium_spi_bus spi2_bus;
  201. #endif
  202. #ifdef RT_USING_SPIM3
  203. static phytium_spi_bus spi3_bus;
  204. #endif
  205. int rt_hw_spi_init(void)
  206. {
  207. /* event creat */
  208. if (RT_EOK != rt_event_init(&rx_done_event, "rx_done_event", RT_IPC_FLAG_FIFO))
  209. {
  210. rt_kprintf("Create event failed.\n");
  211. return -RT_ERROR;
  212. }
  213. #ifdef RT_USING_SPIM0
  214. spi0_bus.name = "SPI0";
  215. spi0_bus.spim_instance.config.instance_id = FSPI0_ID;
  216. spi_init(&spi0_bus);
  217. #endif
  218. #ifdef RT_USING_SPIM1
  219. spi1_bus.name = "SPI1";
  220. spi1_bus.spim_instance.config.instance_id = FSPI1_ID;
  221. spi_init(&spi1_bus);
  222. #endif
  223. #ifdef RT_USING_SPIM2
  224. spi2_bus.name = "SPI2";
  225. spi2_bus.spim_instance.config.instance_id = FSPI2_ID;
  226. spi_init(&spi2_bus);
  227. #endif
  228. #ifdef RT_USING_SPIM3
  229. spi3_bus.name = "SPI3";
  230. spi3_bus.spim_instance.config.instance_id = FSPI3_ID;
  231. spi_init(&spi3_bus);
  232. #endif
  233. return 0;
  234. }
  235. INIT_DEVICE_EXPORT(rt_hw_spi_init);