drv_spi.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-03-27 Liuguang the first version.
  9. */
  10. #include <rtthread.h>
  11. #ifdef BSP_USING_SPI
  12. #include "drv_spi.h"
  13. #include "fsl_common.h"
  14. #include "fsl_iomuxc.h"
  15. #include "fsl_lpspi.h"
  16. #include "fsl_lpspi_edma.h"
  17. #include "fsl_dmamux.h"
  18. #define LOG_TAG "drv.spi"
  19. #include <drv_log.h>
  20. #if defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
  21. #error "Please don't define 'FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL'!"
  22. #endif
  23. enum
  24. {
  25. #ifdef BSP_USING_SPI1
  26. SPI1_INDEX,
  27. #endif
  28. #ifdef BSP_USING_SPI2
  29. SPI2_INDEX,
  30. #endif
  31. #ifdef BSP_USING_SPI3
  32. SPI3_INDEX,
  33. #endif
  34. #ifdef BSP_USING_SPI4
  35. SPI4_INDEX,
  36. #endif
  37. };
  38. struct imxrt_sw_spi_cs
  39. {
  40. rt_uint32_t pin;
  41. };
  42. struct dma_config
  43. {
  44. lpspi_master_edma_handle_t spi_edma;
  45. edma_handle_t rx_edma;
  46. dma_request_source_t rx_request;
  47. rt_uint8_t rx_channel;
  48. edma_handle_t tx_edma;
  49. dma_request_source_t tx_request;
  50. rt_uint8_t tx_channel;
  51. };
  52. struct imxrt_spi
  53. {
  54. char *bus_name;
  55. LPSPI_Type *base;
  56. struct rt_spi_bus spi_bus;
  57. rt_sem_t xfer_sem;
  58. lpspi_master_handle_t spi_normal;
  59. struct dma_config *dma;
  60. rt_uint8_t dma_flag;
  61. };
  62. static struct imxrt_spi lpspis[] =
  63. {
  64. #ifdef BSP_USING_SPI1
  65. {
  66. .bus_name = "spi1",
  67. .base = LPSPI1,
  68. .dma = RT_NULL,
  69. .dma_flag = RT_FALSE,
  70. },
  71. #endif
  72. #ifdef BSP_USING_SPI2
  73. {
  74. .bus_name = "spi2",
  75. .base = LPSPI2,
  76. .dma = RT_NULL,
  77. .dma_flag = RT_FALSE,
  78. },
  79. #endif
  80. #ifdef BSP_USING_SPI3
  81. {
  82. .bus_name = "spi3",
  83. .base = LPSPI3,
  84. .dma = RT_NULL,
  85. .dma_flag = RT_FALSE,
  86. },
  87. #endif
  88. #ifdef BSP_USING_SPI4
  89. {
  90. .bus_name = "spi4",
  91. .base = LPSPI4,
  92. .dma = RT_NULL,
  93. .dma_flag = RT_FALSE,
  94. },
  95. #endif
  96. };
  97. static void spi_get_dma_config(void)
  98. {
  99. #ifdef BSP_SPI1_USING_DMA
  100. static struct dma_config spi1_dma =
  101. {
  102. .rx_request = kDmaRequestMuxLPSPI1Rx,
  103. .rx_channel = BSP_SPI1_RX_DMA_CHANNEL,
  104. .tx_request = kDmaRequestMuxLPSPI1Tx,
  105. .tx_channel = BSP_SPI1_TX_DMA_CHANNEL,
  106. };
  107. lpspis[SPI1_INDEX].dma = &spi1_dma;
  108. lpspis[SPI1_INDEX].dma_flag = RT_TRUE;
  109. #endif
  110. #ifdef BSP_SPI2_USING_DMA
  111. static struct dma_config spi2_dma =
  112. {
  113. .rx_request = kDmaRequestMuxLPSPI2Rx,
  114. .rx_channel = BSP_SPI2_RX_DMA_CHANNEL,
  115. .tx_request = kDmaRequestMuxLPSPI2Tx,
  116. .tx_channel = BSP_SPI2_TX_DMA_CHANNEL,
  117. };
  118. lpspis[SPI2_INDEX].dma = &spi2_dma;
  119. lpspis[SPI2_INDEX].dma_flag = RT_TRUE;
  120. #endif
  121. #ifdef BSP_SPI3_USING_DMA
  122. static struct dma_config spi3_dma =
  123. {
  124. .rx_request = kDmaRequestMuxLPSPI3Rx,
  125. .rx_channel = BSP_SPI3_RX_DMA_CHANNEL,
  126. .tx_request = kDmaRequestMuxLPSPI3Tx,
  127. .tx_channel = BSP_SPI3_TX_DMA_CHANNEL,
  128. };
  129. lpspis[SPI3_INDEX].dma = &spi3_dma;
  130. lpspis[SPI3_INDEX].dma_flag = RT_TRUE;
  131. #endif
  132. #ifdef BSP_SPI4_USING_DMA
  133. static struct dma_config spi4_dma =
  134. {
  135. .rx_request = kDmaRequestMuxLPSPI4Rx,
  136. .rx_channel = BSP_SPI4_RX_DMA_CHANNEL,
  137. .tx_request = kDmaRequestMuxLPSPI4Tx,
  138. .tx_channel = BSP_SPI4_TX_DMA_CHANNEL,
  139. };
  140. lpspis[SPI4_INDEX].dma = &spi4_dma;
  141. lpspis[SPI4_INDEX].dma_flag = RT_TRUE;
  142. #endif
  143. }
  144. void normal_xfer_callback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData)
  145. {
  146. /* xfer complete callback */
  147. struct imxrt_spi *spi = (struct imxrt_spi *)userData;
  148. rt_sem_release(spi->xfer_sem);
  149. }
  150. void edma_xfer_callback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData)
  151. {
  152. /* xfer complete callback */
  153. struct imxrt_spi *spi = (struct imxrt_spi *)userData;
  154. rt_sem_release(spi->xfer_sem);
  155. }
  156. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
  157. {
  158. rt_err_t ret = RT_EOK;
  159. struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  160. RT_ASSERT(spi_device != RT_NULL);
  161. struct imxrt_sw_spi_cs *cs_pin = (struct imxrt_sw_spi_cs *)rt_malloc(sizeof(struct imxrt_sw_spi_cs));
  162. RT_ASSERT(cs_pin != RT_NULL);
  163. cs_pin->pin = pin;
  164. rt_pin_mode(pin, PIN_MODE_OUTPUT);
  165. rt_pin_write(pin, PIN_HIGH);
  166. ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
  167. return ret;
  168. }
  169. static uint32_t imxrt_get_lpspi_freq(void)
  170. {
  171. uint32_t freq = 0;
  172. /* CLOCK_GetMux(kCLOCK_LpspiMux):
  173. 00b: derive clock from PLL3 PFD1 720M
  174. 01b: derive clock from PLL3 PFD0 720M
  175. 10b: derive clock from PLL2 528M
  176. 11b: derive clock from PLL2 PFD2 396M
  177. */
  178. switch(CLOCK_GetMux(kCLOCK_LpspiMux))
  179. {
  180. case 0:
  181. freq = CLOCK_GetFreq(kCLOCK_Usb1PllPfd1Clk);
  182. break;
  183. case 1:
  184. freq = CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk);
  185. break;
  186. case 2:
  187. freq = CLOCK_GetFreq(kCLOCK_SysPllClk);
  188. break;
  189. case 3:
  190. freq = CLOCK_GetFreq(kCLOCK_SysPllPfd2Clk);
  191. break;
  192. }
  193. freq /= (CLOCK_GetDiv(kCLOCK_LpspiDiv) + 1U);
  194. return freq;
  195. }
  196. static void lpspi_normal_config(struct imxrt_spi *spi)
  197. {
  198. RT_ASSERT(spi != RT_NULL);
  199. LPSPI_MasterTransferCreateHandle(spi->base,
  200. &spi->spi_normal,
  201. normal_xfer_callback,
  202. spi);
  203. LOG_D(LOG_TAG" %s normal config done\n", spi->bus_name);
  204. }
  205. static void lpspi_dma_config(struct imxrt_spi *spi)
  206. {
  207. RT_ASSERT(spi != RT_NULL);
  208. DMAMUX_SetSource(DMAMUX, spi->dma->rx_channel, spi->dma->rx_request);
  209. DMAMUX_EnableChannel(DMAMUX, spi->dma->rx_channel);
  210. EDMA_CreateHandle(&spi->dma->rx_edma, DMA0, spi->dma->rx_channel);
  211. DMAMUX_SetSource(DMAMUX, spi->dma->tx_channel, spi->dma->tx_request);
  212. DMAMUX_EnableChannel(DMAMUX, spi->dma->tx_channel);
  213. EDMA_CreateHandle(&spi->dma->tx_edma, DMA0, spi->dma->tx_channel);
  214. LPSPI_MasterTransferCreateHandleEDMA(spi->base,
  215. &spi->dma->spi_edma,
  216. edma_xfer_callback,
  217. spi,
  218. &spi->dma->rx_edma,
  219. &spi->dma->tx_edma);
  220. LOG_D("%s dma config done\n", spi->bus_name);
  221. }
  222. static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
  223. {
  224. lpspi_master_config_t masterConfig;
  225. struct imxrt_spi *spi = RT_NULL;
  226. RT_ASSERT(cfg != RT_NULL);
  227. RT_ASSERT(device != RT_NULL);
  228. spi = (struct imxrt_spi *)(device->bus->parent.user_data);
  229. RT_ASSERT(spi != RT_NULL);
  230. if(cfg->data_width != 8 && cfg->data_width != 16 && cfg->data_width != 32)
  231. {
  232. return RT_EINVAL;
  233. }
  234. LPSPI_MasterGetDefaultConfig(&masterConfig);
  235. if(cfg->max_hz > 40*1000*1000)
  236. {
  237. cfg->max_hz = 40*1000*1000;
  238. }
  239. masterConfig.baudRate = cfg->max_hz;
  240. masterConfig.bitsPerFrame = cfg->data_width;
  241. if(cfg->mode & RT_SPI_MSB)
  242. {
  243. masterConfig.direction = kLPSPI_MsbFirst;
  244. }
  245. else
  246. {
  247. masterConfig.direction = kLPSPI_LsbFirst;
  248. }
  249. if(cfg->mode & RT_SPI_CPHA)
  250. {
  251. masterConfig.cpha = kLPSPI_ClockPhaseSecondEdge;
  252. }
  253. else
  254. {
  255. masterConfig.cpha = kLPSPI_ClockPhaseFirstEdge;
  256. }
  257. if(cfg->mode & RT_SPI_CPOL)
  258. {
  259. masterConfig.cpol = kLPSPI_ClockPolarityActiveLow;
  260. }
  261. else
  262. {
  263. masterConfig.cpol = kLPSPI_ClockPolarityActiveHigh;
  264. }
  265. masterConfig.pinCfg = kLPSPI_SdiInSdoOut;
  266. masterConfig.dataOutConfig = kLpspiDataOutTristate;
  267. masterConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.baudRate;
  268. masterConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.baudRate;
  269. masterConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.baudRate;
  270. LPSPI_MasterInit(spi->base, &masterConfig, imxrt_get_lpspi_freq());
  271. spi->base->CFGR1 |= LPSPI_CFGR1_PCSCFG_MASK;
  272. return RT_EOK;
  273. }
  274. static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
  275. {
  276. lpspi_transfer_t transfer;
  277. status_t status;
  278. RT_ASSERT(device != RT_NULL);
  279. RT_ASSERT(device->bus != RT_NULL);
  280. RT_ASSERT(device->bus->parent.user_data != RT_NULL);
  281. struct imxrt_spi *spi = (struct imxrt_spi *)(device->bus->parent.user_data);
  282. struct imxrt_sw_spi_cs *cs = device->parent.user_data;
  283. if(message->cs_take)
  284. {
  285. rt_pin_write(cs->pin, PIN_LOW);
  286. }
  287. transfer.dataSize = message->length;
  288. transfer.rxData = (uint8_t *)(message->recv_buf);
  289. transfer.txData = (uint8_t *)(message->send_buf);
  290. if(RT_FALSE == spi->dma_flag)
  291. {
  292. #ifdef BSP_USING_BLOCKING_SPI
  293. status = LPSPI_MasterTransferBlocking(spi->base, &transfer);
  294. #else
  295. status = LPSPI_MasterTransferNonBlocking(spi->base, &spi->spi_normal, &transfer);
  296. #endif
  297. }
  298. else
  299. {
  300. status = LPSPI_MasterTransferEDMA(spi->base,&spi->dma->spi_edma,&transfer);
  301. }
  302. rt_sem_take(spi->xfer_sem, RT_WAITING_FOREVER);
  303. if(message->cs_release)
  304. {
  305. rt_pin_write(cs->pin, PIN_HIGH);
  306. }
  307. if (status != kStatus_Success)
  308. {
  309. LOG_E("%s transfer error : %d", spi->bus_name,status);
  310. message->length = 0;
  311. }
  312. return message->length;
  313. }
  314. static struct rt_spi_ops imxrt_spi_ops =
  315. {
  316. .configure = spi_configure,
  317. .xfer = spixfer
  318. };
  319. int rt_hw_spi_bus_init(void)
  320. {
  321. int i;
  322. rt_err_t ret = RT_EOK;
  323. spi_get_dma_config();
  324. for (i = 0; i < sizeof(lpspis) / sizeof(lpspis[0]); i++)
  325. {
  326. lpspis[i].spi_bus.parent.user_data = &lpspis[i];
  327. ret = rt_spi_bus_register(&lpspis[i].spi_bus, lpspis[i].bus_name, &imxrt_spi_ops);
  328. if(RT_TRUE == lpspis[i].dma_flag)
  329. {
  330. lpspi_dma_config(&lpspis[i]);
  331. }
  332. else
  333. {
  334. lpspi_normal_config(&lpspis[i]);
  335. }
  336. char sem_name[RT_NAME_MAX];
  337. rt_sprintf(sem_name, "%s_s", lpspis[i].bus_name);
  338. lpspis[i].xfer_sem = rt_sem_create(sem_name, 0, RT_IPC_FLAG_PRIO);
  339. }
  340. return ret;
  341. }
  342. INIT_BOARD_EXPORT(rt_hw_spi_bus_init);
  343. #endif /* BSP_USING_SPI */