loongson1-apb-dma.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Driver for Loongson-1 APB DMA Controller
  4. *
  5. * Copyright (C) 2015-2024 Keguang Zhang <keguang.zhang@gmail.com>
  6. */
  7. #include <linux/dmapool.h>
  8. #include <linux/dma-mapping.h>
  9. #include <linux/init.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/iopoll.h>
  12. #include <linux/module.h>
  13. #include <linux/of.h>
  14. #include <linux/of_dma.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/slab.h>
  17. #include "dmaengine.h"
  18. #include "virt-dma.h"
  19. /* Loongson-1 DMA Control Register */
  20. #define LS1X_DMA_CTRL 0x0
  21. /* DMA Control Register Bits */
  22. #define LS1X_DMA_STOP BIT(4)
  23. #define LS1X_DMA_START BIT(3)
  24. #define LS1X_DMA_ASK_VALID BIT(2)
  25. /* DMA Next Field Bits */
  26. #define LS1X_DMA_NEXT_VALID BIT(0)
  27. /* DMA Command Field Bits */
  28. #define LS1X_DMA_RAM2DEV BIT(12)
  29. #define LS1X_DMA_INT BIT(1)
  30. #define LS1X_DMA_INT_MASK BIT(0)
  31. #define LS1X_DMA_LLI_ALIGNMENT 64
  32. #define LS1X_DMA_LLI_ADDR_MASK GENMASK(31, __ffs(LS1X_DMA_LLI_ALIGNMENT))
  33. #define LS1X_DMA_MAX_CHANNELS 3
  34. enum ls1x_dmadesc_offsets {
  35. LS1X_DMADESC_NEXT = 0,
  36. LS1X_DMADESC_SADDR,
  37. LS1X_DMADESC_DADDR,
  38. LS1X_DMADESC_LENGTH,
  39. LS1X_DMADESC_STRIDE,
  40. LS1X_DMADESC_CYCLES,
  41. LS1X_DMADESC_CMD,
  42. LS1X_DMADESC_SIZE
  43. };
  44. struct ls1x_dma_lli {
  45. unsigned int hw[LS1X_DMADESC_SIZE];
  46. dma_addr_t phys;
  47. struct list_head node;
  48. } __aligned(LS1X_DMA_LLI_ALIGNMENT);
  49. struct ls1x_dma_desc {
  50. struct virt_dma_desc vd;
  51. struct list_head lli_list;
  52. };
  53. struct ls1x_dma_chan {
  54. struct virt_dma_chan vc;
  55. struct dma_pool *lli_pool;
  56. phys_addr_t src_addr;
  57. phys_addr_t dst_addr;
  58. enum dma_slave_buswidth src_addr_width;
  59. enum dma_slave_buswidth dst_addr_width;
  60. unsigned int bus_width;
  61. void __iomem *reg_base;
  62. int irq;
  63. bool is_cyclic;
  64. struct ls1x_dma_lli *curr_lli;
  65. };
  66. struct ls1x_dma {
  67. struct dma_device ddev;
  68. unsigned int nr_chans;
  69. struct ls1x_dma_chan chan[];
  70. };
  71. static irqreturn_t ls1x_dma_irq_handler(int irq, void *data);
  72. #define to_ls1x_dma_chan(dchan) \
  73. container_of(dchan, struct ls1x_dma_chan, vc.chan)
  74. #define to_ls1x_dma_desc(d) \
  75. container_of(d, struct ls1x_dma_desc, vd)
  76. static inline struct device *chan2dev(struct dma_chan *chan)
  77. {
  78. return &chan->dev->device;
  79. }
  80. static inline int ls1x_dma_query(struct ls1x_dma_chan *chan,
  81. dma_addr_t *lli_phys)
  82. {
  83. struct dma_chan *dchan = &chan->vc.chan;
  84. int val, ret;
  85. val = *lli_phys & LS1X_DMA_LLI_ADDR_MASK;
  86. val |= LS1X_DMA_ASK_VALID;
  87. val |= dchan->chan_id;
  88. writel(val, chan->reg_base + LS1X_DMA_CTRL);
  89. ret = readl_poll_timeout_atomic(chan->reg_base + LS1X_DMA_CTRL, val,
  90. !(val & LS1X_DMA_ASK_VALID), 0, 3000);
  91. if (ret)
  92. dev_err(chan2dev(dchan), "failed to query DMA\n");
  93. return ret;
  94. }
  95. static inline int ls1x_dma_start(struct ls1x_dma_chan *chan,
  96. dma_addr_t *lli_phys)
  97. {
  98. struct dma_chan *dchan = &chan->vc.chan;
  99. struct device *dev = chan2dev(dchan);
  100. int val, ret;
  101. val = *lli_phys & LS1X_DMA_LLI_ADDR_MASK;
  102. val |= LS1X_DMA_START;
  103. val |= dchan->chan_id;
  104. writel(val, chan->reg_base + LS1X_DMA_CTRL);
  105. ret = readl_poll_timeout(chan->reg_base + LS1X_DMA_CTRL, val,
  106. !(val & LS1X_DMA_START), 0, 1000);
  107. if (!ret)
  108. dev_dbg(dev, "start DMA with lli_phys=%pad\n", lli_phys);
  109. else
  110. dev_err(dev, "failed to start DMA\n");
  111. return ret;
  112. }
  113. static inline void ls1x_dma_stop(struct ls1x_dma_chan *chan)
  114. {
  115. int val = readl(chan->reg_base + LS1X_DMA_CTRL);
  116. writel(val | LS1X_DMA_STOP, chan->reg_base + LS1X_DMA_CTRL);
  117. }
  118. static void ls1x_dma_free_chan_resources(struct dma_chan *dchan)
  119. {
  120. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  121. struct device *dev = chan2dev(dchan);
  122. dma_free_coherent(dev, sizeof(struct ls1x_dma_lli),
  123. chan->curr_lli, chan->curr_lli->phys);
  124. dma_pool_destroy(chan->lli_pool);
  125. chan->lli_pool = NULL;
  126. devm_free_irq(dev, chan->irq, chan);
  127. vchan_free_chan_resources(&chan->vc);
  128. }
  129. static int ls1x_dma_alloc_chan_resources(struct dma_chan *dchan)
  130. {
  131. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  132. struct device *dev = chan2dev(dchan);
  133. dma_addr_t phys;
  134. int ret;
  135. ret = devm_request_irq(dev, chan->irq, ls1x_dma_irq_handler,
  136. IRQF_SHARED, dma_chan_name(dchan), chan);
  137. if (ret) {
  138. dev_err(dev, "failed to request IRQ %d\n", chan->irq);
  139. return ret;
  140. }
  141. chan->lli_pool = dma_pool_create(dma_chan_name(dchan), dev,
  142. sizeof(struct ls1x_dma_lli),
  143. __alignof__(struct ls1x_dma_lli), 0);
  144. if (!chan->lli_pool)
  145. return -ENOMEM;
  146. /* allocate memory for querying the current lli */
  147. dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
  148. chan->curr_lli = dma_alloc_coherent(dev, sizeof(struct ls1x_dma_lli),
  149. &phys, GFP_KERNEL);
  150. if (!chan->curr_lli) {
  151. dma_pool_destroy(chan->lli_pool);
  152. return -ENOMEM;
  153. }
  154. chan->curr_lli->phys = phys;
  155. return 0;
  156. }
  157. static void ls1x_dma_free_desc(struct virt_dma_desc *vd)
  158. {
  159. struct ls1x_dma_desc *desc = to_ls1x_dma_desc(vd);
  160. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(vd->tx.chan);
  161. struct ls1x_dma_lli *lli, *_lli;
  162. list_for_each_entry_safe(lli, _lli, &desc->lli_list, node) {
  163. list_del(&lli->node);
  164. dma_pool_free(chan->lli_pool, lli, lli->phys);
  165. }
  166. kfree(desc);
  167. }
  168. static struct ls1x_dma_desc *ls1x_dma_alloc_desc(void)
  169. {
  170. struct ls1x_dma_desc *desc;
  171. desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
  172. if (!desc)
  173. return NULL;
  174. INIT_LIST_HEAD(&desc->lli_list);
  175. return desc;
  176. }
  177. static int ls1x_dma_prep_lli(struct dma_chan *dchan, struct ls1x_dma_desc *desc,
  178. struct scatterlist *sgl, unsigned int sg_len,
  179. enum dma_transfer_direction dir, bool is_cyclic)
  180. {
  181. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  182. struct ls1x_dma_lli *lli, *prev = NULL, *first = NULL;
  183. struct device *dev = chan2dev(dchan);
  184. struct list_head *pos = NULL;
  185. struct scatterlist *sg;
  186. unsigned int dev_addr, cmd, i;
  187. switch (dir) {
  188. case DMA_MEM_TO_DEV:
  189. dev_addr = chan->dst_addr;
  190. chan->bus_width = chan->dst_addr_width;
  191. cmd = LS1X_DMA_RAM2DEV | LS1X_DMA_INT;
  192. break;
  193. case DMA_DEV_TO_MEM:
  194. dev_addr = chan->src_addr;
  195. chan->bus_width = chan->src_addr_width;
  196. cmd = LS1X_DMA_INT;
  197. break;
  198. default:
  199. dev_err(dev, "unsupported DMA direction: %s\n",
  200. dmaengine_get_direction_text(dir));
  201. return -EINVAL;
  202. }
  203. for_each_sg(sgl, sg, sg_len, i) {
  204. dma_addr_t buf_addr = sg_dma_address(sg);
  205. size_t buf_len = sg_dma_len(sg);
  206. dma_addr_t phys;
  207. if (!is_dma_copy_aligned(dchan->device, buf_addr, 0, buf_len)) {
  208. dev_err(dev, "buffer is not aligned\n");
  209. return -EINVAL;
  210. }
  211. /* allocate HW descriptors */
  212. lli = dma_pool_zalloc(chan->lli_pool, GFP_NOWAIT, &phys);
  213. if (!lli) {
  214. dev_err(dev, "failed to alloc lli %u\n", i);
  215. return -ENOMEM;
  216. }
  217. /* setup HW descriptors */
  218. lli->phys = phys;
  219. lli->hw[LS1X_DMADESC_SADDR] = buf_addr;
  220. lli->hw[LS1X_DMADESC_DADDR] = dev_addr;
  221. lli->hw[LS1X_DMADESC_LENGTH] = buf_len / chan->bus_width;
  222. lli->hw[LS1X_DMADESC_STRIDE] = 0;
  223. lli->hw[LS1X_DMADESC_CYCLES] = 1;
  224. lli->hw[LS1X_DMADESC_CMD] = cmd;
  225. if (prev)
  226. prev->hw[LS1X_DMADESC_NEXT] =
  227. lli->phys | LS1X_DMA_NEXT_VALID;
  228. prev = lli;
  229. if (!first)
  230. first = lli;
  231. list_add_tail(&lli->node, &desc->lli_list);
  232. }
  233. if (is_cyclic) {
  234. lli->hw[LS1X_DMADESC_NEXT] = first->phys | LS1X_DMA_NEXT_VALID;
  235. chan->is_cyclic = is_cyclic;
  236. }
  237. list_for_each(pos, &desc->lli_list) {
  238. lli = list_entry(pos, struct ls1x_dma_lli, node);
  239. print_hex_dump_debug("LLI: ", DUMP_PREFIX_OFFSET, 16, 4,
  240. lli, sizeof(*lli), false);
  241. }
  242. return 0;
  243. }
  244. static struct dma_async_tx_descriptor *
  245. ls1x_dma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
  246. unsigned int sg_len, enum dma_transfer_direction dir,
  247. unsigned long flags, void *context)
  248. {
  249. struct ls1x_dma_desc *desc;
  250. dev_dbg(chan2dev(dchan), "sg_len=%u flags=0x%lx dir=%s\n",
  251. sg_len, flags, dmaengine_get_direction_text(dir));
  252. desc = ls1x_dma_alloc_desc();
  253. if (!desc)
  254. return NULL;
  255. if (ls1x_dma_prep_lli(dchan, desc, sgl, sg_len, dir, false)) {
  256. ls1x_dma_free_desc(&desc->vd);
  257. return NULL;
  258. }
  259. return vchan_tx_prep(to_virt_chan(dchan), &desc->vd, flags);
  260. }
  261. static struct dma_async_tx_descriptor *
  262. ls1x_dma_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t buf_addr,
  263. size_t buf_len, size_t period_len,
  264. enum dma_transfer_direction dir, unsigned long flags)
  265. {
  266. struct ls1x_dma_desc *desc;
  267. struct scatterlist *sgl;
  268. unsigned int sg_len;
  269. unsigned int i;
  270. int ret;
  271. dev_dbg(chan2dev(dchan),
  272. "buf_len=%zu period_len=%zu flags=0x%lx dir=%s\n",
  273. buf_len, period_len, flags, dmaengine_get_direction_text(dir));
  274. desc = ls1x_dma_alloc_desc();
  275. if (!desc)
  276. return NULL;
  277. /* allocate the scatterlist */
  278. sg_len = buf_len / period_len;
  279. sgl = kmalloc_array(sg_len, sizeof(*sgl), GFP_NOWAIT);
  280. if (!sgl)
  281. return NULL;
  282. sg_init_table(sgl, sg_len);
  283. for (i = 0; i < sg_len; ++i) {
  284. sg_set_page(&sgl[i], pfn_to_page(PFN_DOWN(buf_addr)),
  285. period_len, offset_in_page(buf_addr));
  286. sg_dma_address(&sgl[i]) = buf_addr;
  287. sg_dma_len(&sgl[i]) = period_len;
  288. buf_addr += period_len;
  289. }
  290. ret = ls1x_dma_prep_lli(dchan, desc, sgl, sg_len, dir, true);
  291. kfree(sgl);
  292. if (ret) {
  293. ls1x_dma_free_desc(&desc->vd);
  294. return NULL;
  295. }
  296. return vchan_tx_prep(to_virt_chan(dchan), &desc->vd, flags);
  297. }
  298. static int ls1x_dma_slave_config(struct dma_chan *dchan,
  299. struct dma_slave_config *config)
  300. {
  301. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  302. chan->src_addr = config->src_addr;
  303. chan->src_addr_width = config->src_addr_width;
  304. chan->dst_addr = config->dst_addr;
  305. chan->dst_addr_width = config->dst_addr_width;
  306. return 0;
  307. }
  308. static int ls1x_dma_pause(struct dma_chan *dchan)
  309. {
  310. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  311. int ret;
  312. guard(spinlock_irqsave)(&chan->vc.lock);
  313. /* save the current lli */
  314. ret = ls1x_dma_query(chan, &chan->curr_lli->phys);
  315. if (!ret)
  316. ls1x_dma_stop(chan);
  317. return ret;
  318. }
  319. static int ls1x_dma_resume(struct dma_chan *dchan)
  320. {
  321. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  322. guard(spinlock_irqsave)(&chan->vc.lock);
  323. return ls1x_dma_start(chan, &chan->curr_lli->phys);
  324. }
  325. static int ls1x_dma_terminate_all(struct dma_chan *dchan)
  326. {
  327. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  328. struct virt_dma_desc *vd;
  329. LIST_HEAD(head);
  330. ls1x_dma_stop(chan);
  331. scoped_guard(spinlock_irqsave, &chan->vc.lock) {
  332. vd = vchan_next_desc(&chan->vc);
  333. if (vd)
  334. vchan_terminate_vdesc(vd);
  335. vchan_get_all_descriptors(&chan->vc, &head);
  336. }
  337. vchan_dma_desc_free_list(&chan->vc, &head);
  338. return 0;
  339. }
  340. static void ls1x_dma_synchronize(struct dma_chan *dchan)
  341. {
  342. vchan_synchronize(to_virt_chan(dchan));
  343. }
  344. static enum dma_status ls1x_dma_tx_status(struct dma_chan *dchan,
  345. dma_cookie_t cookie,
  346. struct dma_tx_state *state)
  347. {
  348. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  349. struct virt_dma_desc *vd;
  350. enum dma_status status;
  351. size_t bytes = 0;
  352. status = dma_cookie_status(dchan, cookie, state);
  353. if (status == DMA_COMPLETE)
  354. return status;
  355. scoped_guard(spinlock_irqsave, &chan->vc.lock) {
  356. vd = vchan_find_desc(&chan->vc, cookie);
  357. if (vd) {
  358. struct ls1x_dma_desc *desc = to_ls1x_dma_desc(vd);
  359. struct ls1x_dma_lli *lli;
  360. dma_addr_t next_phys;
  361. /* get the current lli */
  362. if (ls1x_dma_query(chan, &chan->curr_lli->phys))
  363. return status;
  364. /* locate the current lli */
  365. next_phys = chan->curr_lli->hw[LS1X_DMADESC_NEXT];
  366. list_for_each_entry(lli, &desc->lli_list, node)
  367. if (lli->hw[LS1X_DMADESC_NEXT] == next_phys)
  368. break;
  369. dev_dbg(chan2dev(dchan), "current lli_phys=%pad",
  370. &lli->phys);
  371. /* count the residues */
  372. list_for_each_entry_from(lli, &desc->lli_list, node)
  373. bytes += lli->hw[LS1X_DMADESC_LENGTH] *
  374. chan->bus_width;
  375. }
  376. }
  377. dma_set_residue(state, bytes);
  378. return status;
  379. }
  380. static void ls1x_dma_issue_pending(struct dma_chan *dchan)
  381. {
  382. struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan);
  383. guard(spinlock_irqsave)(&chan->vc.lock);
  384. if (vchan_issue_pending(&chan->vc)) {
  385. struct virt_dma_desc *vd = vchan_next_desc(&chan->vc);
  386. if (vd) {
  387. struct ls1x_dma_desc *desc = to_ls1x_dma_desc(vd);
  388. struct ls1x_dma_lli *lli;
  389. lli = list_first_entry(&desc->lli_list,
  390. struct ls1x_dma_lli, node);
  391. ls1x_dma_start(chan, &lli->phys);
  392. }
  393. }
  394. }
  395. static irqreturn_t ls1x_dma_irq_handler(int irq, void *data)
  396. {
  397. struct ls1x_dma_chan *chan = data;
  398. struct dma_chan *dchan = &chan->vc.chan;
  399. struct device *dev = chan2dev(dchan);
  400. struct virt_dma_desc *vd;
  401. scoped_guard(spinlock, &chan->vc.lock) {
  402. vd = vchan_next_desc(&chan->vc);
  403. if (!vd) {
  404. dev_warn(dev,
  405. "IRQ %d with no active desc on channel %d\n",
  406. irq, dchan->chan_id);
  407. return IRQ_NONE;
  408. }
  409. if (chan->is_cyclic) {
  410. vchan_cyclic_callback(vd);
  411. } else {
  412. list_del(&vd->node);
  413. vchan_cookie_complete(vd);
  414. }
  415. }
  416. dev_dbg(dev, "DMA IRQ %d on channel %d\n", irq, dchan->chan_id);
  417. return IRQ_HANDLED;
  418. }
  419. static int ls1x_dma_chan_probe(struct platform_device *pdev,
  420. struct ls1x_dma *dma)
  421. {
  422. void __iomem *reg_base;
  423. int id;
  424. reg_base = devm_platform_ioremap_resource(pdev, 0);
  425. if (IS_ERR(reg_base))
  426. return PTR_ERR(reg_base);
  427. for (id = 0; id < dma->nr_chans; id++) {
  428. struct ls1x_dma_chan *chan = &dma->chan[id];
  429. char pdev_irqname[16];
  430. snprintf(pdev_irqname, sizeof(pdev_irqname), "ch%d", id);
  431. chan->irq = platform_get_irq_byname(pdev, pdev_irqname);
  432. if (chan->irq < 0)
  433. return dev_err_probe(&pdev->dev, chan->irq,
  434. "failed to get IRQ for ch%d\n",
  435. id);
  436. chan->reg_base = reg_base;
  437. chan->vc.desc_free = ls1x_dma_free_desc;
  438. vchan_init(&chan->vc, &dma->ddev);
  439. }
  440. return 0;
  441. }
  442. static void ls1x_dma_chan_remove(struct ls1x_dma *dma)
  443. {
  444. int id;
  445. for (id = 0; id < dma->nr_chans; id++) {
  446. struct ls1x_dma_chan *chan = &dma->chan[id];
  447. if (chan->vc.chan.device == &dma->ddev) {
  448. list_del(&chan->vc.chan.device_node);
  449. tasklet_kill(&chan->vc.task);
  450. }
  451. }
  452. }
  453. static int ls1x_dma_probe(struct platform_device *pdev)
  454. {
  455. struct device *dev = &pdev->dev;
  456. struct dma_device *ddev;
  457. struct ls1x_dma *dma;
  458. int ret;
  459. ret = platform_irq_count(pdev);
  460. if (ret <= 0 || ret > LS1X_DMA_MAX_CHANNELS)
  461. return dev_err_probe(dev, -EINVAL,
  462. "Invalid number of IRQ channels: %d\n",
  463. ret);
  464. dma = devm_kzalloc(dev, struct_size(dma, chan, ret), GFP_KERNEL);
  465. if (!dma)
  466. return -ENOMEM;
  467. dma->nr_chans = ret;
  468. /* initialize DMA device */
  469. ddev = &dma->ddev;
  470. ddev->dev = dev;
  471. ddev->copy_align = DMAENGINE_ALIGN_4_BYTES;
  472. ddev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
  473. BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
  474. BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
  475. ddev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
  476. BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
  477. BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
  478. ddev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
  479. ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
  480. ddev->device_alloc_chan_resources = ls1x_dma_alloc_chan_resources;
  481. ddev->device_free_chan_resources = ls1x_dma_free_chan_resources;
  482. ddev->device_prep_slave_sg = ls1x_dma_prep_slave_sg;
  483. ddev->device_prep_dma_cyclic = ls1x_dma_prep_dma_cyclic;
  484. ddev->device_config = ls1x_dma_slave_config;
  485. ddev->device_pause = ls1x_dma_pause;
  486. ddev->device_resume = ls1x_dma_resume;
  487. ddev->device_terminate_all = ls1x_dma_terminate_all;
  488. ddev->device_synchronize = ls1x_dma_synchronize;
  489. ddev->device_tx_status = ls1x_dma_tx_status;
  490. ddev->device_issue_pending = ls1x_dma_issue_pending;
  491. dma_cap_set(DMA_SLAVE, ddev->cap_mask);
  492. INIT_LIST_HEAD(&ddev->channels);
  493. /* initialize DMA channels */
  494. ret = ls1x_dma_chan_probe(pdev, dma);
  495. if (ret)
  496. goto err;
  497. ret = dmaenginem_async_device_register(ddev);
  498. if (ret) {
  499. dev_err(dev, "failed to register DMA device\n");
  500. goto err;
  501. }
  502. ret = of_dma_controller_register(dev->of_node, of_dma_xlate_by_chan_id,
  503. ddev);
  504. if (ret) {
  505. dev_err(dev, "failed to register DMA controller\n");
  506. goto err;
  507. }
  508. platform_set_drvdata(pdev, dma);
  509. dev_info(dev, "Loongson1 DMA driver registered\n");
  510. return 0;
  511. err:
  512. ls1x_dma_chan_remove(dma);
  513. return ret;
  514. }
  515. static void ls1x_dma_remove(struct platform_device *pdev)
  516. {
  517. struct ls1x_dma *dma = platform_get_drvdata(pdev);
  518. of_dma_controller_free(pdev->dev.of_node);
  519. ls1x_dma_chan_remove(dma);
  520. }
  521. static const struct of_device_id ls1x_dma_match[] = {
  522. { .compatible = "loongson,ls1b-apbdma" },
  523. { /* sentinel */ }
  524. };
  525. MODULE_DEVICE_TABLE(of, ls1x_dma_match);
  526. static struct platform_driver ls1x_dma_driver = {
  527. .probe = ls1x_dma_probe,
  528. .remove = ls1x_dma_remove,
  529. .driver = {
  530. .name = KBUILD_MODNAME,
  531. .of_match_table = ls1x_dma_match,
  532. },
  533. };
  534. module_platform_driver(ls1x_dma_driver);
  535. MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
  536. MODULE_DESCRIPTION("Loongson-1 APB DMA Controller driver");
  537. MODULE_LICENSE("GPL");