dmac.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. /* Copyright 2018 Canaan Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <stddef.h>
  16. #include <stdint.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "dmac.h"
  20. #include "fpioa.h"
  21. #include "plic.h"
  22. #include "stdlib.h"
  23. #include "sysctl.h"
  24. #include "utils.h"
  25. #include "iomem.h"
  26. volatile dmac_t *const dmac = (dmac_t *)DMAC_BASE_ADDR;
  27. typedef struct _dmac_context
  28. {
  29. dmac_channel_number_t dmac_channel;
  30. #if FIX_CACHE
  31. uint8_t *dest_buffer;
  32. uint8_t *src_malloc;
  33. uint8_t *dest_malloc;
  34. size_t buf_len;
  35. #endif
  36. plic_irq_callback_t callback;
  37. void *ctx;
  38. } dmac_context_t;
  39. dmac_context_t dmac_context[6];
  40. static int is_memory(uintptr_t address)
  41. {
  42. enum
  43. {
  44. mem_len = 6 * 1024 * 1024,
  45. mem_no_cache_len = 8 * 1024 * 1024,
  46. };
  47. return ((address >= 0x80000000) && (address < 0x80000000 + mem_len)) || ((address >= 0x40000000) && (address < 0x40000000 + mem_no_cache_len)) || (address == 0x50450040);
  48. }
  49. uint64_t dmac_read_id(void)
  50. {
  51. return dmac->id;
  52. }
  53. uint64_t dmac_read_version(void)
  54. {
  55. return dmac->compver;
  56. }
  57. uint64_t dmac_read_channel_id(dmac_channel_number_t channel_num)
  58. {
  59. return dmac->channel[channel_num].axi_id;
  60. }
  61. static void dmac_enable(void)
  62. {
  63. dmac_cfg_u_t dmac_cfg;
  64. dmac_cfg.data = readq(&dmac->cfg);
  65. dmac_cfg.cfg.dmac_en = 1;
  66. dmac_cfg.cfg.int_en = 1;
  67. writeq(dmac_cfg.data, &dmac->cfg);
  68. }
  69. void dmac_disable(void)
  70. {
  71. dmac_cfg_u_t dmac_cfg;
  72. dmac_cfg.data = readq(&dmac->cfg);
  73. dmac_cfg.cfg.dmac_en = 0;
  74. dmac_cfg.cfg.int_en = 0;
  75. writeq(dmac_cfg.data, &dmac->cfg);
  76. }
  77. void src_transaction_complete_int_enable(dmac_channel_number_t channel_num)
  78. {
  79. dmac_ch_intstatus_enable_u_t ch_intstat;
  80. ch_intstat.data = readq(&dmac->channel[channel_num].intstatus_en);
  81. ch_intstat.ch_intstatus_enable.enable_src_transcomp_intstat = 1;
  82. writeq(ch_intstat.data, &dmac->channel[channel_num].intstatus_en);
  83. }
  84. void dmac_channel_enable(dmac_channel_number_t channel_num)
  85. {
  86. dmac_chen_u_t chen;
  87. chen.data = readq(&dmac->chen);
  88. switch(channel_num)
  89. {
  90. case DMAC_CHANNEL0:
  91. chen.dmac_chen.ch1_en = 1;
  92. chen.dmac_chen.ch1_en_we = 1;
  93. break;
  94. case DMAC_CHANNEL1:
  95. chen.dmac_chen.ch2_en = 1;
  96. chen.dmac_chen.ch2_en_we = 1;
  97. break;
  98. case DMAC_CHANNEL2:
  99. chen.dmac_chen.ch3_en = 1;
  100. chen.dmac_chen.ch3_en_we = 1;
  101. break;
  102. case DMAC_CHANNEL3:
  103. chen.dmac_chen.ch4_en = 1;
  104. chen.dmac_chen.ch4_en_we = 1;
  105. break;
  106. case DMAC_CHANNEL4:
  107. chen.dmac_chen.ch5_en = 1;
  108. chen.dmac_chen.ch5_en_we = 1;
  109. break;
  110. case DMAC_CHANNEL5:
  111. chen.dmac_chen.ch6_en = 1;
  112. chen.dmac_chen.ch6_en_we = 1;
  113. break;
  114. default:
  115. break;
  116. }
  117. writeq(chen.data, &dmac->chen);
  118. }
  119. void dmac_channel_disable(dmac_channel_number_t channel_num)
  120. {
  121. dmac_chen_u_t chen;
  122. chen.data = readq(&dmac->chen);
  123. switch(channel_num)
  124. {
  125. case DMAC_CHANNEL0:
  126. chen.dmac_chen.ch1_en = 0;
  127. chen.dmac_chen.ch1_en_we = 1;
  128. break;
  129. case DMAC_CHANNEL1:
  130. chen.dmac_chen.ch2_en = 0;
  131. chen.dmac_chen.ch2_en_we = 1;
  132. break;
  133. case DMAC_CHANNEL2:
  134. chen.dmac_chen.ch3_en = 0;
  135. chen.dmac_chen.ch3_en_we = 1;
  136. break;
  137. case DMAC_CHANNEL3:
  138. chen.dmac_chen.ch4_en = 0;
  139. chen.dmac_chen.ch4_en_we = 1;
  140. break;
  141. case DMAC_CHANNEL4:
  142. chen.dmac_chen.ch5_en = 0;
  143. chen.dmac_chen.ch5_en_we = 1;
  144. break;
  145. case DMAC_CHANNEL5:
  146. chen.dmac_chen.ch6_en = 0;
  147. chen.dmac_chen.ch6_en_we = 1;
  148. break;
  149. default:
  150. break;
  151. }
  152. writeq(chen.data, &dmac->chen);
  153. }
  154. int32_t dmac_check_channel_busy(dmac_channel_number_t channel_num)
  155. {
  156. int32_t ret = 0;
  157. dmac_chen_u_t chen_u;
  158. chen_u.data = readq(&dmac->chen);
  159. switch(channel_num)
  160. {
  161. case DMAC_CHANNEL0:
  162. if(chen_u.dmac_chen.ch1_en == 1)
  163. ret = 1;
  164. break;
  165. case DMAC_CHANNEL1:
  166. if(chen_u.dmac_chen.ch2_en == 1)
  167. ret = 1;
  168. break;
  169. case DMAC_CHANNEL2:
  170. if(chen_u.dmac_chen.ch3_en == 1)
  171. ret = 1;
  172. break;
  173. case DMAC_CHANNEL3:
  174. if(chen_u.dmac_chen.ch4_en == 1)
  175. ret = 1;
  176. break;
  177. case DMAC_CHANNEL4:
  178. if(chen_u.dmac_chen.ch5_en == 1)
  179. ret = 1;
  180. break;
  181. case DMAC_CHANNEL5:
  182. if(chen_u.dmac_chen.ch6_en == 1)
  183. ret = 1;
  184. break;
  185. default:
  186. break;
  187. }
  188. writeq(chen_u.data, &dmac->chen);
  189. return ret;
  190. }
  191. int32_t dmac_set_list_master_select(dmac_channel_number_t channel_num,
  192. dmac_src_dst_select_t sd_sel, dmac_master_number_t mst_num)
  193. {
  194. int32_t ret = 0;
  195. uint64_t tmp = 0;
  196. dmac_ch_ctl_u_t ctl;
  197. ctl.data = readq(&dmac->channel[channel_num].ctl);
  198. ret = dmac_check_channel_busy(channel_num);
  199. if(ret == 0)
  200. {
  201. if(sd_sel == DMAC_SRC || sd_sel == DMAC_SRC_DST)
  202. ctl.ch_ctl.sms = mst_num;
  203. if(sd_sel == DMAC_DST || sd_sel == DMAC_SRC_DST)
  204. ctl.ch_ctl.dms = mst_num;
  205. tmp |= *(uint64_t *)&dmac->channel[channel_num].ctl;
  206. writeq(ctl.data, &dmac->channel[channel_num].ctl);
  207. }
  208. return ret;
  209. }
  210. void dmac_enable_common_interrupt_status(void)
  211. {
  212. dmac_commonreg_intstatus_enable_u_t intstatus;
  213. intstatus.data = readq(&dmac->com_intstatus_en);
  214. intstatus.intstatus_enable.enable_slvif_dec_err_intstat = 1;
  215. intstatus.intstatus_enable.enable_slvif_wr2ro_err_intstat = 1;
  216. intstatus.intstatus_enable.enable_slvif_rd2wo_err_intstat = 1;
  217. intstatus.intstatus_enable.enable_slvif_wronhold_err_intstat = 1;
  218. intstatus.intstatus_enable.enable_slvif_undefinedreg_dec_err_intstat = 1;
  219. writeq(intstatus.data, &dmac->com_intstatus_en);
  220. }
  221. void dmac_enable_common_interrupt_signal(void)
  222. {
  223. dmac_commonreg_intsignal_enable_u_t intsignal;
  224. intsignal.data = readq(&dmac->com_intsignal_en);
  225. intsignal.intsignal_enable.enable_slvif_dec_err_intsignal = 1;
  226. intsignal.intsignal_enable.enable_slvif_wr2ro_err_intsignal = 1;
  227. intsignal.intsignal_enable.enable_slvif_rd2wo_err_intsignal = 1;
  228. intsignal.intsignal_enable.enable_slvif_wronhold_err_intsignal = 1;
  229. intsignal.intsignal_enable.enable_slvif_undefinedreg_dec_err_intsignal = 1;
  230. writeq(intsignal.data, &dmac->com_intsignal_en);
  231. }
  232. static void dmac_enable_channel_interrupt(dmac_channel_number_t channel_num)
  233. {
  234. writeq(0xffffffff, &dmac->channel[channel_num].intclear);
  235. writeq(0x2, &dmac->channel[channel_num].intstatus_en);
  236. }
  237. void dmac_disable_channel_interrupt(dmac_channel_number_t channel_num)
  238. {
  239. writeq(0, &dmac->channel[channel_num].intstatus_en);
  240. }
  241. static void dmac_channel_interrupt_clear(dmac_channel_number_t channel_num)
  242. {
  243. writeq(0xffffffff, &dmac->channel[channel_num].intclear);
  244. }
  245. int dmac_set_channel_config(dmac_channel_number_t channel_num,
  246. dmac_channel_config_t *cfg_param)
  247. {
  248. dmac_ch_ctl_u_t ctl;
  249. dmac_ch_cfg_u_t cfg;
  250. dmac_ch_llp_u_t ch_llp;
  251. if(cfg_param->ctl_sms > DMAC_MASTER2)
  252. return -1;
  253. if(cfg_param->ctl_dms > DMAC_MASTER2)
  254. return -1;
  255. if(cfg_param->ctl_src_msize > DMAC_MSIZE_256)
  256. return -1;
  257. if(cfg_param->ctl_drc_msize > DMAC_MSIZE_256)
  258. return -1;
  259. /**
  260. * cfg register must configure before ts_block and
  261. * sar dar register
  262. */
  263. cfg.data = readq(&dmac->channel[channel_num].cfg);
  264. cfg.ch_cfg.hs_sel_src = cfg_param->cfg_hs_sel_src;
  265. cfg.ch_cfg.hs_sel_dst = cfg_param->cfg_hs_sel_dst;
  266. cfg.ch_cfg.src_hwhs_pol = cfg_param->cfg_src_hs_pol;
  267. cfg.ch_cfg.dst_hwhs_pol = cfg_param->cfg_dst_hs_pol;
  268. cfg.ch_cfg.src_per = cfg_param->cfg_src_per;
  269. cfg.ch_cfg.dst_per = cfg_param->cfg_dst_per;
  270. cfg.ch_cfg.ch_prior = cfg_param->cfg_ch_prior;
  271. cfg.ch_cfg.tt_fc = cfg_param->ctl_tt_fc;
  272. cfg.ch_cfg.src_multblk_type = cfg_param->cfg_src_multblk_type;
  273. cfg.ch_cfg.dst_multblk_type = cfg_param->cfg_dst_multblk_type;
  274. writeq(cfg.data, &dmac->channel[channel_num].cfg);
  275. ctl.data = readq(&dmac->channel[channel_num].ctl);
  276. ctl.ch_ctl.sms = cfg_param->ctl_sms;
  277. ctl.ch_ctl.dms = cfg_param->ctl_dms;
  278. /* master select */
  279. ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
  280. ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
  281. /* address incrememt */
  282. ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
  283. ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
  284. /* transfer width */
  285. ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
  286. ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
  287. /* Burst transaction length */
  288. ctl.ch_ctl.ioc_blktfr = cfg_param->ctl_ioc_blktfr;
  289. /* interrupt on completion of block transfer */
  290. /* 0x1 enable BLOCK_TFR_DONE_IntStat field */
  291. writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
  292. /* the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
  293. /* transferred in a dma block transfer */
  294. dmac->channel[channel_num].sar = cfg_param->sar;
  295. dmac->channel[channel_num].dar = cfg_param->dar;
  296. ch_llp.data = readq(&dmac->channel[channel_num].llp);
  297. ch_llp.llp.loc = cfg_param->llp_loc;
  298. ch_llp.llp.lms = cfg_param->llp_lms;
  299. writeq(ch_llp.data, &dmac->channel[channel_num].llp);
  300. writeq(ctl.data, &dmac->channel[channel_num].ctl);
  301. readq(&dmac->channel[channel_num].swhssrc);
  302. return 0;
  303. }
  304. int dmac_set_channel_param(dmac_channel_number_t channel_num,
  305. const void *src, void *dest, dmac_address_increment_t src_inc, dmac_address_increment_t dest_inc,
  306. dmac_burst_trans_length_t dmac_burst_size,
  307. dmac_transfer_width_t dmac_trans_width,
  308. uint32_t blockSize)
  309. {
  310. dmac_ch_ctl_u_t ctl;
  311. dmac_ch_cfg_u_t cfg_u;
  312. #if FIX_CACHE
  313. uint8_t *src_io = (uint8_t *)src;
  314. uint8_t *dest_io = (uint8_t *)dest;
  315. if(is_memory_cache((uintptr_t)src))
  316. {
  317. if(src_inc == DMAC_ADDR_NOCHANGE)
  318. {
  319. src_io = (uint8_t *)iomem_malloc(1<<dmac_trans_width);
  320. memcpy(src_io, src, 1<<dmac_trans_width);
  321. }
  322. else
  323. {
  324. src_io = (uint8_t *)iomem_malloc(blockSize * (1<<dmac_trans_width));
  325. memcpy(src_io, src, blockSize * (1<<dmac_trans_width));
  326. }
  327. dmac_context[channel_num].src_malloc = src_io;
  328. }
  329. if(is_memory_cache((uintptr_t)dest))
  330. {
  331. if(dest_inc == DMAC_ADDR_NOCHANGE)
  332. {
  333. dest_io = (uint8_t *)iomem_malloc(1<<dmac_trans_width);
  334. dmac_context[channel_num].buf_len = 1<<dmac_trans_width;
  335. }
  336. else
  337. {
  338. dest_io = (uint8_t *)iomem_malloc(blockSize * (1<<dmac_trans_width));
  339. dmac_context[channel_num].buf_len = blockSize * (1<<dmac_trans_width);
  340. }
  341. dmac_context[channel_num].dest_malloc = dest_io;
  342. dmac_context[channel_num].dest_buffer = dest;
  343. }
  344. #endif
  345. int mem_type_src = is_memory((uintptr_t)src), mem_type_dest = is_memory((uintptr_t)dest);
  346. dmac_transfer_flow_t flow_control;
  347. if(mem_type_src == 0 && mem_type_dest == 0)
  348. {
  349. flow_control = DMAC_PRF2PRF_DMA;
  350. } else if(mem_type_src == 1 && mem_type_dest == 0)
  351. flow_control = DMAC_MEM2PRF_DMA;
  352. else if(mem_type_src == 0 && mem_type_dest == 1)
  353. flow_control = DMAC_PRF2MEM_DMA;
  354. else
  355. flow_control = DMAC_MEM2MEM_DMA;
  356. /**
  357. * cfg register must configure before ts_block and
  358. * sar dar register
  359. */
  360. cfg_u.data = readq(&dmac->channel[channel_num].cfg);
  361. cfg_u.ch_cfg.tt_fc = flow_control;
  362. cfg_u.ch_cfg.hs_sel_src = mem_type_src ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
  363. cfg_u.ch_cfg.hs_sel_dst = mem_type_dest ? DMAC_HS_SOFTWARE : DMAC_HS_HARDWARE;
  364. cfg_u.ch_cfg.src_per = channel_num;
  365. cfg_u.ch_cfg.dst_per = channel_num;
  366. cfg_u.ch_cfg.src_multblk_type = 0;
  367. cfg_u.ch_cfg.dst_multblk_type = 0;
  368. writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
  369. #if FIX_CACHE
  370. dmac->channel[channel_num].sar = (uint64_t)src_io;
  371. dmac->channel[channel_num].dar = (uint64_t)dest_io;
  372. #else
  373. dmac->channel[channel_num].sar = (uint64_t)src;
  374. dmac->channel[channel_num].dar = (uint64_t)dest;
  375. #endif
  376. ctl.data = readq(&dmac->channel[channel_num].ctl);
  377. ctl.ch_ctl.sms = DMAC_MASTER1;
  378. ctl.ch_ctl.dms = DMAC_MASTER2;
  379. /* master select */
  380. ctl.ch_ctl.sinc = src_inc;
  381. ctl.ch_ctl.dinc = dest_inc;
  382. /* address incrememt */
  383. ctl.ch_ctl.src_tr_width = dmac_trans_width;
  384. ctl.ch_ctl.dst_tr_width = dmac_trans_width;
  385. /* transfer width */
  386. ctl.ch_ctl.src_msize = dmac_burst_size;
  387. ctl.ch_ctl.dst_msize = dmac_burst_size;
  388. writeq(ctl.data, &dmac->channel[channel_num].ctl);
  389. writeq(blockSize - 1, &dmac->channel[channel_num].block_ts);
  390. /*the number of (blcok_ts +1) data of width SRC_TR_WIDTF to be */
  391. /* transferred in a dma block transfer */
  392. return 0;
  393. }
  394. int dmac_get_channel_config(dmac_channel_number_t channel_num,
  395. dmac_channel_config_t *cfg_param)
  396. {
  397. dmac_ch_ctl_u_t ctl;
  398. dmac_ch_cfg_u_t cfg;
  399. dmac_ch_llp_u_t ch_llp;
  400. if(cfg_param == 0)
  401. return -1;
  402. if(channel_num < DMAC_CHANNEL0 ||
  403. channel_num > DMAC_CHANNEL3)
  404. return -1;
  405. ctl.data = readq(&dmac->channel[channel_num].ctl);
  406. cfg_param->ctl_sms = ctl.ch_ctl.sms;
  407. cfg_param->ctl_dms = ctl.ch_ctl.dms;
  408. cfg_param->ctl_sinc = ctl.ch_ctl.sinc;
  409. cfg_param->ctl_dinc = ctl.ch_ctl.dinc;
  410. cfg_param->ctl_src_tr_width = ctl.ch_ctl.src_tr_width;
  411. cfg_param->ctl_dst_tr_width = ctl.ch_ctl.dst_tr_width;
  412. cfg_param->ctl_src_msize = ctl.ch_ctl.src_msize;
  413. cfg_param->ctl_drc_msize = ctl.ch_ctl.dst_msize;
  414. cfg_param->ctl_ioc_blktfr = ctl.ch_ctl.ioc_blktfr;
  415. cfg.data = readq(&dmac->channel[channel_num].cfg);
  416. cfg_param->cfg_hs_sel_src = cfg.ch_cfg.hs_sel_src;
  417. cfg_param->cfg_hs_sel_dst = cfg.ch_cfg.hs_sel_dst;
  418. cfg_param->cfg_src_hs_pol = cfg.ch_cfg.src_hwhs_pol;
  419. cfg_param->cfg_dst_hs_pol = cfg.ch_cfg.dst_hwhs_pol;
  420. cfg_param->cfg_src_per = cfg.ch_cfg.src_per;
  421. cfg_param->cfg_dst_per = cfg.ch_cfg.dst_per;
  422. cfg_param->cfg_ch_prior = cfg.ch_cfg.ch_prior;
  423. cfg_param->cfg_src_multblk_type = cfg.ch_cfg.src_multblk_type;
  424. cfg_param->cfg_dst_multblk_type = cfg.ch_cfg.dst_multblk_type;
  425. cfg_param->sar = dmac->channel[channel_num].sar;
  426. cfg_param->dar = dmac->channel[channel_num].dar;
  427. ch_llp.data = readq(&dmac->channel[channel_num].llp);
  428. cfg_param->llp_loc = ch_llp.llp.loc;
  429. cfg_param->llp_lms = ch_llp.llp.lms;
  430. cfg_param->ctl_block_ts = readq(&dmac->channel[channel_num].block_ts);
  431. return 0;
  432. }
  433. void dmac_set_address(dmac_channel_number_t channel_num, uint64_t src_addr,
  434. uint64_t dst_addr)
  435. {
  436. writeq(src_addr, &dmac->channel[channel_num].sar);
  437. writeq(dst_addr, &dmac->channel[channel_num].dar);
  438. }
  439. void dmac_set_block_ts(dmac_channel_number_t channel_num,
  440. uint32_t block_size)
  441. {
  442. uint32_t block_ts;
  443. block_ts = block_size & 0x3fffff;
  444. writeq(block_ts, &dmac->channel[channel_num].block_ts);
  445. }
  446. void dmac_source_control(dmac_channel_number_t channel_num,
  447. dmac_master_number_t master_select,
  448. dmac_address_increment_t address_mode,
  449. dmac_transfer_width_t tr_width,
  450. dmac_burst_trans_length_t burst_length)
  451. {
  452. dmac_ch_ctl_u_t ctl_u;
  453. ctl_u.data = readq(&dmac->channel[channel_num].ctl);
  454. ctl_u.ch_ctl.sms = master_select;
  455. ctl_u.ch_ctl.sinc = address_mode;
  456. ctl_u.ch_ctl.src_tr_width = tr_width;
  457. ctl_u.ch_ctl.src_msize = burst_length;
  458. writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
  459. }
  460. void dmac_master_control(dmac_channel_number_t channel_num,
  461. dmac_master_number_t master_select,
  462. dmac_address_increment_t address_mode,
  463. dmac_transfer_width_t tr_width,
  464. dmac_burst_trans_length_t burst_length)
  465. {
  466. dmac_ch_ctl_u_t ctl_u;
  467. ctl_u.data = readq(&dmac->channel[channel_num].ctl);
  468. ctl_u.ch_ctl.dms = master_select;
  469. ctl_u.ch_ctl.dinc = address_mode;
  470. ctl_u.ch_ctl.dst_tr_width = tr_width;
  471. ctl_u.ch_ctl.dst_msize = burst_length;
  472. writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
  473. }
  474. void dmac_set_source_transfer_control(dmac_channel_number_t channel_num,
  475. dmac_multiblk_transfer_type_t transfer_type,
  476. dmac_sw_hw_hs_select_t handshak_select)
  477. {
  478. dmac_ch_cfg_u_t cfg_u;
  479. cfg_u.data = readq(&dmac->channel[channel_num].cfg);
  480. cfg_u.ch_cfg.src_multblk_type = transfer_type;
  481. cfg_u.ch_cfg.hs_sel_src = handshak_select;
  482. writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
  483. }
  484. void dmac_set_destination_transfer_control(dmac_channel_number_t channel_num,
  485. dmac_multiblk_transfer_type_t transfer_type,
  486. dmac_sw_hw_hs_select_t handshak_select)
  487. {
  488. dmac_ch_cfg_u_t cfg_u;
  489. cfg_u.data = readq(&dmac->channel[channel_num].cfg);
  490. cfg_u.ch_cfg.dst_multblk_type = transfer_type;
  491. cfg_u.ch_cfg.hs_sel_dst = handshak_select;
  492. writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
  493. }
  494. void dmac_set_flow_control(dmac_channel_number_t channel_num,
  495. dmac_transfer_flow_t flow_control)
  496. {
  497. dmac_ch_cfg_u_t cfg_u;
  498. cfg_u.data = readq(&dmac->channel[channel_num].cfg);
  499. cfg_u.ch_cfg.tt_fc = flow_control;
  500. writeq(cfg_u.data, &dmac->channel[channel_num].cfg);
  501. }
  502. void dmac_set_linked_list_addr_point(dmac_channel_number_t channel_num,
  503. uint64_t *addr)
  504. {
  505. dmac_ch_llp_u_t llp_u;
  506. llp_u.data = readq(&dmac->channel[channel_num].llp);
  507. /* Cast pointer to uint64_t */
  508. llp_u.llp.loc = (uint64_t)addr;
  509. writeq(llp_u.data, &dmac->channel[channel_num].llp);
  510. }
  511. void dmac_init(void)
  512. {
  513. uint64_t tmp;
  514. dmac_commonreg_intclear_u_t intclear;
  515. dmac_cfg_u_t dmac_cfg;
  516. dmac_reset_u_t dmac_reset;
  517. sysctl_clock_enable(SYSCTL_CLOCK_DMA);
  518. dmac_reset.data = readq(&dmac->reset);
  519. dmac_reset.reset.rst = 1;
  520. writeq(dmac_reset.data, &dmac->reset);
  521. while(dmac_reset.reset.rst)
  522. dmac_reset.data = readq(&dmac->reset);
  523. /*reset dmac */
  524. intclear.data = readq(&dmac->com_intclear);
  525. intclear.com_intclear.cear_slvif_dec_err_intstat = 1;
  526. intclear.com_intclear.clear_slvif_wr2ro_err_intstat = 1;
  527. intclear.com_intclear.clear_slvif_rd2wo_err_intstat = 1;
  528. intclear.com_intclear.clear_slvif_wronhold_err_intstat = 1;
  529. intclear.com_intclear.clear_slvif_undefinedreg_dec_err_intstat = 1;
  530. writeq(intclear.data, &dmac->com_intclear);
  531. /* clear common register interrupt */
  532. dmac_cfg.data = readq(&dmac->cfg);
  533. dmac_cfg.cfg.dmac_en = 0;
  534. dmac_cfg.cfg.int_en = 0;
  535. writeq(dmac_cfg.data, &dmac->cfg);
  536. /* disable dmac and disable interrupt */
  537. while(readq(&dmac->cfg))
  538. ;
  539. tmp = readq(&dmac->chen);
  540. tmp &= ~0xf;
  541. writeq(tmp, &dmac->chen);
  542. for(dmac_channel_number_t channel=DMAC_CHANNEL0; channel<DMAC_CHANNEL_MAX; channel++)
  543. {
  544. dmac_disable_channel_interrupt(channel);
  545. }
  546. /* disable all channel before configure */
  547. dmac_enable();
  548. }
  549. static void list_add(struct list_head_t *new, struct list_head_t *prev,
  550. struct list_head_t *next)
  551. {
  552. next->prev = new;
  553. new->next = next;
  554. new->prev = prev;
  555. prev->next = new;
  556. }
  557. void list_add_tail(struct list_head_t *new, struct list_head_t *head)
  558. {
  559. list_add(new, head->prev, head);
  560. }
  561. void INIT_LIST_HEAD(struct list_head_t *list)
  562. {
  563. list->next = list;
  564. list->prev = list;
  565. }
  566. void dmac_link_list_item(dmac_channel_number_t channel_num,
  567. uint8_t LLI_row_num, int8_t LLI_last_row,
  568. dmac_lli_item_t *lli_item,
  569. dmac_channel_config_t *cfg_param)
  570. {
  571. dmac_ch_ctl_u_t ctl;
  572. dmac_ch_llp_u_t llp_u;
  573. lli_item[LLI_row_num].sar = cfg_param->sar;
  574. lli_item[LLI_row_num].dar = cfg_param->dar;
  575. ctl.data = readq(&dmac->channel[channel_num].ctl);
  576. ctl.ch_ctl.sms = cfg_param->ctl_sms;
  577. ctl.ch_ctl.dms = cfg_param->ctl_dms;
  578. ctl.ch_ctl.sinc = cfg_param->ctl_sinc;
  579. ctl.ch_ctl.dinc = cfg_param->ctl_dinc;
  580. ctl.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
  581. ctl.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
  582. ctl.ch_ctl.src_msize = cfg_param->ctl_src_msize;
  583. ctl.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
  584. ctl.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
  585. ctl.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
  586. if(LLI_last_row != LAST_ROW)
  587. {
  588. ctl.ch_ctl.shadowreg_or_lli_valid = 1;
  589. ctl.ch_ctl.shadowreg_or_lli_last = 0;
  590. } else
  591. {
  592. ctl.ch_ctl.shadowreg_or_lli_valid = 1;
  593. ctl.ch_ctl.shadowreg_or_lli_last = 1;
  594. }
  595. lli_item[LLI_row_num].ctl = ctl.data;
  596. lli_item[LLI_row_num].ch_block_ts = cfg_param->ctl_block_ts;
  597. lli_item[LLI_row_num].sstat = 0;
  598. lli_item[LLI_row_num].dstat = 0;
  599. llp_u.data = readq(&dmac->channel[channel_num].llp);
  600. if(LLI_last_row != LAST_ROW)
  601. llp_u.llp.loc = ((uint64_t)&lli_item[LLI_row_num + 1]) >> 6;
  602. else
  603. llp_u.llp.loc = 0;
  604. lli_item[LLI_row_num].llp = llp_u.data;
  605. }
  606. void dmac_update_shandow_register(dmac_channel_number_t channel_num,
  607. int8_t last_block, dmac_channel_config_t *cfg_param)
  608. {
  609. dmac_ch_ctl_u_t ctl_u;
  610. do
  611. {
  612. ctl_u.data = readq(&dmac->channel[channel_num].ctl);
  613. } while(ctl_u.ch_ctl.shadowreg_or_lli_valid);
  614. writeq(cfg_param->sar, &dmac->channel[channel_num].sar);
  615. writeq(cfg_param->dar, &dmac->channel[channel_num].dar);
  616. writeq(cfg_param->ctl_block_ts, &dmac->channel[channel_num].block_ts);
  617. ctl_u.ch_ctl.sms = cfg_param->ctl_sms;
  618. ctl_u.ch_ctl.dms = cfg_param->ctl_dms;
  619. ctl_u.ch_ctl.sinc = cfg_param->ctl_sinc;
  620. ctl_u.ch_ctl.dinc = cfg_param->ctl_dinc;
  621. ctl_u.ch_ctl.src_tr_width = cfg_param->ctl_src_tr_width;
  622. ctl_u.ch_ctl.dst_tr_width = cfg_param->ctl_dst_tr_width;
  623. ctl_u.ch_ctl.src_msize = cfg_param->ctl_src_msize;
  624. ctl_u.ch_ctl.dst_msize = cfg_param->ctl_drc_msize;
  625. ctl_u.ch_ctl.src_stat_en = cfg_param->ctl_src_stat_en;
  626. ctl_u.ch_ctl.dst_stat_en = cfg_param->ctl_dst_stat_en;
  627. if(last_block != LAST_ROW)
  628. {
  629. ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
  630. ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
  631. } else
  632. {
  633. ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
  634. ctl_u.ch_ctl.shadowreg_or_lli_last = 1;
  635. }
  636. writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
  637. writeq(0, &dmac->channel[channel_num].blk_tfr);
  638. }
  639. void dmac_set_shadow_invalid_flag(dmac_channel_number_t channel_num)
  640. {
  641. dmac_ch_ctl_u_t ctl_u;
  642. ctl_u.data = readq(&dmac->channel[channel_num].ctl);
  643. ctl_u.ch_ctl.shadowreg_or_lli_valid = 1;
  644. ctl_u.ch_ctl.shadowreg_or_lli_last = 0;
  645. writeq(ctl_u.data, &dmac->channel[channel_num].ctl);
  646. }
  647. void dmac_set_single_mode(dmac_channel_number_t channel_num,
  648. const void *src, void *dest, dmac_address_increment_t src_inc,
  649. dmac_address_increment_t dest_inc,
  650. dmac_burst_trans_length_t dmac_burst_size,
  651. dmac_transfer_width_t dmac_trans_width,
  652. size_t block_size)
  653. {
  654. dmac_channel_interrupt_clear(channel_num);
  655. dmac_channel_disable(channel_num);
  656. dmac_wait_idle(channel_num);
  657. dmac_set_channel_param(channel_num, src, dest, src_inc, dest_inc,
  658. dmac_burst_size, dmac_trans_width, block_size);
  659. dmac_enable();
  660. dmac_channel_enable(channel_num);
  661. }
  662. int dmac_is_done(dmac_channel_number_t channel_num)
  663. {
  664. if(readq(&dmac->channel[channel_num].intstatus) & 0x2)
  665. return 1;
  666. else
  667. return 0;
  668. }
  669. void dmac_wait_done(dmac_channel_number_t channel_num)
  670. {
  671. dmac_wait_idle(channel_num);
  672. #if FIX_CACHE
  673. if(dmac_context[channel_num].dest_buffer)
  674. {
  675. memcpy(dmac_context[channel_num].dest_buffer, dmac_context[channel_num].dest_malloc, dmac_context[channel_num].buf_len);
  676. iomem_free(dmac_context[channel_num].dest_malloc);
  677. dmac_context[channel_num].dest_malloc = NULL;
  678. dmac_context[channel_num].dest_buffer = NULL;
  679. dmac_context[channel_num].buf_len = 0;
  680. }
  681. if(dmac_context[channel_num].src_malloc)
  682. {
  683. iomem_free(dmac_context[channel_num].src_malloc);
  684. dmac_context[channel_num].src_malloc = NULL;
  685. }
  686. #endif
  687. }
  688. int dmac_is_idle(dmac_channel_number_t channel_num)
  689. {
  690. dmac_chen_u_t chen;
  691. chen.data = readq(&dmac->chen);
  692. if((chen.data >> channel_num) & 0x1UL)
  693. return 0;
  694. else
  695. return 1;
  696. }
  697. void dmac_wait_idle(dmac_channel_number_t channel_num)
  698. {
  699. while(!dmac_is_idle(channel_num))
  700. ;
  701. dmac_channel_interrupt_clear(channel_num); /* clear interrupt */
  702. }
  703. void dmac_set_src_dest_length(dmac_channel_number_t channel_num, const void *src, void *dest, size_t len)
  704. {
  705. if(src != NULL)
  706. dmac->channel[channel_num].sar = (uint64_t)src;
  707. if(dest != NULL)
  708. dmac->channel[channel_num].dar = (uint64_t)dest;
  709. if(len > 0)
  710. dmac_set_block_ts(channel_num, len - 1);
  711. dmac_channel_enable(channel_num);
  712. }
  713. static int dmac_irq_callback(void *ctx)
  714. {
  715. dmac_context_t *v_dmac_context = (dmac_context_t *)(ctx);
  716. dmac_channel_number_t v_dmac_channel = v_dmac_context->dmac_channel;
  717. dmac_channel_interrupt_clear(v_dmac_channel);
  718. #if FIX_CACHE
  719. if(v_dmac_context->dest_buffer)
  720. {
  721. memcpy(v_dmac_context->dest_buffer, v_dmac_context->dest_malloc, v_dmac_context->buf_len);
  722. iomem_free(v_dmac_context->dest_malloc);
  723. v_dmac_context->dest_malloc = NULL;
  724. v_dmac_context->dest_buffer = NULL;
  725. v_dmac_context->buf_len = 0;
  726. }
  727. if(v_dmac_context->src_malloc)
  728. {
  729. iomem_free(v_dmac_context->src_malloc);
  730. v_dmac_context->src_malloc = NULL;
  731. }
  732. #endif
  733. if(v_dmac_context->callback != NULL)
  734. v_dmac_context->callback(v_dmac_context->ctx);
  735. return 0;
  736. }
  737. void dmac_irq_register(dmac_channel_number_t channel_num, plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority)
  738. {
  739. dmac_context[channel_num].dmac_channel = channel_num;
  740. dmac_context[channel_num].callback = dmac_callback;
  741. dmac_context[channel_num].ctx = ctx;
  742. dmac_enable_channel_interrupt(channel_num);
  743. plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority);
  744. plic_irq_register(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]);
  745. plic_irq_enable(IRQN_DMA0_INTERRUPT + channel_num);
  746. }
  747. void __attribute__((weak, alias("dmac_irq_register"))) dmac_set_irq(dmac_channel_number_t channel_num, plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority);
  748. void dmac_irq_unregister(dmac_channel_number_t channel_num)
  749. {
  750. dmac_context[channel_num].callback = NULL;
  751. dmac_context[channel_num].ctx = NULL;
  752. dmac_disable_channel_interrupt(channel_num);
  753. plic_irq_unregister(IRQN_DMA0_INTERRUPT + channel_num);
  754. }
  755. void __attribute__((weak, alias("dmac_irq_unregister"))) dmac_free_irq(dmac_channel_number_t channel_num);