drv_qspi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2022-3-15 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_QSPI)
  14. #define LOG_TAG "drv.qspi"
  15. #define DBG_ENABLE
  16. #define DBG_SECTION_NAME LOG_TAG
  17. #define DBG_LEVEL DBG_INFO
  18. #define DBG_COLOR
  19. #include <rtdbg.h>
  20. #include <rthw.h>
  21. #include <rtdef.h>
  22. #include <drv_spi.h>
  23. /* Private define ---------------------------------------------------------------*/
  24. enum
  25. {
  26. QSPI_START = -1,
  27. #if defined(BSP_USING_QSPI0)
  28. QSPI0_IDX,
  29. #endif
  30. #if defined(BSP_USING_QSPI1)
  31. QSPI1_IDX,
  32. #endif
  33. QSPI_CNT
  34. };
  35. /* Private typedef --------------------------------------------------------------*/
  36. /* Private functions ------------------------------------------------------------*/
  37. static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
  38. static rt_ssize_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message);
  39. static int nu_qspi_register_bus(struct nu_spi *qspi_bus, const char *name);
  40. /* Public functions -------------------------------------------------------------*/
  41. /* Private variables ------------------------------------------------------------*/
  42. static struct rt_spi_ops nu_qspi_poll_ops =
  43. {
  44. .configure = nu_qspi_bus_configure,
  45. .xfer = nu_qspi_bus_xfer,
  46. };
  47. static struct nu_spi nu_qspi_arr [] =
  48. {
  49. #if defined(BSP_USING_QSPI0)
  50. {
  51. .name = "qspi0",
  52. .spi_base = (SPI_T *)QSPI0,
  53. .rstidx = QSPI0_RST,
  54. #if defined(BSP_USING_SPI_PDMA)
  55. #if defined(BSP_USING_QSPI0_PDMA)
  56. .pdma_perp_tx = PDMA_QSPI0_TX,
  57. .pdma_perp_rx = PDMA_QSPI0_RX,
  58. #else
  59. .pdma_perp_tx = NU_PDMA_UNUSED,
  60. .pdma_perp_rx = NU_PDMA_UNUSED,
  61. #endif
  62. #endif
  63. },
  64. #endif
  65. #if defined(BSP_USING_QSPI1)
  66. {
  67. .name = "qspi1",
  68. .spi_base = (SPI_T *)QSPI1,
  69. .rstidx = QSPI1_RST,
  70. #if defined(BSP_USING_SPI_PDMA)
  71. #if defined(BSP_USING_QSPI1_PDMA)
  72. .pdma_perp_tx = PDMA_QSPI1_TX,
  73. .pdma_perp_rx = PDMA_QSPI1_RX,
  74. #else
  75. .pdma_perp_tx = NU_PDMA_UNUSED,
  76. .pdma_perp_rx = NU_PDMA_UNUSED,
  77. #endif
  78. #endif
  79. },
  80. #endif
  81. }; /* qspi nu_qspi */
  82. static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device,
  83. struct rt_spi_configuration *configuration)
  84. {
  85. struct nu_spi *spi_bus;
  86. rt_uint32_t u32SPIMode;
  87. rt_uint32_t u32BusClock;
  88. rt_err_t ret = RT_EOK;
  89. RT_ASSERT(device != RT_NULL);
  90. RT_ASSERT(configuration != RT_NULL);
  91. spi_bus = (struct nu_spi *) device->bus;
  92. /* Check mode */
  93. switch (configuration->mode & RT_SPI_MODE_3)
  94. {
  95. case RT_SPI_MODE_0:
  96. u32SPIMode = SPI_MODE_0;
  97. break;
  98. case RT_SPI_MODE_1:
  99. u32SPIMode = SPI_MODE_1;
  100. break;
  101. case RT_SPI_MODE_2:
  102. u32SPIMode = SPI_MODE_2;
  103. break;
  104. case RT_SPI_MODE_3:
  105. u32SPIMode = SPI_MODE_3;
  106. break;
  107. default:
  108. ret = -RT_EIO;
  109. goto exit_nu_qspi_bus_configure;
  110. }
  111. /* Check data width */
  112. if (!(configuration->data_width == 8 ||
  113. configuration->data_width == 16 ||
  114. configuration->data_width == 24 ||
  115. configuration->data_width == 32))
  116. {
  117. ret = -RT_EINVAL;
  118. goto exit_nu_qspi_bus_configure;
  119. }
  120. /* Try to set clock and get actual spi bus clock */
  121. u32BusClock = QSPI_SetBusClock((QSPI_T *)spi_bus->spi_base, configuration->max_hz);
  122. if (configuration->max_hz > u32BusClock)
  123. {
  124. LOG_W("%s clock max frequency is %dHz (!= %dHz)\n", spi_bus->name, u32BusClock, configuration->max_hz);
  125. configuration->max_hz = u32BusClock;
  126. }
  127. /* Need to initialize new configuration? */
  128. if (rt_memcmp(configuration, &spi_bus->configuration, sizeof(struct rt_spi_configuration)) != 0)
  129. {
  130. rt_memcpy(&spi_bus->configuration, configuration, sizeof(struct rt_spi_configuration));
  131. QSPI_Open((QSPI_T *)spi_bus->spi_base, SPI_MASTER, u32SPIMode, configuration->data_width, u32BusClock);
  132. if (configuration->mode & RT_SPI_CS_HIGH)
  133. {
  134. /* Set CS pin to LOW */
  135. SPI_SET_SS_LOW(spi_bus->spi_base);
  136. }
  137. else
  138. {
  139. /* Set CS pin to HIGH */
  140. SPI_SET_SS_HIGH(spi_bus->spi_base);
  141. }
  142. if (configuration->mode & RT_SPI_MSB)
  143. {
  144. /* Set sequence to MSB first */
  145. SPI_SET_MSB_FIRST(spi_bus->spi_base);
  146. }
  147. else
  148. {
  149. /* Set sequence to LSB first */
  150. SPI_SET_LSB_FIRST(spi_bus->spi_base);
  151. }
  152. }
  153. /* Clear SPI RX FIFO */
  154. nu_spi_drain_rxfifo(spi_bus->spi_base);
  155. exit_nu_qspi_bus_configure:
  156. return -(ret);
  157. }
  158. static int nu_qspi_mode_config(struct nu_spi *qspi_bus, rt_uint8_t *tx, rt_uint8_t *rx, int qspi_lines)
  159. {
  160. QSPI_T *qspi_base = (QSPI_T *)qspi_bus->spi_base;
  161. #if defined(RT_SFUD_USING_QSPI)
  162. if (qspi_lines > 1)
  163. {
  164. if (tx)
  165. {
  166. switch (qspi_lines)
  167. {
  168. case 2:
  169. QSPI_ENABLE_DUAL_OUTPUT_MODE(qspi_base);
  170. break;
  171. case 4:
  172. QSPI_ENABLE_QUAD_OUTPUT_MODE(qspi_base);
  173. break;
  174. default:
  175. LOG_E("Data line is not supported.\n");
  176. break;
  177. }
  178. }
  179. else
  180. {
  181. switch (qspi_lines)
  182. {
  183. case 2:
  184. QSPI_ENABLE_DUAL_INPUT_MODE(qspi_base);
  185. break;
  186. case 4:
  187. QSPI_ENABLE_QUAD_INPUT_MODE(qspi_base);
  188. break;
  189. default:
  190. LOG_E("Data line is not supported.\n");
  191. break;
  192. }
  193. }
  194. }
  195. else
  196. #endif
  197. {
  198. QSPI_DISABLE_DUAL_MODE(qspi_base);
  199. QSPI_DISABLE_QUAD_MODE(qspi_base);
  200. }
  201. return qspi_lines;
  202. }
  203. static rt_ssize_t nu_qspi_bus_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  204. {
  205. struct nu_spi *qspi_bus;
  206. struct rt_qspi_configuration *qspi_configuration;
  207. struct rt_qspi_message *qspi_message;
  208. rt_uint8_t u8last = 1;
  209. rt_uint8_t bytes_per_word;
  210. QSPI_T *qspi_base;
  211. rt_ssize_t u32len = 0;
  212. RT_ASSERT(device != RT_NULL);
  213. RT_ASSERT(message != RT_NULL);
  214. qspi_bus = (struct nu_spi *) device->bus;
  215. qspi_base = (QSPI_T *)qspi_bus->spi_base;
  216. qspi_configuration = &qspi_bus->configuration;
  217. bytes_per_word = qspi_configuration->parent.data_width / 8;
  218. if (message->cs_take && !(qspi_configuration->parent.mode & RT_SPI_NO_CS))
  219. {
  220. if (qspi_configuration->parent.mode & RT_SPI_CS_HIGH)
  221. {
  222. QSPI_SET_SS_HIGH(qspi_base);
  223. }
  224. else
  225. {
  226. QSPI_SET_SS_LOW(qspi_base);
  227. }
  228. }
  229. qspi_message = (struct rt_qspi_message *)message;
  230. /* Command + Address + Dummy + Data */
  231. /* Command stage */
  232. if (qspi_message->instruction.content != 0)
  233. {
  234. u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) &qspi_message->instruction.content, RT_NULL, qspi_message->instruction.qspi_lines);
  235. nu_spi_transfer((struct nu_spi *)qspi_bus,
  236. (rt_uint8_t *) &qspi_message->instruction.content,
  237. RT_NULL,
  238. 1,
  239. 1);
  240. }
  241. /* Address stage */
  242. if (qspi_message->address.size > 0)
  243. {
  244. rt_uint32_t u32ReversedAddr = 0;
  245. rt_uint32_t u32AddrNumOfByte = qspi_message->address.size / 8;
  246. switch (u32AddrNumOfByte)
  247. {
  248. case 1:
  249. u32ReversedAddr = (qspi_message->address.content & 0xff);
  250. break;
  251. case 2:
  252. nu_set16_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content);
  253. break;
  254. case 3:
  255. nu_set24_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content);
  256. break;
  257. case 4:
  258. nu_set32_be((rt_uint8_t *)&u32ReversedAddr, qspi_message->address.content);
  259. break;
  260. default:
  261. RT_ASSERT(0);
  262. break;
  263. }
  264. u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *)&u32ReversedAddr, RT_NULL, qspi_message->address.qspi_lines);
  265. nu_spi_transfer((struct nu_spi *)qspi_bus,
  266. (rt_uint8_t *) &u32ReversedAddr,
  267. RT_NULL,
  268. u32AddrNumOfByte,
  269. 1);
  270. }
  271. /* alternate_bytes stage */
  272. if ((qspi_message->alternate_bytes.size > 0) && (qspi_message->alternate_bytes.size <= 4))
  273. {
  274. rt_uint32_t u32AlternateByte = 0;
  275. rt_uint32_t u32NumOfByte = qspi_message->alternate_bytes.size / 8;
  276. switch (u32NumOfByte)
  277. {
  278. case 1:
  279. u32AlternateByte = (qspi_message->alternate_bytes.content & 0xff);
  280. break;
  281. case 2:
  282. nu_set16_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content);
  283. break;
  284. case 3:
  285. nu_set24_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content);
  286. break;
  287. case 4:
  288. nu_set32_be((rt_uint8_t *)&u32AlternateByte, qspi_message->alternate_bytes.content);
  289. break;
  290. default:
  291. RT_ASSERT(0);
  292. break;
  293. }
  294. u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *)&u32AlternateByte, RT_NULL, qspi_message->alternate_bytes.qspi_lines);
  295. nu_spi_transfer((struct nu_spi *)qspi_bus,
  296. (rt_uint8_t *) &u32AlternateByte,
  297. RT_NULL,
  298. u32NumOfByte,
  299. 1);
  300. }
  301. /* Dummy_cycles stage */
  302. if (qspi_message->dummy_cycles > 0)
  303. {
  304. qspi_bus->dummy = 0x00;
  305. u8last = nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) &qspi_bus->dummy, RT_NULL, u8last);
  306. nu_spi_transfer((struct nu_spi *)qspi_bus,
  307. (rt_uint8_t *) &qspi_bus->dummy,
  308. RT_NULL,
  309. qspi_message->dummy_cycles / (8 / u8last),
  310. 1);
  311. }
  312. if (message->length > 0)
  313. {
  314. /* Data stage */
  315. nu_qspi_mode_config(qspi_bus, (rt_uint8_t *) message->send_buf, (rt_uint8_t *) message->recv_buf, qspi_message->qspi_data_lines);
  316. nu_spi_transfer((struct nu_spi *)qspi_bus,
  317. (rt_uint8_t *) message->send_buf,
  318. (rt_uint8_t *) message->recv_buf,
  319. message->length,
  320. bytes_per_word);
  321. u32len = message->length;
  322. }
  323. else
  324. {
  325. u32len = 1;
  326. }
  327. if (message->cs_release && !(qspi_configuration->parent.mode & RT_SPI_NO_CS))
  328. {
  329. if (qspi_configuration->parent.mode & RT_SPI_CS_HIGH)
  330. {
  331. QSPI_SET_SS_LOW(qspi_base);
  332. }
  333. else
  334. {
  335. QSPI_SET_SS_HIGH(qspi_base);
  336. }
  337. }
  338. return u32len;
  339. }
  340. static int nu_qspi_register_bus(struct nu_spi *qspi_bus, const char *name)
  341. {
  342. return rt_qspi_bus_register(&qspi_bus->dev, name, &nu_qspi_poll_ops);
  343. }
  344. /**
  345. * Hardware SPI Initial
  346. */
  347. static int rt_hw_qspi_init(void)
  348. {
  349. rt_uint8_t i;
  350. for (i = (QSPI_START + 1); i < QSPI_CNT; i++)
  351. {
  352. SYS_ResetModule(nu_qspi_arr[i].rstidx);
  353. nu_qspi_register_bus(&nu_qspi_arr[i], nu_qspi_arr[i].name);
  354. #if defined(BSP_USING_SPI_PDMA)
  355. nu_qspi_arr[i].pdma_chanid_tx = -1;
  356. nu_qspi_arr[i].pdma_chanid_rx = -1;
  357. #endif
  358. #if defined(BSP_USING_QSPI_PDMA)
  359. if ((nu_qspi_arr[i].pdma_perp_tx != NU_PDMA_UNUSED) && (nu_qspi_arr[i].pdma_perp_rx != NU_PDMA_UNUSED))
  360. {
  361. if (nu_hw_spi_pdma_allocate(&nu_qspi_arr[i]) != RT_EOK)
  362. {
  363. LOG_E("Failed to allocate DMA channels for %s. We will use poll-mode for this bus.\n", nu_qspi_arr[i].name);
  364. }
  365. }
  366. #endif
  367. }
  368. return 0;
  369. }
  370. INIT_DEVICE_EXPORT(rt_hw_qspi_init);
  371. rt_err_t nu_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)())
  372. {
  373. struct rt_qspi_device *qspi_device = RT_NULL;
  374. rt_err_t result = RT_EOK;
  375. RT_ASSERT(bus_name != RT_NULL);
  376. RT_ASSERT(device_name != RT_NULL);
  377. RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
  378. qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
  379. if (qspi_device == RT_NULL)
  380. {
  381. LOG_E("no memory, qspi bus attach device failed!\n");
  382. result = -RT_ENOMEM;
  383. goto __exit;
  384. }
  385. qspi_device->enter_qspi_mode = enter_qspi_mode;
  386. qspi_device->exit_qspi_mode = exit_qspi_mode;
  387. qspi_device->config.qspi_dl_width = data_line_width;
  388. result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, RT_NULL);
  389. __exit:
  390. if (result != RT_EOK)
  391. {
  392. if (qspi_device)
  393. {
  394. rt_free(qspi_device);
  395. }
  396. }
  397. return result;
  398. }
  399. #endif //#if defined(BSP_USING_QSPI)