drv_spi.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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 <rtthread.h>
  15. #include <rtdevice.h>
  16. #include "interrupt.h"
  17. #include <string.h>
  18. #include "fdebug.h"
  19. #if defined(TARGET_E2000)
  20. #include "fparameters.h"
  21. #endif
  22. #include "fcpu_info.h"
  23. #include "fkernel.h"
  24. #include "ftypes.h"
  25. #include "fsleep.h"
  26. #ifdef RT_USING_SPI
  27. #include <dfs_file.h>
  28. #include "fspim.h"
  29. #include "fspim_hw.h" /* include low-level header file for internal probe */
  30. #include "drv_spi.h"
  31. /************************** Constant Definitions *****************************/
  32. /**************************** Type Definitions *******************************/
  33. /************************** Variable Definitions *****************************/
  34. #ifdef RT_USING_SPIM0
  35. static struct drv_spi _RTSpim0;
  36. #endif
  37. #ifdef RT_USING_SPIM1
  38. static struct drv_spi _RTSpim1;
  39. #endif
  40. #ifdef RT_USING_SPIM2
  41. static struct drv_spi _RTSpim2;
  42. #endif
  43. #ifdef RT_USING_SPIM3
  44. static struct drv_spi _RTSpim3;
  45. #endif
  46. static struct rt_spi_device *spi_device = RT_NULL;
  47. static struct rt_event rx_done_event;
  48. /***************** Macros (Inline Functions) Definitions *********************/
  49. #define FSPIM_DEBUG_TAG "SPIM"
  50. #define FSPIM_ERROR(format, ...) FT_DEBUG_PRINT_E(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  51. #define FSPIM_WARN(format, ...) FT_DEBUG_PRINT_W(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  52. #define FSPIM_INFO(format, ...) FT_DEBUG_PRINT_I(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  53. #define FSPIM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
  54. #define EVENT_RX_DONE (1 << 1)
  55. /*******************************Api Functions*********************************/
  56. static rt_err_t spim_configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration);
  57. static rt_uint32_t spim_xfer(struct rt_spi_device* device, struct rt_spi_message* message);
  58. static FError FSpimSetupInterrupt(FSpim *instance_p)
  59. {
  60. FASSERT(instance_p);
  61. FSpimConfig *config_p = &instance_p->config;
  62. uintptr base_addr = config_p->base_addr;
  63. u32 cpu_id = 0;
  64. GetCpuId(&cpu_id);
  65. FSPIM_DEBUG("cpu_id is %d, irq_num is %d\n", cpu_id, config_p->irq_num);
  66. config_p->irq_prority = 0xd0;
  67. rt_hw_interrupt_set_target_cpus(config_p->irq_num, cpu_id);
  68. rt_hw_interrupt_set_priority(config_p->irq_num, config_p->irq_prority);
  69. /* register intr callback */
  70. rt_hw_interrupt_install(config_p->irq_num,
  71. FSpimInterruptHandler,
  72. instance_p,
  73. NULL);
  74. /* enable tx fifo overflow / rx overflow / rx full */
  75. FSpimMaskIrq(base_addr, FSPIM_IMR_ALL_BITS);
  76. /* enable irq */
  77. rt_hw_interrupt_umask(config_p->irq_num);
  78. return FSPIM_SUCCESS;
  79. }
  80. static void rt_ft_send_event_done(void *instance_p, void *param)
  81. {
  82. FASSERT(instance_p);
  83. rt_event_send(&rx_done_event, EVENT_RX_DONE);
  84. return;
  85. }
  86. static const struct rt_spi_ops spim_ops =
  87. {
  88. .configure = spim_configure,
  89. .xfer = spim_xfer
  90. };
  91. static rt_err_t spim_configure(struct rt_spi_device *device,
  92. struct rt_spi_configuration *configuration)
  93. {
  94. FError ret = FSPIM_SUCCESS;
  95. RT_ASSERT(device != RT_NULL);
  96. RT_ASSERT(configuration != RT_NULL);
  97. struct drv_spi *user_data_cfg = device->parent.user_data;
  98. FSpimConfig input_cfg = *FSpimLookupConfig(user_data_cfg->spi_id);
  99. FSpimConfig *set_input_cfg = &input_cfg;
  100. /* set fspim device according to configuration */
  101. if (configuration->mode & RT_SPI_CPOL)
  102. {
  103. set_input_cfg->cpol = FSPIM_CPOL_HIGH;
  104. }
  105. else
  106. {
  107. set_input_cfg->cpol = FSPIM_CPOL_LOW;
  108. }
  109. if (configuration->mode & RT_SPI_CPHA)
  110. {
  111. set_input_cfg->cpha = FSPIM_CPHA_2_EDGE;
  112. }
  113. else
  114. {
  115. set_input_cfg->cpha = FSPIM_CPHA_1_EDGE;
  116. }
  117. if (configuration->data_width == 8)
  118. {
  119. set_input_cfg->n_bytes = FSPIM_1_BYTE;
  120. }
  121. else if (configuration->data_width == 16)
  122. {
  123. set_input_cfg->n_bytes = FSPIM_2_BYTE;
  124. }
  125. /* send spi_cfg to RT-Thread sys */
  126. ret = FSpimCfgInitialize(&user_data_cfg->spim_instance, &input_cfg);
  127. if (FSPIM_SUCCESS != ret)
  128. return RT_ERROR;
  129. /* irq setting */
  130. ret = FSpimSetupInterrupt(&user_data_cfg->spim_instance);
  131. if (FSPIM_SUCCESS != ret)
  132. return RT_ERROR;
  133. FSpimRegisterIntrruptHandler(&user_data_cfg->spim_instance, FSPIM_INTR_EVT_RX_DONE, rt_ft_send_event_done, NULL);
  134. return ret;
  135. }
  136. static rt_uint32_t spim_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  137. {
  138. RT_ASSERT(device != RT_NULL);
  139. RT_ASSERT(device->parent.user_data != RT_NULL);
  140. RT_ASSERT(message != RT_NULL);
  141. rt_size_t message_length;
  142. rt_uint8_t *recv_buf;
  143. const rt_uint8_t *send_buf;
  144. /* recv spi_cfg from RT-Thread sys */
  145. struct drv_spi *user_data_xfer = device->parent.user_data;
  146. FSpim *xfer_spim_instance = &user_data_xfer->spim_instance;
  147. FError tx_rx_result = FSPIM_SUCCESS;
  148. message_length = message->length;
  149. recv_buf = message->recv_buf;
  150. send_buf = message->send_buf;
  151. if (message->cs_take)
  152. {
  153. FSpimSetChipSelection(xfer_spim_instance, TRUE);
  154. }
  155. if (message_length > 0)
  156. {
  157. if (send_buf == RT_NULL && recv_buf != RT_NULL)
  158. {
  159. /* receive message */
  160. tx_rx_result = FSpimTransferByInterrupt(xfer_spim_instance, RT_NULL, recv_buf, message_length);
  161. }
  162. else if (send_buf != RT_NULL && recv_buf == RT_NULL)
  163. {
  164. /* send message */
  165. tx_rx_result = FSpimTransferByInterrupt(xfer_spim_instance, send_buf, RT_NULL, message_length);
  166. }
  167. else if (send_buf != RT_NULL && recv_buf != RT_NULL)
  168. {
  169. /* not supported yet */
  170. rt_kprintf("Do not support the situation that send_buf and recv_buf both not equal to 0.");
  171. }
  172. }
  173. if (FSPIM_SUCCESS != tx_rx_result)
  174. {
  175. rt_kprintf("FSpimTransferByInterrupt() fail!!!");
  176. message_length = 0;
  177. }
  178. if (rt_event_recv(&rx_done_event, (EVENT_RX_DONE),
  179. (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR),
  180. RT_WAITING_FOREVER, RT_NULL) != RT_EOK)
  181. {
  182. rt_kprintf("Wait rx timeout!!!\n");
  183. message_length = 0;
  184. }
  185. if (message->cs_release)
  186. {
  187. FSpimSetChipSelection(xfer_spim_instance, FALSE);
  188. }
  189. return message_length;
  190. }
  191. int ft_spi_init(void)
  192. {
  193. rt_err_t result;
  194. static struct rt_spi_bus spim_bus;
  195. /* event creat */
  196. if (RT_EOK != rt_event_init(&rx_done_event, "rx_done_event", RT_IPC_FLAG_FIFO))
  197. {
  198. rt_kprintf("Create event failed.\n");
  199. return RT_ERROR;
  200. }
  201. /* spi bus init */
  202. result = rt_spi_bus_register(&spim_bus, "spi0", &spim_ops);
  203. RT_ASSERT((struct rt_spi_device *)rt_device_find("spi0"));
  204. rt_kprintf("Spi bus spi0 init\n");
  205. /* spi device init and attach to bus */
  206. #ifdef RT_USING_SPIM0
  207. _RTSpim0.spi_id = FSPI0_ID;
  208. result = rt_spi_bus_attach_device(&_RTSpim0.device, "spi00", "spi0", &_RTSpim0);
  209. spi_device = (struct rt_spi_device *)rt_device_find("spi00");
  210. if (RT_NULL == spi_device)
  211. {
  212. rt_kprintf("Spi init failed -> can't find spi00 device!\n");
  213. return RT_ERROR;
  214. }
  215. rt_kprintf("Spi master device spi00 init.\n");
  216. #endif
  217. #ifdef RT_USING_SPIM1
  218. _RTSpim1.spi_id = FSPI1_ID;
  219. result = rt_spi_bus_attach_device(&_RTSpim1.device, "spi01", "spi0", &_RTSpim1);
  220. spi_device = (struct rt_spi_device *)rt_device_find("spi01");
  221. if (RT_NULL == spi_device)
  222. {
  223. rt_kprintf("Spi init failed -> can't find spi01 device!\n");
  224. return RT_ERROR;
  225. }
  226. rt_kprintf("Spi master device spi01 init.\n");
  227. #endif
  228. #ifdef RT_USING_SPIM2
  229. _RTSpim2.spi_id = FSPI2_ID;
  230. result = rt_spi_bus_attach_device(&_RTSpim2.device, "spi02", "spi0", &_RTSpim2);
  231. spi_device = (struct rt_spi_device *)rt_device_find("spi02");
  232. if (RT_NULL == spi_device)
  233. {
  234. rt_kprintf("Spi init failed -> can't find spi02 device!\n");
  235. return RT_ERROR;
  236. }
  237. rt_kprintf("Spi master device spi02 init.\n");
  238. #endif
  239. #ifdef RT_USING_SPIM3
  240. _RTSpim3.spi_id = FSPI3_ID;
  241. result = rt_spi_bus_attach_device(&_RTSpim3.device, "spi03", "spi0", &_RTSpim3);
  242. spi_device = (struct rt_spi_device *)rt_device_find("spi03");
  243. if (RT_NULL == spi_device)
  244. {
  245. rt_kprintf("Spi init failed -> can't find spi03 device!\n");
  246. return RT_ERROR;
  247. }
  248. rt_kprintf("Spi master device spi03 init.\n");
  249. #endif
  250. return result;
  251. }
  252. INIT_DEVICE_EXPORT(ft_spi_init);
  253. /* spi test example */
  254. static void fspim_test_sample(int argc, char *argv[])
  255. {
  256. rt_uint8_t send_to_flash_id = 0x9f; /* Flash cmd */
  257. rt_uint8_t recv_from_falsh_id1[5] = {0};
  258. rt_uint8_t recv_from_falsh_id2[5] = {0};
  259. /* find the spi device to get the device handle */
  260. spi_device = (struct rt_spi_device *)rt_device_find("spi02");
  261. if (!spi_device)
  262. {
  263. rt_kprintf("fspim_test_sample run failed! can't find spi02 device!\n");
  264. }
  265. else
  266. {
  267. static struct rt_spi_message msg1, msg2;
  268. msg1.send_buf = &send_to_flash_id;
  269. msg1.recv_buf = RT_NULL;
  270. msg1.length = 1;
  271. msg1.cs_take = 1;
  272. msg1.cs_release = 0;
  273. msg1.next = &msg2;
  274. msg2.send_buf = RT_NULL;
  275. msg2.recv_buf = recv_from_falsh_id2;
  276. msg2.length = 5;
  277. msg2.cs_take = 0;
  278. msg2.cs_release = 1;
  279. msg2.next = RT_NULL;
  280. /* send the command to read the ID using rt_spi_send_then_recv() */
  281. rt_spi_send_then_recv(spi_device, &send_to_flash_id, 1, recv_from_falsh_id1, 5);
  282. rt_kprintf("use rt_spi_send_then_recv() read flash ID is:0x%x 0x%x 0x%x 0x%x 0x%x\n", recv_from_falsh_id1[0], recv_from_falsh_id1[1], recv_from_falsh_id1[2], recv_from_falsh_id1[3], recv_from_falsh_id1[4]);
  283. /* send the command to read the ID using rt_spi_transfer_message() */
  284. rt_spi_transfer_message(spi_device, &msg1);
  285. rt_kprintf("use rt_spi_transfer_message() read flash ID is:0x%x 0x%x 0x%x 0x%x 0x%x\n", recv_from_falsh_id2[0], recv_from_falsh_id2[1], recv_from_falsh_id2[2], recv_from_falsh_id2[3], recv_from_falsh_id2[4]);
  286. }
  287. }
  288. MSH_CMD_EXPORT(fspim_test_sample, "fspim test sample");
  289. #endif