drv_dw_spi.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * Copyright (c) 2006-2025 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * spi driver for synopsys dw apb spi
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2025-01-03 ZhangJing first version
  11. */
  12. #include <rtconfig.h>
  13. #ifdef BSP_USING_DW_SPI
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include "drv_dw_spi.h"
  17. #include <rtdbg.h>
  18. #include <io.h>
  19. #ifdef RT_USING_SMART
  20. #include <ioremap.h>
  21. #endif
  22. #define SPI0_BUS_NAME "spi0"
  23. #define SPI0_BUS_DEVICE0_NAME "spi00"
  24. static struct dw_spi dw_spi_device =
  25. {
  26. .device_name = "spi0",
  27. .irq = DW_SPI_IRQ_BASE,
  28. .max_freq = DW_SPI_MAX_FREQ,
  29. .bits_per_word = 8,
  30. .cs = 0,
  31. .fifo_len = 0,
  32. .type = DW_SPI_CTRLR0_FRF_MOT,
  33. };
  34. static rt_uint32_t update_control_reg_16(struct dw_spi *dw_spi_dev)
  35. {
  36. return ((dw_spi_dev->bits_per_word - 1) << CTRLR0_DFS_SHIFT) |
  37. (dw_spi_dev->type << DW_SPI_CTRLR0_FRF_SHIFT) |
  38. (dw_spi_dev->mode << DW_SPI_CTRLR0_MODE_SHIFT) |
  39. (dw_spi_dev->tmode << DW_SPI_CTRLR0_TMOD_SHIFT);
  40. }
  41. static rt_uint32_t update_control_reg_32(struct dw_spi *dw_spi_dev)
  42. {
  43. return ((dw_spi_dev->bits_per_word - 1) << CTRLR0_DFS_32_SHIFT) |
  44. (dw_spi_dev->type << DW_SPI_CTRLR0_FRF_SHIFT) |
  45. (dw_spi_dev->mode << DW_SPI_CTRLR0_MODE_SHIFT) |
  46. (dw_spi_dev->tmode << DW_SPI_CTRLR0_TMOD_SHIFT);
  47. }
  48. static rt_err_t _dw_drv_spi_configure(struct rt_spi_device *device,
  49. struct rt_spi_configuration *config)
  50. {
  51. struct dw_spi *dw_spi_dev = (struct dw_spi *)(device->bus->parent.user_data);
  52. if (!dw_spi_dev)
  53. {
  54. LOG_E("SPI device is null");
  55. return -RT_ERROR;
  56. }
  57. struct dw_spi_regs *regs = dw_spi_dev->reg;
  58. writel(0, &regs->ssienr);
  59. writel(0, &regs->ser);
  60. writel(0, &regs->imr);
  61. writel(0, &regs->dmacr);
  62. rt_uint32_t ctrl = 0;
  63. switch (config->mode & (RT_SPI_CPHA | RT_SPI_CPOL))
  64. {
  65. case RT_SPI_MODE_0:
  66. ctrl |= 0;
  67. break;
  68. case RT_SPI_MODE_1:
  69. ctrl |= DW_SPI_CTRLR0_SCPH;
  70. break;
  71. case RT_SPI_MODE_2:
  72. ctrl |= DW_SPI_CTRLR0_SCPOL;
  73. break;
  74. case RT_SPI_MODE_3:
  75. ctrl |= DW_SPI_CTRLR0_SCPH | DW_SPI_CTRLR0_SCPOL;
  76. break;
  77. }
  78. dw_spi_dev->mode = ctrl;
  79. /* div = dw_spi_dev->max_freq / configuration->max_hz;*/
  80. rt_uint32_t div = 0;
  81. div = dw_spi_dev->max_freq / 15625000;
  82. if (div % 2)
  83. div++;
  84. /* TODO: */
  85. /* write clock divider register */
  86. writel(div, &regs->baudr);
  87. /* write TX threshold register */
  88. writel(0, &regs->txflr);
  89. /* write RX threshold register */
  90. writel(0, &regs->rxflr);
  91. /* enable spi */
  92. writel(1, &regs->ssienr);
  93. return RT_EOK;
  94. }
  95. static rt_uint32_t min3(rt_uint32_t a, rt_uint32_t b, rt_uint32_t c)
  96. {
  97. return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
  98. }
  99. static inline rt_uint32_t tx_max(struct dw_spi *dw_spi_dev)
  100. {
  101. rt_uint32_t tx_left, tx_room, rxtx_gap;
  102. struct dw_spi_regs *regs = dw_spi_dev->reg;
  103. tx_left = dw_spi_dev->tx_len;
  104. tx_room = dw_spi_dev->fifo_len - (rt_uint32_t)(readl(&regs->txflr));
  105. /*
  106. * Another concern is about the tx/rx mismatch, we
  107. * thought about using (priv->fifo_len - rxflr - txflr) as
  108. * one maximum value for tx, but it doesn't cover the
  109. * data which is out of tx/rx fifo and inside the
  110. * shift registers. So a control from sw point of
  111. * view is taken.
  112. */
  113. if (dw_spi_dev->rx != NULL && dw_spi_dev->tx != NULL)
  114. {
  115. rxtx_gap = dw_spi_dev->fifo_len - (dw_spi_dev->rx_len - dw_spi_dev->tx_len);
  116. return min3(tx_left, tx_room, (rt_uint32_t)(rxtx_gap));
  117. }
  118. else
  119. {
  120. return tx_left < tx_room ? tx_left : tx_room;
  121. }
  122. }
  123. static inline rt_uint32_t rx_max(struct dw_spi *dw_spi_dev)
  124. {
  125. rt_uint32_t rx_left = dw_spi_dev->rx_len;
  126. struct dw_spi_regs *regs = dw_spi_dev->reg;
  127. rt_uint32_t val = readl(&regs->rxflr);
  128. return (rx_left < val) ? rx_left : val;
  129. }
  130. /* write data to spi */
  131. static void dw_spi_writer(struct dw_spi *dw_spi_dev)
  132. {
  133. rt_uint32_t max = tx_max(dw_spi_dev);
  134. rt_uint32_t txw = 0xFF;
  135. struct dw_spi_regs *regs = dw_spi_dev->reg;
  136. while (max--)
  137. {
  138. /* Set the tx word if the transfer's original "tx" is not null */
  139. if (dw_spi_dev->tx)
  140. {
  141. if (dw_spi_dev->bits_per_word == 8)
  142. txw = *(rt_uint8_t *)(dw_spi_dev->tx);
  143. else
  144. txw = *(rt_uint16_t *)(dw_spi_dev->tx);
  145. dw_spi_dev->tx += dw_spi_dev->bits_per_word >> 3;
  146. }
  147. writel(txw, &regs->dr);
  148. dw_spi_dev->tx_len--;
  149. }
  150. }
  151. /* read data from spi */
  152. static void dw_spi_reader(struct dw_spi *dw_spi_dev)
  153. {
  154. struct dw_spi_regs *regs = dw_spi_dev->reg;
  155. rt_uint32_t max = rx_max(dw_spi_dev);
  156. rt_uint16_t rxw;
  157. while (max--)
  158. {
  159. rxw = readl(&regs->dr);
  160. if (dw_spi_dev->rx)
  161. {
  162. if (dw_spi_dev->bits_per_word == 8)
  163. *(rt_uint8_t *)(dw_spi_dev->rx) = rxw;
  164. else
  165. *(rt_uint16_t *)(dw_spi_dev->rx) = rxw;
  166. dw_spi_dev->rx += dw_spi_dev->bits_per_word >> 3;
  167. }
  168. dw_spi_dev->rx_len--;
  169. }
  170. }
  171. static void wait_for_idle(struct dw_spi *dw_spi_dev)
  172. {
  173. rt_uint32_t status;
  174. struct dw_spi_regs *regs = dw_spi_dev->reg;
  175. while (1)
  176. {
  177. status = readl(&regs->sr);
  178. if (!(status & DW_SPI_SR_BUSY))
  179. {
  180. if (status & DW_SPI_SR_TX_EMPTY)
  181. {
  182. break;
  183. }
  184. }
  185. rt_thread_yield();
  186. }
  187. }
  188. static int dw_spi_poll_transfer(struct dw_spi *dw_spi_dev)
  189. {
  190. do
  191. {
  192. dw_spi_writer(dw_spi_dev);
  193. wait_for_idle(dw_spi_dev);
  194. dw_spi_reader(dw_spi_dev);
  195. }
  196. while (dw_spi_dev->rx_len && dw_spi_dev->tx_len);
  197. return 0;
  198. }
  199. static rt_ssize_t _dw_spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
  200. {
  201. struct dw_spi *dw_spi_dev = (struct dw_spi *)(device->bus->parent.user_data);
  202. if (!dw_spi_dev)
  203. {
  204. LOG_E("SPI device is null");
  205. return -RT_ERROR;
  206. }
  207. dw_spi_dev->tx = (void *)message->send_buf;
  208. dw_spi_dev->tx_end = dw_spi_dev->tx + dw_spi_dev->tx_len;
  209. dw_spi_dev->rx = (void *)message->recv_buf;
  210. dw_spi_dev->rx_end = dw_spi_dev->rx + dw_spi_dev->rx_len;
  211. dw_spi_dev->tx_len = message->length;
  212. dw_spi_dev->rx_len = message->length;
  213. if (dw_spi_dev->tx && dw_spi_dev->rx)
  214. {
  215. /* set mode to Tx & Rx */
  216. dw_spi_dev->tmode = DW_SPI_CTRLR0_TMOD_TX_RX;
  217. }
  218. else if (dw_spi_dev->rx)
  219. {
  220. /* set mode to Rx only */
  221. dw_spi_dev->tmode = DW_SPI_CTRLR0_TMOD_RX;
  222. }
  223. else
  224. {
  225. /* set mode to Tx only */
  226. dw_spi_dev->tmode = DW_SPI_CTRLR0_TMOD_TX;
  227. }
  228. struct dw_spi_regs *regs = dw_spi_dev->reg;
  229. /* disable spi */
  230. writel(0, &regs->ssienr);
  231. LOG_D("dw_spixfer:tx 0x%x rx 0x%x len %d\n", dw_spi_dev->tx, dw_spi_dev->rx, message->length);
  232. rt_uint32_t cr0 = dw_spi_dev->update_cr0(dw_spi_dev);
  233. /* write control register */
  234. if (cr0 != readl(&regs->ctrl0))
  235. {
  236. writel(cr0, &regs->ctrl0);
  237. }
  238. /* set slave select */
  239. writel(1 << (dw_spi_dev->cs), &regs->ser);
  240. /* enable spi */
  241. writel(1, &regs->ssienr);
  242. /* transfer data */
  243. dw_spi_poll_transfer(dw_spi_dev);
  244. /* wait for transfer complete */
  245. wait_for_idle(dw_spi_dev);
  246. return message->length;
  247. }
  248. const static struct rt_spi_ops dw_drv_spi_ops =
  249. {
  250. _dw_drv_spi_configure,
  251. _dw_spixfer,
  252. };
  253. static int dw_spi_hw_init(struct dw_spi *dw_spi_dev)
  254. {
  255. struct dw_spi_regs *regs = dw_spi_dev->reg;
  256. /* disable spi */
  257. writel(0, &regs->ssienr);
  258. /* disbale all interrupts */
  259. writel(0, &regs->imr);
  260. /* read and clear interrupt status */
  261. readl(&regs->icr);
  262. /* set slave select */
  263. writel(0, &regs->ser);
  264. /* enable spi */
  265. writel(1, &regs->ssienr);
  266. dw_spi_dev->version = readl(&regs->version);
  267. rt_kprintf("ssi_version_id=%c.%c%c%c\n",
  268. dw_spi_dev->version >> 24, dw_spi_dev->version >> 16,
  269. dw_spi_dev->version >> 8, dw_spi_dev->version);
  270. /* detect the FIFO depth if not set by interface driver */
  271. if (!dw_spi_dev->fifo_len)
  272. {
  273. uint32_t fifo;
  274. for (fifo = 1; fifo < 256; fifo++)
  275. {
  276. writel(fifo, &regs->txftlr);
  277. if (fifo != readl(&regs->txftlr))
  278. {
  279. break;
  280. }
  281. }
  282. dw_spi_dev->fifo_len = (fifo == 1) ? 0 : fifo;
  283. writel(0, &regs->txftlr);
  284. rt_kprintf("fifo length is %d\n", dw_spi_dev->fifo_len);
  285. }
  286. rt_uint32_t cr0, tmp = readl(&regs->ctrl0);
  287. writel(0, &regs->ssienr);
  288. writel(0xffffffff, &regs->ctrl0);
  289. cr0 = readl(&regs->ctrl0);
  290. writel(tmp, &regs->ctrl0);
  291. writel(1, &regs->ssienr);
  292. if (cr0 & DW_SPI_CTRLR0_DFS_MASK)
  293. {
  294. dw_spi_device.update_cr0 = update_control_reg_16;
  295. }
  296. else
  297. {
  298. dw_spi_device.update_cr0 = update_control_reg_32;
  299. }
  300. return 0;
  301. }
  302. int rt_hw_dw_spi_init(void)
  303. {
  304. rt_err_t ret = RT_EOK;
  305. struct dw_spi_regs *reg = NULL;
  306. /* set reg base */
  307. #ifdef RT_USING_SMART
  308. reg = (struct dw_spi_regs *)rt_ioremap((void *)DW_SPI_BASE_ADDR, sizeof(struct dw_spi_regs));
  309. #else
  310. reg = (struct dw_spi_regs *)DW_SPI_BASE_ADDR;
  311. #endif
  312. LOG_D("%s: reg base %p\n", __func__, reg);
  313. if (!reg)
  314. return -RT_ERROR;
  315. dw_spi_device.reg = reg;
  316. dw_spi_device.spi_bus.parent.user_data = &dw_spi_device;
  317. dw_spi_device.tmode = 0; /* Tx & Rx */
  318. dw_spi_device.bits_per_word = 8;
  319. /* init spi */
  320. dw_spi_hw_init(&dw_spi_device);
  321. /* Register SPI bus*/
  322. ret = rt_spi_bus_register(&dw_spi_device.spi_bus, dw_spi_device.device_name, &dw_drv_spi_ops);
  323. if (ret == RT_EOK)
  324. {
  325. static struct rt_spi_device spi_device0;
  326. rt_spi_bus_attach_device(&spi_device0, SPI0_BUS_DEVICE0_NAME, SPI0_BUS_NAME, (void *)&dw_spi_device);
  327. }
  328. return ret;
  329. }
  330. INIT_BOARD_EXPORT(rt_hw_dw_spi_init);
  331. #endif /* BSP_USING_DW_SPI */