| .. | .. |
|---|
| 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); |
|---|