aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/mmp_pdma.c
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2013-08-10 12:52:19 -0400
committerVinod Koul <vinod.koul@intel.com>2013-08-14 04:25:15 -0400
commita9a7cf08bd080289bbf01ceed9369220f0715684 (patch)
tree5ee01d6efb976c7aa758aa716a82ab43d657db5e /drivers/dma/mmp_pdma.c
parent13b3006b8ebd60926a60fc378ff6fe8affa9a194 (diff)
dma: mmp_pdma: make the controller a DMA provider
This patch makes the mmp_pdma controller able to provide DMA resources in DT environments by providing an dma xlate function. of_dma_simple_xlate() isn't used here, because if fails to handle multiple different DMA engines or several instances of the same controller. Instead, a private implementation is provided that makes use of the newly introduced dma_get_slave_channel() call. Signed-off-by: Daniel Mack <zonque@gmail.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/mmp_pdma.c')
-rw-r--r--drivers/dma/mmp_pdma.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index dd024d4759e7..76884c48ea85 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -18,6 +18,7 @@
18#include <linux/platform_data/mmp_dma.h> 18#include <linux/platform_data/mmp_dma.h>
19#include <linux/dmapool.h> 19#include <linux/dmapool.h>
20#include <linux/of_device.h> 20#include <linux/of_device.h>
21#include <linux/of_dma.h>
21#include <linux/of.h> 22#include <linux/of.h>
22#include <linux/dma/mmp-pdma.h> 23#include <linux/dma/mmp-pdma.h>
23 24
@@ -777,6 +778,39 @@ static struct of_device_id mmp_pdma_dt_ids[] = {
777}; 778};
778MODULE_DEVICE_TABLE(of, mmp_pdma_dt_ids); 779MODULE_DEVICE_TABLE(of, mmp_pdma_dt_ids);
779 780
781static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec,
782 struct of_dma *ofdma)
783{
784 struct mmp_pdma_device *d = ofdma->of_dma_data;
785 struct dma_chan *chan, *candidate;
786
787retry:
788 candidate = NULL;
789
790 /* walk the list of channels registered with the current instance and
791 * find one that is currently unused */
792 list_for_each_entry(chan, &d->device.channels, device_node)
793 if (chan->client_count == 0) {
794 candidate = chan;
795 break;
796 }
797
798 if (!candidate)
799 return NULL;
800
801 /* dma_get_slave_channel will return NULL if we lost a race between
802 * the lookup and the reservation */
803 chan = dma_get_slave_channel(candidate);
804
805 if (chan) {
806 struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan);
807 c->drcmr = dma_spec->args[0];
808 return chan;
809 }
810
811 goto retry;
812}
813
780static int mmp_pdma_probe(struct platform_device *op) 814static int mmp_pdma_probe(struct platform_device *op)
781{ 815{
782 struct mmp_pdma_device *pdev; 816 struct mmp_pdma_device *pdev;
@@ -863,6 +897,16 @@ static int mmp_pdma_probe(struct platform_device *op)
863 return ret; 897 return ret;
864 } 898 }
865 899
900 if (op->dev.of_node) {
901 /* Device-tree DMA controller registration */
902 ret = of_dma_controller_register(op->dev.of_node,
903 mmp_pdma_dma_xlate, pdev);
904 if (ret < 0) {
905 dev_err(&op->dev, "of_dma_controller_register failed\n");
906 return ret;
907 }
908 }
909
866 dev_info(pdev->device.dev, "initialized\n"); 910 dev_info(pdev->device.dev, "initialized\n");
867 return 0; 911 return 0;
868} 912}