drv_spi_msg.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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_msg_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_msg.h"
  30. #include "fspim_msg_hw.h" /* include low-level header file for internal probe */
  31. #include "drv_spi_msg.h"
  32. /************************** Constant Definitions *****************************/
  33. /**************************** Type Definitions *******************************/
  34. /************************** Variable Definitions *****************************/
  35. typedef struct
  36. {
  37. struct rt_spi_bus spi_bus;
  38. FSpiMsgCtrl spim_msg_instance;
  39. const char *name;
  40. } phytium_spi_bus;
  41. /***************** Macros (Inline Functions) Definitions *********************/
  42. #define EVENT_RX_DONE (1 << 1)
  43. /*******************************Api Functions*********************************/
  44. static rt_err_t spim_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
  45. static rt_ssize_t spim_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
  46. static const struct rt_spi_ops spim_ops =
  47. {
  48. .configure = spim_configure,
  49. .xfer = spim_xfer
  50. };
  51. static rt_err_t spim_configure(struct rt_spi_device *device,
  52. struct rt_spi_configuration *configuration)
  53. {
  54. FError ret = 0;
  55. RT_ASSERT(device != RT_NULL);
  56. RT_ASSERT(configuration != RT_NULL);
  57. phytium_spi_bus *user_data_cfg = device->parent.user_data;
  58. FSpiMsgConfig *set_input_cfg = &user_data_cfg->spim_msg_instance.spi_msg_config;
  59. /* set fspim device according to configuration */
  60. /* Modifying the CPOL and CPHA parameters requires support from relevant documentation*/
  61. if (configuration->data_width == 8)
  62. {
  63. set_input_cfg->n_bytes = FSPIM_1_BYTE;
  64. }
  65. /* send spi_cfg to RT-Thread sys */
  66. ret = FSpiMsgCfgInitialize(&user_data_cfg->spim_msg_instance, set_input_cfg);
  67. if (0 != ret)
  68. {
  69. return -RT_ERROR;
  70. }
  71. return ret;
  72. }
  73. static rt_ssize_t spim_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  74. {
  75. RT_ASSERT(device != RT_NULL);
  76. RT_ASSERT(device->parent.user_data != RT_NULL);
  77. RT_ASSERT(message != RT_NULL);
  78. rt_ssize_t message_length;
  79. rt_uint8_t *recv_buf;
  80. const rt_uint8_t *send_buf;
  81. /* recv spi_cfg from RT-Thread sys */
  82. phytium_spi_bus *user_data_xfer = device->parent.user_data;
  83. FSpiMsgCtrl *xfer_spim_msg_instance = &user_data_xfer->spim_msg_instance;
  84. FError tx_rx_result = 0;
  85. message_length = message->length;
  86. recv_buf = message->recv_buf;
  87. send_buf = message->send_buf;
  88. if (message->cs_take)
  89. {
  90. FSpiMsgSetChipSelection(xfer_spim_msg_instance, 1);
  91. }
  92. if (message_length > 0)
  93. {
  94. if (send_buf == RT_NULL && recv_buf != RT_NULL)
  95. {
  96. /* receive message */
  97. tx_rx_result = FSpiMsgTransfer(xfer_spim_msg_instance, RT_NULL, recv_buf, message_length);
  98. }
  99. else if (send_buf != RT_NULL && recv_buf == RT_NULL)
  100. {
  101. /* send message */
  102. tx_rx_result = FSpiMsgTransfer(xfer_spim_msg_instance, send_buf, RT_NULL, message_length);
  103. }
  104. else if (send_buf != RT_NULL && recv_buf != RT_NULL)
  105. {
  106. /* send and recv */
  107. tx_rx_result = FSpiMsgTransfer(xfer_spim_msg_instance, send_buf, recv_buf, message_length);
  108. }
  109. }
  110. if (0 != tx_rx_result)
  111. {
  112. rt_kprintf("FSpimTransferByInterrupt() fail!!!");
  113. message_length = 0;
  114. }
  115. if (message->cs_release)
  116. {
  117. FSpiMsgSetChipSelection(xfer_spim_msg_instance, 0);
  118. }
  119. return message_length;
  120. }
  121. static void FSpiMsgIntrInit(FSpiMsgCtrl *ctrl, const FSpiMsgConfig *config)
  122. {
  123. rt_uint32_t cpu_id = rt_hw_cpu_id();
  124. rt_hw_interrupt_set_target_cpus(config->irq_num, cpu_id);
  125. rt_hw_interrupt_set_priority(config->irq_num, config->irq_priority);
  126. ctrl->cmd_completion = CMD_MSG_NOT_COMPLETION;
  127. rt_hw_interrupt_install(config->irq_num, FSpiMsgInterruptHandler, ctrl, NULL);
  128. rt_hw_interrupt_umask(config->irq_num);
  129. }
  130. static int spi_init(phytium_spi_bus *spi_bus)
  131. {
  132. FError ret = 0;
  133. FSpiMsgConfig input_cfg = *FSpiMsgLookupConfig(spi_bus->spim_msg_instance.spi_msg_config.instance_id);
  134. #ifdef RT_USING_SMART
  135. input_cfg.spi_msg.regfile = (uintptr)rt_ioremap((void *)input_cfg.spi_msg.regfile, 0x1000);
  136. input_cfg.spi_msg.shmem = (uintptr)rt_ioremap((void *)input_cfg.spi_msg.shmem, 0x1000);
  137. #endif
  138. FSpiMsgIntrInit(&spi_bus->spim_msg_instance, &input_cfg);
  139. /* send spi_cfg to RT-Thread sys */
  140. ret = FSpiMsgCfgInitialize(&spi_bus->spim_msg_instance, &input_cfg);
  141. if (0 != ret)
  142. {
  143. return -RT_ERROR;
  144. }
  145. rt_spi_bus_register(&spi_bus->spi_bus, spi_bus->name, &spim_ops);
  146. RT_ASSERT((struct rt_spi_device *)rt_device_find(spi_bus->name));
  147. return 0;
  148. }
  149. #ifdef RT_USING_SPIM0_MSG
  150. static phytium_spi_bus spi0_bus;
  151. #endif
  152. #ifdef RT_USING_SPIM1_MSG
  153. static phytium_spi_bus spi1_bus;
  154. #endif
  155. #ifdef RT_USING_SPIM2_MSG
  156. static phytium_spi_bus spi2_bus;
  157. #endif
  158. #ifdef RT_USING_SPIM3_MSG
  159. static phytium_spi_bus spi3_bus;
  160. #endif
  161. int rt_hw_spi_init(void)
  162. {
  163. #ifdef RT_USING_SPIM0_MSG
  164. spi0_bus.name = "SPI0";
  165. spi0_bus.spim_msg_instance.spi_msg_config.instance_id = FSPI0_MSG_ID;
  166. FIOPadSetSpimMux(FSPI0_MSG_ID);
  167. spi_init(&spi0_bus);
  168. #endif
  169. #ifdef RT_USING_SPIM1_MSG
  170. spi1_bus.name = "SPI1";
  171. spi1_bus.spim_msg_instance.spi_msg_config.instance_id = FSPI1_MSG_ID;
  172. FIOPadSetSpimMux(FSPI1_MSG_ID);
  173. spi_init(&spi1_bus);
  174. #endif
  175. return 0;
  176. }
  177. INIT_DEVICE_EXPORT(rt_hw_spi_init);