aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2014-06-18 04:59:44 -0400
committerSimon Horman <horms+renesas@verge.net.au>2014-07-11 07:35:08 -0400
commitcaf18c27ddb2fb8ae2a7591b908e7efb7484e459 (patch)
treead20e75301fcaa0f95b4826b18118cb4c8b2404a /drivers/dma
parent75bfa5f60a368b1ccacaf71bfc0376b8d9eb2e9f (diff)
dma: rcar-audmapp: add DT support
This patch adds DT support to Audio DMAC peri peri driver. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> [horms+renesas@verge.net.au: Do not add trailing blank line to rcar-audmapp.txt] [horms+renesas@verge.net.au: squashed patch to add NULL terminater to audmapp_of_match] Signed-off-by: Simon Horman <horms+renesas@verge.net.au> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/sh/rcar-audmapp.c72
1 files changed, 58 insertions, 14 deletions
diff --git a/drivers/dma/sh/rcar-audmapp.c b/drivers/dma/sh/rcar-audmapp.c
index dd0077519e3e..dabbf0aba2e9 100644
--- a/drivers/dma/sh/rcar-audmapp.c
+++ b/drivers/dma/sh/rcar-audmapp.c
@@ -22,6 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/dmaengine.h> 24#include <linux/dmaengine.h>
25#include <linux/of_dma.h>
25#include <linux/platform_data/dma-rcar-audmapp.h> 26#include <linux/platform_data/dma-rcar-audmapp.h>
26#include <linux/platform_device.h> 27#include <linux/platform_device.h>
27#include <linux/shdma-base.h> 28#include <linux/shdma-base.h>
@@ -63,6 +64,8 @@ struct audmapp_desc {
63 dma_addr_t dst; 64 dma_addr_t dst;
64}; 65};
65 66
67#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
68
66#define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan) 69#define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan)
67#define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc) 70#define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc)
68#define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device, \ 71#define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device, \
@@ -114,38 +117,50 @@ static void audmapp_start_xfer(struct shdma_chan *schan,
114 audmapp_write(auchan, chcr, PDMACHCR); 117 audmapp_write(auchan, chcr, PDMACHCR);
115} 118}
116 119
117static struct audmapp_slave_config * 120static void audmapp_get_config(struct audmapp_chan *auchan, int slave_id,
118audmapp_find_slave(struct audmapp_chan *auchan, int slave_id) 121 u32 *chcr, dma_addr_t *dst)
119{ 122{
120 struct audmapp_device *audev = to_dev(auchan); 123 struct audmapp_device *audev = to_dev(auchan);
121 struct audmapp_pdata *pdata = audev->pdata; 124 struct audmapp_pdata *pdata = audev->pdata;
122 struct audmapp_slave_config *cfg; 125 struct audmapp_slave_config *cfg;
123 int i; 126 int i;
124 127
128 *chcr = 0;
129 *dst = 0;
130
131 if (!pdata) { /* DT */
132 *chcr = ((u32)slave_id) << 16;
133 auchan->shdma_chan.slave_id = (slave_id) >> 8;
134 return;
135 }
136
137 /* non-DT */
138
125 if (slave_id >= AUDMAPP_SLAVE_NUMBER) 139 if (slave_id >= AUDMAPP_SLAVE_NUMBER)
126 return NULL; 140 return;
127 141
128 for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) 142 for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
129 if (cfg->slave_id == slave_id) 143 if (cfg->slave_id == slave_id) {
130 return cfg; 144 *chcr = cfg->chcr;
131 145 *dst = cfg->dst;
132 return NULL; 146 break;
147 }
133} 148}
134 149
135static int audmapp_set_slave(struct shdma_chan *schan, int slave_id, 150static int audmapp_set_slave(struct shdma_chan *schan, int slave_id,
136 dma_addr_t slave_addr, bool try) 151 dma_addr_t slave_addr, bool try)
137{ 152{
138 struct audmapp_chan *auchan = to_chan(schan); 153 struct audmapp_chan *auchan = to_chan(schan);
139 struct audmapp_slave_config *cfg = 154 u32 chcr;
140 audmapp_find_slave(auchan, slave_id); 155 dma_addr_t dst;
156
157 audmapp_get_config(auchan, slave_id, &chcr, &dst);
141 158
142 if (!cfg)
143 return -ENODEV;
144 if (try) 159 if (try)
145 return 0; 160 return 0;
146 161
147 auchan->chcr = cfg->chcr; 162 auchan->chcr = chcr;
148 auchan->slave_addr = slave_addr ? : cfg->dst; 163 auchan->slave_addr = slave_addr ? : dst;
149 164
150 return 0; 165 return 0;
151} 166}
@@ -244,16 +259,39 @@ static void audmapp_chan_remove(struct audmapp_device *audev)
244 dma_dev->chancnt = 0; 259 dma_dev->chancnt = 0;
245} 260}
246 261
262static struct dma_chan *audmapp_of_xlate(struct of_phandle_args *dma_spec,
263 struct of_dma *ofdma)
264{
265 dma_cap_mask_t mask;
266 struct dma_chan *chan;
267 u32 chcr = dma_spec->args[0];
268
269 if (dma_spec->args_count != 1)
270 return NULL;
271
272 dma_cap_zero(mask);
273 dma_cap_set(DMA_SLAVE, mask);
274
275 chan = dma_request_channel(mask, shdma_chan_filter, NULL);
276 if (chan)
277 to_shdma_chan(chan)->hw_req = chcr;
278
279 return chan;
280}
281
247static int audmapp_probe(struct platform_device *pdev) 282static int audmapp_probe(struct platform_device *pdev)
248{ 283{
249 struct audmapp_pdata *pdata = pdev->dev.platform_data; 284 struct audmapp_pdata *pdata = pdev->dev.platform_data;
285 struct device_node *np = pdev->dev.of_node;
250 struct audmapp_device *audev; 286 struct audmapp_device *audev;
251 struct shdma_dev *sdev; 287 struct shdma_dev *sdev;
252 struct dma_device *dma_dev; 288 struct dma_device *dma_dev;
253 struct resource *res; 289 struct resource *res;
254 int err, i; 290 int err, i;
255 291
256 if (!pdata) 292 if (np)
293 of_dma_controller_register(np, audmapp_of_xlate, pdev);
294 else if (!pdata)
257 return -ENODEV; 295 return -ENODEV;
258 296
259 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 297 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -315,12 +353,18 @@ static int audmapp_remove(struct platform_device *pdev)
315 return 0; 353 return 0;
316} 354}
317 355
356static const struct of_device_id audmapp_of_match[] = {
357 { .compatible = "renesas,rcar-audmapp", },
358 {},
359};
360
318static struct platform_driver audmapp_driver = { 361static struct platform_driver audmapp_driver = {
319 .probe = audmapp_probe, 362 .probe = audmapp_probe,
320 .remove = audmapp_remove, 363 .remove = audmapp_remove,
321 .driver = { 364 .driver = {
322 .owner = THIS_MODULE, 365 .owner = THIS_MODULE,
323 .name = "rcar-audmapp-engine", 366 .name = "rcar-audmapp-engine",
367 .of_match_table = audmapp_of_match,
324 }, 368 },
325}; 369};
326module_platform_driver(audmapp_driver); 370module_platform_driver(audmapp_driver);