.. | .. |
---|
24 | 24 | #include <linux/of_device.h> |
---|
25 | 25 | #include <linux/of_dma.h> |
---|
26 | 26 | #include <linux/list.h> |
---|
| 27 | +#include <linux/dma/mxs-dma.h> |
---|
27 | 28 | |
---|
28 | 29 | #include <asm/irq.h> |
---|
29 | 30 | |
---|
.. | .. |
---|
77 | 78 | #define BM_CCW_COMMAND (3 << 0) |
---|
78 | 79 | #define CCW_CHAIN (1 << 2) |
---|
79 | 80 | #define CCW_IRQ (1 << 3) |
---|
| 81 | +#define CCW_WAIT4RDY (1 << 5) |
---|
80 | 82 | #define CCW_DEC_SEM (1 << 6) |
---|
81 | 83 | #define CCW_WAIT4END (1 << 7) |
---|
82 | 84 | #define CCW_HALT_ON_TERM (1 << 8) |
---|
.. | .. |
---|
139 | 141 | void __iomem *base; |
---|
140 | 142 | struct clk *clk; |
---|
141 | 143 | struct dma_device dma_device; |
---|
142 | | - struct device_dma_parameters dma_parms; |
---|
143 | 144 | struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; |
---|
144 | 145 | struct platform_device *pdev; |
---|
145 | 146 | unsigned int nr_channels; |
---|
.. | .. |
---|
166 | 167 | } |
---|
167 | 168 | }; |
---|
168 | 169 | |
---|
169 | | -static const struct platform_device_id mxs_dma_ids[] = { |
---|
170 | | - { |
---|
171 | | - .name = "imx23-dma-apbh", |
---|
172 | | - .driver_data = (kernel_ulong_t) &mxs_dma_types[0], |
---|
173 | | - }, { |
---|
174 | | - .name = "imx23-dma-apbx", |
---|
175 | | - .driver_data = (kernel_ulong_t) &mxs_dma_types[1], |
---|
176 | | - }, { |
---|
177 | | - .name = "imx28-dma-apbh", |
---|
178 | | - .driver_data = (kernel_ulong_t) &mxs_dma_types[2], |
---|
179 | | - }, { |
---|
180 | | - .name = "imx28-dma-apbx", |
---|
181 | | - .driver_data = (kernel_ulong_t) &mxs_dma_types[3], |
---|
182 | | - }, { |
---|
183 | | - /* end of list */ |
---|
184 | | - } |
---|
185 | | -}; |
---|
186 | | - |
---|
187 | 170 | static const struct of_device_id mxs_dma_dt_ids[] = { |
---|
188 | | - { .compatible = "fsl,imx23-dma-apbh", .data = &mxs_dma_ids[0], }, |
---|
189 | | - { .compatible = "fsl,imx23-dma-apbx", .data = &mxs_dma_ids[1], }, |
---|
190 | | - { .compatible = "fsl,imx28-dma-apbh", .data = &mxs_dma_ids[2], }, |
---|
191 | | - { .compatible = "fsl,imx28-dma-apbx", .data = &mxs_dma_ids[3], }, |
---|
| 171 | + { .compatible = "fsl,imx23-dma-apbh", .data = &mxs_dma_types[0], }, |
---|
| 172 | + { .compatible = "fsl,imx23-dma-apbx", .data = &mxs_dma_types[1], }, |
---|
| 173 | + { .compatible = "fsl,imx28-dma-apbh", .data = &mxs_dma_types[2], }, |
---|
| 174 | + { .compatible = "fsl,imx28-dma-apbx", .data = &mxs_dma_types[3], }, |
---|
192 | 175 | { /* sentinel */ } |
---|
193 | 176 | }; |
---|
194 | 177 | MODULE_DEVICE_TABLE(of, mxs_dma_dt_ids); |
---|
.. | .. |
---|
318 | 301 | return dma_cookie_assign(tx); |
---|
319 | 302 | } |
---|
320 | 303 | |
---|
321 | | -static void mxs_dma_tasklet(unsigned long data) |
---|
| 304 | +static void mxs_dma_tasklet(struct tasklet_struct *t) |
---|
322 | 305 | { |
---|
323 | | - struct mxs_dma_chan *mxs_chan = (struct mxs_dma_chan *) data; |
---|
| 306 | + struct mxs_dma_chan *mxs_chan = from_tasklet(mxs_chan, t, tasklet); |
---|
324 | 307 | |
---|
325 | 308 | dmaengine_desc_get_callback_invoke(&mxs_chan->desc, NULL); |
---|
326 | 309 | } |
---|
.. | .. |
---|
416 | 399 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; |
---|
417 | 400 | int ret; |
---|
418 | 401 | |
---|
419 | | - mxs_chan->ccw = dma_zalloc_coherent(mxs_dma->dma_device.dev, |
---|
420 | | - CCW_BLOCK_SIZE, |
---|
421 | | - &mxs_chan->ccw_phys, GFP_KERNEL); |
---|
| 402 | + mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, |
---|
| 403 | + CCW_BLOCK_SIZE, |
---|
| 404 | + &mxs_chan->ccw_phys, GFP_KERNEL); |
---|
422 | 405 | if (!mxs_chan->ccw) { |
---|
423 | 406 | ret = -ENOMEM; |
---|
424 | 407 | goto err_alloc; |
---|
.. | .. |
---|
477 | 460 | * ...... |
---|
478 | 461 | * ->device_prep_slave_sg(0); |
---|
479 | 462 | * ...... |
---|
480 | | - * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
---|
| 463 | + * ->device_prep_slave_sg(DMA_CTRL_ACK); |
---|
481 | 464 | * ...... |
---|
482 | 465 | * [3] If there are more than two DMA commands in the DMA chain, the code |
---|
483 | 466 | * should be: |
---|
484 | 467 | * ...... |
---|
485 | 468 | * ->device_prep_slave_sg(0); // First |
---|
486 | 469 | * ...... |
---|
487 | | - * ->device_prep_slave_sg(DMA_PREP_INTERRUPT [| DMA_CTRL_ACK]); |
---|
| 470 | + * ->device_prep_slave_sg(DMA_CTRL_ACK]); |
---|
488 | 471 | * ...... |
---|
489 | | - * ->device_prep_slave_sg(DMA_PREP_INTERRUPT | DMA_CTRL_ACK); // Last |
---|
| 472 | + * ->device_prep_slave_sg(DMA_CTRL_ACK); // Last |
---|
490 | 473 | * ...... |
---|
491 | 474 | */ |
---|
492 | 475 | static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg( |
---|
.. | .. |
---|
500 | 483 | struct scatterlist *sg; |
---|
501 | 484 | u32 i, j; |
---|
502 | 485 | u32 *pio; |
---|
503 | | - bool append = flags & DMA_PREP_INTERRUPT; |
---|
504 | | - int idx = append ? mxs_chan->desc_count : 0; |
---|
| 486 | + int idx = 0; |
---|
505 | 487 | |
---|
506 | | - if (mxs_chan->status == DMA_IN_PROGRESS && !append) |
---|
507 | | - return NULL; |
---|
| 488 | + if (mxs_chan->status == DMA_IN_PROGRESS) |
---|
| 489 | + idx = mxs_chan->desc_count; |
---|
508 | 490 | |
---|
509 | | - if (sg_len + (append ? idx : 0) > NUM_CCW) { |
---|
| 491 | + if (sg_len + idx > NUM_CCW) { |
---|
510 | 492 | dev_err(mxs_dma->dma_device.dev, |
---|
511 | 493 | "maximum number of sg exceeded: %d > %d\n", |
---|
512 | 494 | sg_len, NUM_CCW); |
---|
.. | .. |
---|
520 | 502 | * If the sg is prepared with append flag set, the sg |
---|
521 | 503 | * will be appended to the last prepared sg. |
---|
522 | 504 | */ |
---|
523 | | - if (append) { |
---|
| 505 | + if (idx) { |
---|
524 | 506 | BUG_ON(idx < 1); |
---|
525 | 507 | ccw = &mxs_chan->ccw[idx - 1]; |
---|
526 | 508 | ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx; |
---|
.. | .. |
---|
541 | 523 | ccw->bits = 0; |
---|
542 | 524 | ccw->bits |= CCW_IRQ; |
---|
543 | 525 | ccw->bits |= CCW_DEC_SEM; |
---|
544 | | - if (flags & DMA_CTRL_ACK) |
---|
| 526 | + if (flags & MXS_DMA_CTRL_WAIT4END) |
---|
545 | 527 | ccw->bits |= CCW_WAIT4END; |
---|
546 | 528 | ccw->bits |= CCW_HALT_ON_TERM; |
---|
547 | 529 | ccw->bits |= CCW_TERM_FLUSH; |
---|
548 | 530 | ccw->bits |= BF_CCW(sg_len, PIO_NUM); |
---|
549 | 531 | ccw->bits |= BF_CCW(MXS_DMA_CMD_NO_XFER, COMMAND); |
---|
| 532 | + if (flags & MXS_DMA_CTRL_WAIT4RDY) |
---|
| 533 | + ccw->bits |= CCW_WAIT4RDY; |
---|
550 | 534 | } else { |
---|
551 | 535 | for_each_sg(sgl, sg, sg_len, i) { |
---|
552 | 536 | if (sg_dma_len(sg) > MAX_XFER_BYTES) { |
---|
.. | .. |
---|
573 | 557 | ccw->bits &= ~CCW_CHAIN; |
---|
574 | 558 | ccw->bits |= CCW_IRQ; |
---|
575 | 559 | ccw->bits |= CCW_DEC_SEM; |
---|
576 | | - if (flags & DMA_CTRL_ACK) |
---|
| 560 | + if (flags & MXS_DMA_CTRL_WAIT4END) |
---|
577 | 561 | ccw->bits |= CCW_WAIT4END; |
---|
578 | 562 | } |
---|
579 | 563 | } |
---|
.. | .. |
---|
686 | 670 | return mxs_chan->status; |
---|
687 | 671 | } |
---|
688 | 672 | |
---|
689 | | -static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) |
---|
| 673 | +static int mxs_dma_init(struct mxs_dma_engine *mxs_dma) |
---|
690 | 674 | { |
---|
691 | 675 | int ret; |
---|
692 | 676 | |
---|
.. | .. |
---|
716 | 700 | } |
---|
717 | 701 | |
---|
718 | 702 | struct mxs_dma_filter_param { |
---|
719 | | - struct device_node *of_node; |
---|
720 | 703 | unsigned int chan_id; |
---|
721 | 704 | }; |
---|
722 | 705 | |
---|
.. | .. |
---|
726 | 709 | struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); |
---|
727 | 710 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; |
---|
728 | 711 | int chan_irq; |
---|
729 | | - |
---|
730 | | - if (mxs_dma->dma_device.dev->of_node != param->of_node) |
---|
731 | | - return false; |
---|
732 | 712 | |
---|
733 | 713 | if (chan->chan_id != param->chan_id) |
---|
734 | 714 | return false; |
---|
.. | .. |
---|
752 | 732 | if (dma_spec->args_count != 1) |
---|
753 | 733 | return NULL; |
---|
754 | 734 | |
---|
755 | | - param.of_node = ofdma->of_node; |
---|
756 | 735 | param.chan_id = dma_spec->args[0]; |
---|
757 | 736 | |
---|
758 | 737 | if (param.chan_id >= mxs_dma->nr_channels) |
---|
759 | 738 | return NULL; |
---|
760 | 739 | |
---|
761 | | - return dma_request_channel(mask, mxs_dma_filter_fn, ¶m); |
---|
| 740 | + return __dma_request_channel(&mask, mxs_dma_filter_fn, ¶m, |
---|
| 741 | + ofdma->of_node); |
---|
762 | 742 | } |
---|
763 | 743 | |
---|
764 | | -static int __init mxs_dma_probe(struct platform_device *pdev) |
---|
| 744 | +static int mxs_dma_probe(struct platform_device *pdev) |
---|
765 | 745 | { |
---|
766 | 746 | struct device_node *np = pdev->dev.of_node; |
---|
767 | | - const struct platform_device_id *id_entry; |
---|
768 | | - const struct of_device_id *of_id; |
---|
769 | 747 | const struct mxs_dma_type *dma_type; |
---|
770 | 748 | struct mxs_dma_engine *mxs_dma; |
---|
771 | 749 | struct resource *iores; |
---|
.. | .. |
---|
781 | 759 | return ret; |
---|
782 | 760 | } |
---|
783 | 761 | |
---|
784 | | - of_id = of_match_device(mxs_dma_dt_ids, &pdev->dev); |
---|
785 | | - if (of_id) |
---|
786 | | - id_entry = of_id->data; |
---|
787 | | - else |
---|
788 | | - id_entry = platform_get_device_id(pdev); |
---|
789 | | - |
---|
790 | | - dma_type = (struct mxs_dma_type *)id_entry->driver_data; |
---|
| 762 | + dma_type = (struct mxs_dma_type *)of_device_get_match_data(&pdev->dev); |
---|
791 | 763 | mxs_dma->type = dma_type->type; |
---|
792 | 764 | mxs_dma->dev_id = dma_type->id; |
---|
793 | 765 | |
---|
.. | .. |
---|
813 | 785 | mxs_chan->chan.device = &mxs_dma->dma_device; |
---|
814 | 786 | dma_cookie_init(&mxs_chan->chan); |
---|
815 | 787 | |
---|
816 | | - tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet, |
---|
817 | | - (unsigned long) mxs_chan); |
---|
| 788 | + tasklet_setup(&mxs_chan->tasklet, mxs_dma_tasklet); |
---|
818 | 789 | |
---|
819 | 790 | |
---|
820 | 791 | /* Add the channel to mxs_chan list */ |
---|
.. | .. |
---|
830 | 801 | mxs_dma->dma_device.dev = &pdev->dev; |
---|
831 | 802 | |
---|
832 | 803 | /* mxs_dma gets 65535 bytes maximum sg size */ |
---|
833 | | - mxs_dma->dma_device.dev->dma_parms = &mxs_dma->dma_parms; |
---|
834 | 804 | dma_set_max_seg_size(mxs_dma->dma_device.dev, MAX_XFER_BYTES); |
---|
835 | 805 | |
---|
836 | 806 | mxs_dma->dma_device.device_alloc_chan_resources = mxs_dma_alloc_chan_resources; |
---|
.. | .. |
---|
847 | 817 | mxs_dma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; |
---|
848 | 818 | mxs_dma->dma_device.device_issue_pending = mxs_dma_enable_chan; |
---|
849 | 819 | |
---|
850 | | - ret = dma_async_device_register(&mxs_dma->dma_device); |
---|
| 820 | + ret = dmaenginem_async_device_register(&mxs_dma->dma_device); |
---|
851 | 821 | if (ret) { |
---|
852 | 822 | dev_err(mxs_dma->dma_device.dev, "unable to register\n"); |
---|
853 | 823 | return ret; |
---|
.. | .. |
---|
857 | 827 | if (ret) { |
---|
858 | 828 | dev_err(mxs_dma->dma_device.dev, |
---|
859 | 829 | "failed to register controller\n"); |
---|
860 | | - dma_async_device_unregister(&mxs_dma->dma_device); |
---|
861 | 830 | } |
---|
862 | 831 | |
---|
863 | 832 | dev_info(mxs_dma->dma_device.dev, "initialized\n"); |
---|
.. | .. |
---|
870 | 839 | .name = "mxs-dma", |
---|
871 | 840 | .of_match_table = mxs_dma_dt_ids, |
---|
872 | 841 | }, |
---|
873 | | - .id_table = mxs_dma_ids, |
---|
| 842 | + .probe = mxs_dma_probe, |
---|
874 | 843 | }; |
---|
875 | 844 | |
---|
876 | | -static int __init mxs_dma_module_init(void) |
---|
877 | | -{ |
---|
878 | | - return platform_driver_probe(&mxs_dma_driver, mxs_dma_probe); |
---|
879 | | -} |
---|
880 | | -subsys_initcall(mxs_dma_module_init); |
---|
| 845 | +builtin_platform_driver(mxs_dma_driver); |
---|