dma: rcar-audmapp: don't keep audmapp_slave_config for each channeles
[cascardo/linux.git] / drivers / dma / sh / rcar-audmapp.c
1 /*
2  * This is for Renesas R-Car Audio-DMAC-peri-peri.
3  *
4  * Copyright (C) 2014 Renesas Electronics Corporation
5  * Copyright (C) 2014 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6  *
7  * based on the drivers/dma/sh/shdma.c
8  *
9  * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
10  * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
11  * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
12  * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
13  *
14  * This is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  */
20 #include <linux/delay.h>
21 #include <linux/init.h>
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/dmaengine.h>
25 #include <linux/platform_data/dma-rcar-audmapp.h>
26 #include <linux/platform_device.h>
27 #include <linux/shdma-base.h>
28
29 /*
30  * DMA register
31  */
32 #define PDMASAR         0x00
33 #define PDMADAR         0x04
34 #define PDMACHCR        0x0c
35
36 /* PDMACHCR */
37 #define PDMACHCR_DE             (1 << 0)
38
39 #define AUDMAPP_MAX_CHANNELS    29
40
41 /* Default MEMCPY transfer size = 2^2 = 4 bytes */
42 #define LOG2_DEFAULT_XFER_SIZE  2
43 #define AUDMAPP_SLAVE_NUMBER    256
44 #define AUDMAPP_LEN_MAX         (16 * 1024 * 1024)
45
46 struct audmapp_chan {
47         struct shdma_chan shdma_chan;
48         void __iomem *base;
49         dma_addr_t slave_addr;
50         u32 chcr;
51 };
52
53 struct audmapp_device {
54         struct shdma_dev shdma_dev;
55         struct audmapp_pdata *pdata;
56         struct device *dev;
57         void __iomem *chan_reg;
58 };
59
60 struct audmapp_desc {
61         struct shdma_desc shdma_desc;
62         dma_addr_t src;
63         dma_addr_t dst;
64 };
65
66 #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)
68 #define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device,     \
69                                   struct audmapp_device, shdma_dev.dma_dev)
70
71 static void audmapp_write(struct audmapp_chan *auchan, u32 data, u32 reg)
72 {
73         struct audmapp_device *audev = to_dev(auchan);
74         struct device *dev = audev->dev;
75
76         dev_dbg(dev, "w %p : %08x\n", auchan->base + reg, data);
77
78         iowrite32(data, auchan->base + reg);
79 }
80
81 static u32 audmapp_read(struct audmapp_chan *auchan, u32 reg)
82 {
83         return ioread32(auchan->base + reg);
84 }
85
86 static void audmapp_halt(struct shdma_chan *schan)
87 {
88         struct audmapp_chan *auchan = to_chan(schan);
89         int i;
90
91         audmapp_write(auchan, 0, PDMACHCR);
92
93         for (i = 0; i < 1024; i++) {
94                 if (0 == audmapp_read(auchan, PDMACHCR))
95                         return;
96                 udelay(1);
97         }
98 }
99
100 static void audmapp_start_xfer(struct shdma_chan *schan,
101                                struct shdma_desc *sdesc)
102 {
103         struct audmapp_chan *auchan = to_chan(schan);
104         struct audmapp_device *audev = to_dev(auchan);
105         struct audmapp_desc *desc = to_desc(sdesc);
106         struct device *dev = audev->dev;
107         u32 chcr = auchan->chcr | PDMACHCR_DE;
108
109         dev_dbg(dev, "src/dst/chcr = %pad/%pad/%08x\n",
110                 &desc->src, &desc->dst, chcr);
111
112         audmapp_write(auchan, desc->src,        PDMASAR);
113         audmapp_write(auchan, desc->dst,        PDMADAR);
114         audmapp_write(auchan, chcr,     PDMACHCR);
115 }
116
117 static struct audmapp_slave_config *
118 audmapp_find_slave(struct audmapp_chan *auchan, int slave_id)
119 {
120         struct audmapp_device *audev = to_dev(auchan);
121         struct audmapp_pdata *pdata = audev->pdata;
122         struct audmapp_slave_config *cfg;
123         int i;
124
125         if (slave_id >= AUDMAPP_SLAVE_NUMBER)
126                 return NULL;
127
128         for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
129                 if (cfg->slave_id == slave_id)
130                         return cfg;
131
132         return NULL;
133 }
134
135 static int audmapp_set_slave(struct shdma_chan *schan, int slave_id,
136                              dma_addr_t slave_addr, bool try)
137 {
138         struct audmapp_chan *auchan = to_chan(schan);
139         struct audmapp_slave_config *cfg =
140                 audmapp_find_slave(auchan, slave_id);
141
142         if (!cfg)
143                 return -ENODEV;
144         if (try)
145                 return 0;
146
147         auchan->chcr    = cfg->chcr;
148         auchan->slave_addr = slave_addr ? : cfg->dst;
149
150         return 0;
151 }
152
153 static int audmapp_desc_setup(struct shdma_chan *schan,
154                               struct shdma_desc *sdesc,
155                               dma_addr_t src, dma_addr_t dst, size_t *len)
156 {
157         struct audmapp_desc *desc = to_desc(sdesc);
158
159         if (*len > (size_t)AUDMAPP_LEN_MAX)
160                 *len = (size_t)AUDMAPP_LEN_MAX;
161
162         desc->src = src;
163         desc->dst = dst;
164
165         return 0;
166 }
167
168 static void audmapp_setup_xfer(struct shdma_chan *schan,
169                                int slave_id)
170 {
171 }
172
173 static dma_addr_t audmapp_slave_addr(struct shdma_chan *schan)
174 {
175         struct audmapp_chan *auchan = to_chan(schan);
176
177         return auchan->slave_addr;
178 }
179
180 static bool audmapp_channel_busy(struct shdma_chan *schan)
181 {
182         struct audmapp_chan *auchan = to_chan(schan);
183         u32 chcr = audmapp_read(auchan, PDMACHCR);
184
185         return chcr & ~PDMACHCR_DE;
186 }
187
188 static bool audmapp_desc_completed(struct shdma_chan *schan,
189                                    struct shdma_desc *sdesc)
190 {
191         return true;
192 }
193
194 static struct shdma_desc *audmapp_embedded_desc(void *buf, int i)
195 {
196         return &((struct audmapp_desc *)buf)[i].shdma_desc;
197 }
198
199 static const struct shdma_ops audmapp_shdma_ops = {
200         .halt_channel   = audmapp_halt,
201         .desc_setup     = audmapp_desc_setup,
202         .set_slave      = audmapp_set_slave,
203         .start_xfer     = audmapp_start_xfer,
204         .embedded_desc  = audmapp_embedded_desc,
205         .setup_xfer     = audmapp_setup_xfer,
206         .slave_addr     = audmapp_slave_addr,
207         .channel_busy   = audmapp_channel_busy,
208         .desc_completed = audmapp_desc_completed,
209 };
210
211 static int audmapp_chan_probe(struct platform_device *pdev,
212                               struct audmapp_device *audev, int id)
213 {
214         struct shdma_dev *sdev = &audev->shdma_dev;
215         struct audmapp_chan *auchan;
216         struct shdma_chan *schan;
217         struct device *dev = audev->dev;
218
219         auchan = devm_kzalloc(dev, sizeof(*auchan), GFP_KERNEL);
220         if (!auchan)
221                 return -ENOMEM;
222
223         schan = &auchan->shdma_chan;
224         schan->max_xfer_len = AUDMAPP_LEN_MAX;
225
226         shdma_chan_probe(sdev, schan, id);
227
228         auchan->base = audev->chan_reg + 0x20 + (0x10 * id);
229         dev_dbg(dev, "%02d : %p / %p", id, auchan->base, audev->chan_reg);
230
231         return 0;
232 }
233
234 static void audmapp_chan_remove(struct audmapp_device *audev)
235 {
236         struct dma_device *dma_dev = &audev->shdma_dev.dma_dev;
237         struct shdma_chan *schan;
238         int i;
239
240         shdma_for_each_chan(schan, &audev->shdma_dev, i) {
241                 BUG_ON(!schan);
242                 shdma_chan_remove(schan);
243         }
244         dma_dev->chancnt = 0;
245 }
246
247 static int audmapp_probe(struct platform_device *pdev)
248 {
249         struct audmapp_pdata *pdata = pdev->dev.platform_data;
250         struct audmapp_device *audev;
251         struct shdma_dev *sdev;
252         struct dma_device *dma_dev;
253         struct resource *res;
254         int err, i;
255
256         if (!pdata)
257                 return -ENODEV;
258
259         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
260
261         audev = devm_kzalloc(&pdev->dev, sizeof(*audev), GFP_KERNEL);
262         if (!audev)
263                 return -ENOMEM;
264
265         audev->dev      = &pdev->dev;
266         audev->pdata    = pdata;
267         audev->chan_reg = devm_ioremap_resource(&pdev->dev, res);
268         if (IS_ERR(audev->chan_reg))
269                 return PTR_ERR(audev->chan_reg);
270
271         sdev            = &audev->shdma_dev;
272         sdev->ops       = &audmapp_shdma_ops;
273         sdev->desc_size = sizeof(struct audmapp_desc);
274
275         dma_dev                 = &sdev->dma_dev;
276         dma_dev->copy_align     = LOG2_DEFAULT_XFER_SIZE;
277         dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
278
279         err = shdma_init(&pdev->dev, sdev, AUDMAPP_MAX_CHANNELS);
280         if (err < 0)
281                 return err;
282
283         platform_set_drvdata(pdev, audev);
284
285         /* Create DMA Channel */
286         for (i = 0; i < AUDMAPP_MAX_CHANNELS; i++) {
287                 err = audmapp_chan_probe(pdev, audev, i);
288                 if (err)
289                         goto chan_probe_err;
290         }
291
292         err = dma_async_device_register(dma_dev);
293         if (err < 0)
294                 goto chan_probe_err;
295
296         return err;
297
298 chan_probe_err:
299         audmapp_chan_remove(audev);
300         shdma_cleanup(sdev);
301
302         return err;
303 }
304
305 static int audmapp_remove(struct platform_device *pdev)
306 {
307         struct audmapp_device *audev = platform_get_drvdata(pdev);
308         struct dma_device *dma_dev = &audev->shdma_dev.dma_dev;
309
310         dma_async_device_unregister(dma_dev);
311
312         audmapp_chan_remove(audev);
313         shdma_cleanup(&audev->shdma_dev);
314
315         return 0;
316 }
317
318 static struct platform_driver audmapp_driver = {
319         .probe          = audmapp_probe,
320         .remove         = audmapp_remove,
321         .driver         = {
322                 .owner  = THIS_MODULE,
323                 .name   = "rcar-audmapp-engine",
324         },
325 };
326 module_platform_driver(audmapp_driver);
327
328 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
329 MODULE_DESCRIPTION("Renesas R-Car Audio DMAC peri-peri driver");
330 MODULE_LICENSE("GPL");