diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2013-02-25 20:42:09 -0500 |
---|---|---|
committer | Shawn Guo <shawn.guo@linaro.org> | 2013-04-04 09:22:43 -0400 |
commit | d84f638b037fcd132ecf6f09f5b8ccf82278b9ee (patch) | |
tree | b515de0f0bcabd60c36e04cb54b056eb2187600a /drivers/dma/mxs-dma.c | |
parent | aaa20517c0880d021c4839eb172e8cfc03c43e21 (diff) |
dma: mxs-dma: move to generic device tree binding
Update mxs-dma driver to adopt generic DMA device tree binding. It
calls of_dma_controller_register() with mxs specific of_dma_xlate to
get the generic DMA device tree helper support. Then DMA clients only
need to call dma_request_slave_channel() for requesting a DMA channel
from dmaengine.
The existing way of requesting channel, clients directly call
dma_request_channel(), still work there, and will be removed after
all mxs-dma clients get converted to generic DMA device tree helper.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/dma/mxs-dma.c')
-rw-r--r-- | drivers/dma/mxs-dma.c | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index bb86f7ff55d9..b48a79c28845 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/stmp_device.h> | 27 | #include <linux/stmp_device.h> |
28 | #include <linux/of.h> | 28 | #include <linux/of.h> |
29 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
30 | #include <linux/of_dma.h> | ||
30 | 31 | ||
31 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
32 | 33 | ||
@@ -139,6 +140,8 @@ struct mxs_dma_engine { | |||
139 | struct dma_device dma_device; | 140 | struct dma_device dma_device; |
140 | struct device_dma_parameters dma_parms; | 141 | struct device_dma_parameters dma_parms; |
141 | struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; | 142 | struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; |
143 | struct platform_device *pdev; | ||
144 | unsigned int nr_channels; | ||
142 | }; | 145 | }; |
143 | 146 | ||
144 | struct mxs_dma_type { | 147 | struct mxs_dma_type { |
@@ -350,10 +353,8 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan) | |||
350 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; | 353 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; |
351 | int ret; | 354 | int ret; |
352 | 355 | ||
353 | if (!data) | 356 | if (data) |
354 | return -EINVAL; | 357 | mxs_chan->chan_irq = data->chan_irq; |
355 | |||
356 | mxs_chan->chan_irq = data->chan_irq; | ||
357 | 358 | ||
358 | mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, | 359 | mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, |
359 | CCW_BLOCK_SIZE, &mxs_chan->ccw_phys, | 360 | CCW_BLOCK_SIZE, &mxs_chan->ccw_phys, |
@@ -665,8 +666,55 @@ err_out: | |||
665 | return ret; | 666 | return ret; |
666 | } | 667 | } |
667 | 668 | ||
669 | struct mxs_dma_filter_param { | ||
670 | struct device_node *of_node; | ||
671 | unsigned int chan_id; | ||
672 | }; | ||
673 | |||
674 | static bool mxs_dma_filter_fn(struct dma_chan *chan, void *fn_param) | ||
675 | { | ||
676 | struct mxs_dma_filter_param *param = fn_param; | ||
677 | struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); | ||
678 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; | ||
679 | int chan_irq; | ||
680 | |||
681 | if (mxs_dma->dma_device.dev->of_node != param->of_node) | ||
682 | return false; | ||
683 | |||
684 | if (chan->chan_id != param->chan_id) | ||
685 | return false; | ||
686 | |||
687 | chan_irq = platform_get_irq(mxs_dma->pdev, param->chan_id); | ||
688 | if (chan_irq < 0) | ||
689 | return false; | ||
690 | |||
691 | mxs_chan->chan_irq = chan_irq; | ||
692 | |||
693 | return true; | ||
694 | } | ||
695 | |||
696 | struct dma_chan *mxs_dma_xlate(struct of_phandle_args *dma_spec, | ||
697 | struct of_dma *ofdma) | ||
698 | { | ||
699 | struct mxs_dma_engine *mxs_dma = ofdma->of_dma_data; | ||
700 | dma_cap_mask_t mask = mxs_dma->dma_device.cap_mask; | ||
701 | struct mxs_dma_filter_param param; | ||
702 | |||
703 | if (dma_spec->args_count != 1) | ||
704 | return NULL; | ||
705 | |||
706 | param.of_node = ofdma->of_node; | ||
707 | param.chan_id = dma_spec->args[0]; | ||
708 | |||
709 | if (param.chan_id >= mxs_dma->nr_channels) | ||
710 | return NULL; | ||
711 | |||
712 | return dma_request_channel(mask, mxs_dma_filter_fn, ¶m); | ||
713 | } | ||
714 | |||
668 | static int __init mxs_dma_probe(struct platform_device *pdev) | 715 | static int __init mxs_dma_probe(struct platform_device *pdev) |
669 | { | 716 | { |
717 | struct device_node *np = pdev->dev.of_node; | ||
670 | const struct platform_device_id *id_entry; | 718 | const struct platform_device_id *id_entry; |
671 | const struct of_device_id *of_id; | 719 | const struct of_device_id *of_id; |
672 | const struct mxs_dma_type *dma_type; | 720 | const struct mxs_dma_type *dma_type; |
@@ -678,6 +726,12 @@ static int __init mxs_dma_probe(struct platform_device *pdev) | |||
678 | if (!mxs_dma) | 726 | if (!mxs_dma) |
679 | return -ENOMEM; | 727 | return -ENOMEM; |
680 | 728 | ||
729 | ret = of_property_read_u32(np, "dma-channels", &mxs_dma->nr_channels); | ||
730 | if (ret) { | ||
731 | dev_err(&pdev->dev, "failed to read dma-channels\n"); | ||
732 | return ret; | ||
733 | } | ||
734 | |||
681 | of_id = of_match_device(mxs_dma_dt_ids, &pdev->dev); | 735 | of_id = of_match_device(mxs_dma_dt_ids, &pdev->dev); |
682 | if (of_id) | 736 | if (of_id) |
683 | id_entry = of_id->data; | 737 | id_entry = of_id->data; |
@@ -723,6 +777,7 @@ static int __init mxs_dma_probe(struct platform_device *pdev) | |||
723 | if (ret) | 777 | if (ret) |
724 | return ret; | 778 | return ret; |
725 | 779 | ||
780 | mxs_dma->pdev = pdev; | ||
726 | mxs_dma->dma_device.dev = &pdev->dev; | 781 | mxs_dma->dma_device.dev = &pdev->dev; |
727 | 782 | ||
728 | /* mxs_dma gets 65535 bytes maximum sg size */ | 783 | /* mxs_dma gets 65535 bytes maximum sg size */ |
@@ -743,6 +798,13 @@ static int __init mxs_dma_probe(struct platform_device *pdev) | |||
743 | return ret; | 798 | return ret; |
744 | } | 799 | } |
745 | 800 | ||
801 | ret = of_dma_controller_register(np, mxs_dma_xlate, mxs_dma); | ||
802 | if (ret) { | ||
803 | dev_err(mxs_dma->dma_device.dev, | ||
804 | "failed to register controller\n"); | ||
805 | dma_async_device_unregister(&mxs_dma->dma_device); | ||
806 | } | ||
807 | |||
746 | dev_info(mxs_dma->dma_device.dev, "initialized\n"); | 808 | dev_info(mxs_dma->dma_device.dev, "initialized\n"); |
747 | 809 | ||
748 | return 0; | 810 | return 0; |