wm_dma.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /**
  2. * @file wm_dma.c
  3. *
  4. * @brief DMA Driver Module
  5. *
  6. * @author dave
  7. *
  8. * Copyright (c) 2014 Winner Microelectronics Co., Ltd.
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include "wm_dma.h"
  14. #include "wm_regs.h"
  15. #include "wm_irq.h"
  16. #include "wm_osal.h"
  17. #include "core_804.h"
  18. #include "wm_pmu.h"
  19. #define ATTRIBUTE_ISR __attribute__((isr))
  20. static u16 dma_used_bit = 0;
  21. struct tls_dma_channels {
  22. unsigned char channels[8]; /* list of channels */
  23. };
  24. typedef void (*dma_irq_callback)(void *p);
  25. struct dma_irq_context {
  26. u8 flags;
  27. dma_irq_callback burst_done_pf;
  28. void *burst_done_priv;
  29. dma_irq_callback transfer_done_pf;
  30. void *transfer_done_priv;
  31. };
  32. static struct dma_irq_context dma_context[8];
  33. static struct tls_dma_channels channels;
  34. extern void wm_delay_ticks(uint32_t ticks);
  35. extern void tls_irq_priority(u8 vec_no, u32 prio);
  36. static void dma_irq_proc(void *p)
  37. {
  38. unsigned char ch;
  39. unsigned int int_src;
  40. static uint32_t len[8] = {0,0,0,0,0,0,0,0};
  41. ch = (unsigned char)(unsigned long)p;
  42. int_src = tls_reg_read32(HR_DMA_INT_SRC);
  43. if (ch > 3)
  44. {
  45. for (ch = 4; ch < 8; ch++)
  46. {
  47. if (int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2))
  48. break;
  49. }
  50. if (8 == ch)
  51. return;
  52. }
  53. if (DMA_CTRL_REG(ch) & 0x01)
  54. {
  55. uint32_t temp = 0, cur_len = 0;
  56. temp = DMA_CTRL_REG(ch);
  57. if(len[ch] == 0)
  58. {
  59. len[ch] = (temp & 0xFFFF00) >> 8;
  60. }
  61. cur_len = (temp & 0xFFFF00) >> 8;
  62. if((cur_len + len[ch]) > 0xFFFF)
  63. {
  64. cur_len = 0;
  65. DMA_CHNLCTRL_REG(ch) |= (1 << 1);
  66. while(DMA_CHNLCTRL_REG(ch) & (1 << 0));
  67. DMA_CHNLCTRL_REG(ch) |= (1 << 0);
  68. }
  69. temp &= ~(0xFFFF << 8);
  70. temp |= ((cur_len + len[ch]) << 8);
  71. DMA_CTRL_REG(ch) = temp;
  72. }
  73. if ((int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2)) &&
  74. (TLS_DMA_IRQ_BOTH_DONE == dma_context[ch].flags))
  75. {
  76. tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE);
  77. if (dma_context[ch].burst_done_pf)
  78. dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv);
  79. }
  80. else if ((int_src & (TLS_DMA_IRQ_BURST_DONE << ch * 2)) &&
  81. (TLS_DMA_IRQ_BURST_DONE == dma_context[ch].flags))
  82. {
  83. tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE);
  84. if (dma_context[ch].burst_done_pf)
  85. dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv);
  86. }
  87. else if ((int_src & (TLS_DMA_IRQ_TRANSFER_DONE << ch * 2)) &&
  88. (TLS_DMA_IRQ_TRANSFER_DONE == dma_context[ch].flags))
  89. {
  90. tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE);
  91. if (dma_context[ch].transfer_done_pf)
  92. dma_context[ch].transfer_done_pf(dma_context[ch].transfer_done_priv);
  93. }
  94. return;
  95. }
  96. ATTRIBUTE_ISR void DMA_Channel0_IRQHandler(void)
  97. {
  98. csi_kernel_intrpt_enter();
  99. dma_irq_proc((void *)0);
  100. csi_kernel_intrpt_exit();
  101. }
  102. ATTRIBUTE_ISR void DMA_Channel1_IRQHandler(void)
  103. {
  104. csi_kernel_intrpt_enter();
  105. dma_irq_proc((void *)1);
  106. csi_kernel_intrpt_exit();
  107. }
  108. ATTRIBUTE_ISR void DMA_Channel2_IRQHandler(void)
  109. {
  110. csi_kernel_intrpt_enter();
  111. dma_irq_proc((void *)2);
  112. csi_kernel_intrpt_exit();
  113. }
  114. ATTRIBUTE_ISR void DMA_Channel3_IRQHandler(void)
  115. {
  116. csi_kernel_intrpt_enter();
  117. dma_irq_proc((void *)3);
  118. csi_kernel_intrpt_exit();
  119. }
  120. ATTRIBUTE_ISR void DMA_Channel4_7_IRQHandler(void)
  121. {
  122. csi_kernel_intrpt_enter();
  123. dma_irq_proc((void *)4);
  124. csi_kernel_intrpt_exit();
  125. }
  126. /**
  127. * @brief This function is used to clear dma interrupt flag.
  128. *
  129. * @param[in] ch Channel no.[0~7]
  130. * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE.
  131. *
  132. * @return None
  133. *
  134. * @note None
  135. */
  136. void tls_dma_irq_clr(unsigned char ch, unsigned char flags)
  137. {
  138. unsigned int int_src = 0;
  139. int_src |= flags << 2 * ch;
  140. tls_reg_write32(HR_DMA_INT_SRC, int_src);
  141. return;
  142. }
  143. /**
  144. * @brief This function is used to register dma interrupt callback function.
  145. *
  146. * @param[in] ch Channel no.[0~7]
  147. * @param[in] callback is the dma interrupt call back function.
  148. * @param[in] arg the param of the callback function.
  149. * @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE.
  150. *
  151. * @return None
  152. *
  153. * @note None
  154. */void tls_dma_irq_register(unsigned char ch, void (*callback)(void *p), void *arg, unsigned char flags)
  155. {
  156. unsigned int mask;
  157. mask = tls_reg_read32(HR_DMA_INT_MASK);
  158. mask |= TLS_DMA_IRQ_BOTH_DONE << 2 * ch;
  159. mask &= ~(flags << 2 * ch);
  160. tls_reg_write32(HR_DMA_INT_MASK, mask);
  161. dma_context[ch].flags = flags;
  162. if (flags & TLS_DMA_IRQ_BURST_DONE)
  163. {
  164. dma_context[ch].burst_done_pf = callback;
  165. dma_context[ch].burst_done_priv = arg;
  166. }
  167. if (flags & TLS_DMA_IRQ_TRANSFER_DONE)
  168. {
  169. dma_context[ch].transfer_done_pf = callback;
  170. dma_context[ch].transfer_done_priv = arg;
  171. }
  172. if (ch > 3)
  173. ch = 4;
  174. tls_irq_priority(DMA_Channel0_IRQn + ch, ch/2);
  175. tls_irq_enable(DMA_Channel0_IRQn + ch);
  176. }
  177. /**
  178. * @brief This function is used to Wait until DMA operation completes
  179. *
  180. * @param[in] ch channel no
  181. *
  182. * @retval 0 completed
  183. * @retval -1 failed
  184. *
  185. * @note None
  186. */
  187. int tls_dma_wait_complt(unsigned char ch)
  188. {
  189. unsigned long timeout = 0;
  190. while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON)
  191. {
  192. tls_os_time_delay(1);
  193. timeout ++;
  194. if(timeout > 500)
  195. return -1;
  196. }
  197. return 0;
  198. }
  199. /**
  200. * @brief This function is used to Start the DMA controller by Wrap
  201. *
  202. * @param[in] ch channel no
  203. * @param[in] dma_desc pointer to DMA channel descriptor structure
  204. * @param[in] auto_reload does restart when current transfer complete
  205. * @param[in] src_zize dource address size
  206. * @param[in] dest_zize destination address size
  207. *
  208. * @retval 1 success
  209. * @retval 0 failed
  210. *
  211. * @note
  212. * DMA Descriptor:
  213. * +--------------------------------------------------------------+
  214. * |Vld[31] | RSV |
  215. * +--------------------------------------------------------------+
  216. * | RSV | Dma_Ctrl[16:0] |
  217. * +--------------------------------------------------------------+
  218. * | Src_Addr[31:0] |
  219. * +--------------------------------------------------------------+
  220. * | Dest_Addr[31:0] |
  221. * +--------------------------------------------------------------+
  222. * | Next_Desc_Add[31:0] |
  223. * +--------------------------------------------------------------+
  224. */
  225. unsigned char tls_dma_start_by_wrap(unsigned char ch, struct tls_dma_descriptor *dma_desc,
  226. unsigned char auto_reload,
  227. unsigned short src_zize,
  228. unsigned short dest_zize)
  229. {
  230. if((ch > 7) && !dma_desc) return 1;
  231. DMA_SRCWRAPADDR_REG(ch) = dma_desc->src_addr;
  232. DMA_DESTWRAPADDR_REG(ch) = dma_desc->dest_addr;
  233. DMA_WRAPSIZE_REG(ch) = (dest_zize << 16) | src_zize;
  234. DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x7fffff) << 1) | (auto_reload ? 0x1: 0x0);
  235. DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON;
  236. return 0;
  237. }
  238. /**
  239. * @brief This function is used to Start the DMA controller
  240. *
  241. * @param[in] ch channel no
  242. * @param[in] dma_desc pointer to DMA channel descriptor structure
  243. * @param[in] auto_reload does restart when current transfer complete
  244. *
  245. * @retval 1 success
  246. * @retval 0 failed
  247. *
  248. * @note
  249. * DMA Descriptor:
  250. * +--------------------------------------------------------------+
  251. * |Vld[31] | RSV |
  252. * +--------------------------------------------------------------+
  253. * | RSV | Dma_Ctrl[16:0] |
  254. * +--------------------------------------------------------------+
  255. * | Src_Addr[31:0] |
  256. * +--------------------------------------------------------------+
  257. * | Dest_Addr[31:0] |
  258. * +--------------------------------------------------------------+
  259. * | Next_Desc_Add[31:0] |
  260. * +--------------------------------------------------------------+
  261. */
  262. unsigned char tls_dma_start(unsigned char ch, struct tls_dma_descriptor *dma_desc, unsigned char auto_reload)
  263. {
  264. if((ch > 7) && !dma_desc) return 1;
  265. if ((dma_used_bit &(1<<ch)) == 0)
  266. {
  267. dma_used_bit |= (1<<ch);
  268. }
  269. DMA_SRCADDR_REG(ch) = dma_desc->src_addr;
  270. DMA_DESTADDR_REG(ch) = dma_desc->dest_addr;
  271. DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x7fffff) << 1) | (auto_reload ? 0x1: 0x0);
  272. DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON;
  273. return 0;
  274. }
  275. /**
  276. * @brief This function is used to To stop current DMA channel transfer
  277. *
  278. * @param[in] ch channel no. to be stopped
  279. *
  280. * @retval 0 success
  281. * @retval 1 failed
  282. *
  283. * @note
  284. * If channel stop, DMA_CHNL_CTRL_CHNL_ON bit in DMA_CHNLCTRL_REG is cleared.
  285. */
  286. unsigned char tls_dma_stop(unsigned char ch)
  287. {
  288. if(ch > 7) return 1;
  289. if(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON)
  290. {
  291. DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_OFF;
  292. while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON);
  293. }
  294. return 0;
  295. }
  296. /**
  297. * @brief This function is used to Request a free dma channel
  298. *
  299. * @param[in] ch specified channel when ch is valid and not used.
  300. * @param[in] flags flags setted to selected channel
  301. *
  302. * @return Real DMA Channel No.
  303. *
  304. * @note
  305. * If ch is invalid or valid but used, the function will select a random free channel.
  306. * else return the selected channel no.
  307. */
  308. unsigned char tls_dma_request(unsigned char ch, unsigned char flags)
  309. {
  310. unsigned char freeCh = 0xFF;
  311. int i = 0;
  312. /*If channel is valid, try to use specified DMA channel!*/
  313. if (ch < 8)
  314. {
  315. if (!(channels.channels[ch] & TLS_DMA_FLAGS_CHANNEL_VALID))
  316. {
  317. freeCh = ch;
  318. }
  319. }
  320. /*If ch is not valid, or ch has been used, try to select another free channel for the caller*/
  321. if (freeCh == 0xFF)
  322. {
  323. for (i = 0; i < 8; i++)
  324. {
  325. if (!(channels.channels[i] & TLS_DMA_FLAGS_CHANNEL_VALID))
  326. {
  327. freeCh = i;
  328. break;
  329. }
  330. }
  331. if (8 == i)
  332. {
  333. printf("!!!There is no free DMA channel.!!!\n");
  334. }
  335. }
  336. if (freeCh < 8)
  337. {
  338. if (dma_used_bit == 0)
  339. {
  340. tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_DMA);
  341. }
  342. dma_used_bit |= (1<<freeCh);
  343. channels.channels[freeCh] = flags | TLS_DMA_FLAGS_CHANNEL_VALID;
  344. DMA_MODE_REG(freeCh) = flags;
  345. }
  346. return freeCh;
  347. }
  348. /**
  349. * @brief This function is used to Free the DMA channel when not use
  350. *
  351. * @param[in] ch channel no. that is ready to free
  352. *
  353. * @return None
  354. *
  355. * @note None
  356. */
  357. void tls_dma_free(unsigned char ch)
  358. {
  359. if(ch < 8)
  360. {
  361. tls_dma_stop(ch);
  362. DMA_SRCADDR_REG(ch) = 0;
  363. DMA_DESTADDR_REG(ch) = 0;
  364. DMA_MODE_REG(ch) = 0;
  365. DMA_CTRL_REG(ch) = 0;
  366. // DMA_INTSRC_REG = 0xffff;
  367. DMA_INTSRC_REG |= 0x03<<(ch*2);
  368. channels.channels[ch] = 0x00;
  369. dma_used_bit &= ~(1<<ch);
  370. if (dma_used_bit == 0)
  371. {
  372. tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_DMA);
  373. }
  374. }
  375. }
  376. /**
  377. * @brief This function is used to Initialize DMA Control
  378. *
  379. * @param[in] None
  380. *
  381. * @return None
  382. *
  383. * @note None
  384. */
  385. void tls_dma_init(void)
  386. {
  387. u32 i = 0;
  388. u32 value = 0;
  389. for (i = 0; i < 8; i++)
  390. {
  391. if (!(dma_used_bit & (1<<i)))
  392. {
  393. value |= 3<<(i*2);
  394. }
  395. }
  396. DMA_INTMASK_REG = value;
  397. DMA_INTSRC_REG = value;
  398. }