2 * Renesas SUDMAC support
4 * Copyright (C) 2013 Renesas Solutions Corp.
6 * based on drivers/dma/sh/shdma.c:
7 * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
8 * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
9 * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
10 * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
12 * This is free software; you can redistribute it and/or modify
13 * it under the terms of version 2 of the GNU General Public License as
14 * published by the Free Software Foundation.
17 #include <linux/dmaengine.h>
18 #include <linux/err.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/slab.h>
24 #include <linux/sudmac.h>
27 struct shdma_chan shdma_chan
;
29 char dev_id
[16]; /* unique name per DMAC of channel */
31 u32 offset
; /* for CFG, BA, BBC, CA, CBC, DEN */
36 struct sudmac_device
{
37 struct shdma_dev shdma_dev
;
38 struct sudmac_pdata
*pdata
;
39 void __iomem
*chan_reg
;
48 struct sudmac_regs hw
;
49 struct shdma_desc shdma_desc
;
52 #define to_chan(schan) container_of(schan, struct sudmac_chan, shdma_chan)
53 #define to_desc(sdesc) container_of(sdesc, struct sudmac_desc, shdma_desc)
54 #define to_sdev(sc) container_of(sc->shdma_chan.dma_chan.device, \
55 struct sudmac_device, shdma_dev.dma_dev)
58 #define SUDMAC_CH0CFG 0x00
59 #define SUDMAC_CH0BA 0x10
60 #define SUDMAC_CH0BBC 0x18
61 #define SUDMAC_CH0CA 0x20
62 #define SUDMAC_CH0CBC 0x28
63 #define SUDMAC_CH0DEN 0x30
64 #define SUDMAC_DSTSCLR 0x38
65 #define SUDMAC_DBUFCTRL 0x3C
66 #define SUDMAC_DINTCTRL 0x40
67 #define SUDMAC_DINTSTS 0x44
68 #define SUDMAC_DINTSTSCLR 0x48
69 #define SUDMAC_CH0SHCTRL 0x50
71 /* Definitions for the sudmac_channel.config */
72 #define SUDMAC_SENDBUFM 0x1000 /* b12: Transmit Buffer Mode */
73 #define SUDMAC_RCVENDM 0x0100 /* b8: Receive Data Transfer End Mode */
74 #define SUDMAC_LBA_WAIT 0x0030 /* b5-4: Local Bus Access Wait */
76 /* Definitions for the sudmac_channel.dint_end_bit */
77 #define SUDMAC_CH1ENDE 0x0002 /* b1: Ch1 DMA Transfer End Int Enable */
78 #define SUDMAC_CH0ENDE 0x0001 /* b0: Ch0 DMA Transfer End Int Enable */
80 #define SUDMAC_DRV_NAME "sudmac"
82 static void sudmac_writel(struct sudmac_chan
*sc
, u32 data
, u32 reg
)
84 iowrite32(data
, sc
->base
+ reg
);
87 static u32
sudmac_readl(struct sudmac_chan
*sc
, u32 reg
)
89 return ioread32(sc
->base
+ reg
);
92 static bool sudmac_is_busy(struct sudmac_chan
*sc
)
94 u32 den
= sudmac_readl(sc
, SUDMAC_CH0DEN
+ sc
->offset
);
97 return true; /* working */
99 return false; /* waiting */
102 static void sudmac_set_reg(struct sudmac_chan
*sc
, struct sudmac_regs
*hw
,
103 struct shdma_desc
*sdesc
)
105 sudmac_writel(sc
, sc
->cfg
, SUDMAC_CH0CFG
+ sc
->offset
);
106 sudmac_writel(sc
, hw
->base_addr
, SUDMAC_CH0BA
+ sc
->offset
);
107 sudmac_writel(sc
, hw
->base_byte_count
, SUDMAC_CH0BBC
+ sc
->offset
);
110 static void sudmac_start(struct sudmac_chan
*sc
)
112 u32 dintctrl
= sudmac_readl(sc
, SUDMAC_DINTCTRL
);
114 sudmac_writel(sc
, dintctrl
| sc
->dint_end_bit
, SUDMAC_DINTCTRL
);
115 sudmac_writel(sc
, 1, SUDMAC_CH0DEN
+ sc
->offset
);
118 static void sudmac_start_xfer(struct shdma_chan
*schan
,
119 struct shdma_desc
*sdesc
)
121 struct sudmac_chan
*sc
= to_chan(schan
);
122 struct sudmac_desc
*sd
= to_desc(sdesc
);
124 sudmac_set_reg(sc
, &sd
->hw
, sdesc
);
128 static bool sudmac_channel_busy(struct shdma_chan
*schan
)
130 struct sudmac_chan
*sc
= to_chan(schan
);
132 return sudmac_is_busy(sc
);
135 static void sudmac_setup_xfer(struct shdma_chan
*schan
, int slave_id
)
139 static const struct sudmac_slave_config
*sudmac_find_slave(
140 struct sudmac_chan
*sc
, int slave_id
)
142 struct sudmac_device
*sdev
= to_sdev(sc
);
143 struct sudmac_pdata
*pdata
= sdev
->pdata
;
144 const struct sudmac_slave_config
*cfg
;
147 for (i
= 0, cfg
= pdata
->slave
; i
< pdata
->slave_num
; i
++, cfg
++)
148 if (cfg
->slave_id
== slave_id
)
154 static int sudmac_set_slave(struct shdma_chan
*schan
, int slave_id
,
155 dma_addr_t slave_addr
, bool try)
157 struct sudmac_chan
*sc
= to_chan(schan
);
158 const struct sudmac_slave_config
*cfg
= sudmac_find_slave(sc
, slave_id
);
166 static inline void sudmac_dma_halt(struct sudmac_chan
*sc
)
168 u32 dintctrl
= sudmac_readl(sc
, SUDMAC_DINTCTRL
);
170 sudmac_writel(sc
, 0, SUDMAC_CH0DEN
+ sc
->offset
);
171 sudmac_writel(sc
, dintctrl
& ~sc
->dint_end_bit
, SUDMAC_DINTCTRL
);
172 sudmac_writel(sc
, sc
->dint_end_bit
, SUDMAC_DINTSTSCLR
);
175 static int sudmac_desc_setup(struct shdma_chan
*schan
,
176 struct shdma_desc
*sdesc
,
177 dma_addr_t src
, dma_addr_t dst
, size_t *len
)
179 struct sudmac_chan
*sc
= to_chan(schan
);
180 struct sudmac_desc
*sd
= to_desc(sdesc
);
182 dev_dbg(sc
->shdma_chan
.dev
, "%s: src=%pad, dst=%pad, len=%zu\n",
183 __func__
, &src
, &dst
, *len
);
185 if (*len
> schan
->max_xfer_len
)
186 *len
= schan
->max_xfer_len
;
189 sd
->hw
.base_addr
= dst
;
191 sd
->hw
.base_addr
= src
;
192 sd
->hw
.base_byte_count
= *len
;
197 static void sudmac_halt(struct shdma_chan
*schan
)
199 struct sudmac_chan
*sc
= to_chan(schan
);
204 static bool sudmac_chan_irq(struct shdma_chan
*schan
, int irq
)
206 struct sudmac_chan
*sc
= to_chan(schan
);
207 u32 dintsts
= sudmac_readl(sc
, SUDMAC_DINTSTS
);
209 if (!(dintsts
& sc
->dint_end_bit
))
218 static size_t sudmac_get_partial(struct shdma_chan
*schan
,
219 struct shdma_desc
*sdesc
)
221 struct sudmac_chan
*sc
= to_chan(schan
);
222 struct sudmac_desc
*sd
= to_desc(sdesc
);
223 u32 current_byte_count
= sudmac_readl(sc
, SUDMAC_CH0CBC
+ sc
->offset
);
225 return sd
->hw
.base_byte_count
- current_byte_count
;
228 static bool sudmac_desc_completed(struct shdma_chan
*schan
,
229 struct shdma_desc
*sdesc
)
231 struct sudmac_chan
*sc
= to_chan(schan
);
232 struct sudmac_desc
*sd
= to_desc(sdesc
);
233 u32 current_addr
= sudmac_readl(sc
, SUDMAC_CH0CA
+ sc
->offset
);
235 return sd
->hw
.base_addr
+ sd
->hw
.base_byte_count
== current_addr
;
238 static int sudmac_chan_probe(struct sudmac_device
*su_dev
, int id
, int irq
,
241 struct shdma_dev
*sdev
= &su_dev
->shdma_dev
;
242 struct platform_device
*pdev
= to_platform_device(sdev
->dma_dev
.dev
);
243 struct sudmac_chan
*sc
;
244 struct shdma_chan
*schan
;
247 sc
= devm_kzalloc(&pdev
->dev
, sizeof(struct sudmac_chan
), GFP_KERNEL
);
249 dev_err(sdev
->dma_dev
.dev
,
250 "No free memory for allocating dma channels!\n");
254 schan
= &sc
->shdma_chan
;
255 schan
->max_xfer_len
= 64 * 1024 * 1024 - 1;
257 shdma_chan_probe(sdev
, schan
, id
);
259 sc
->base
= su_dev
->chan_reg
;
261 /* get platform_data */
262 sc
->offset
= su_dev
->pdata
->channel
->offset
;
263 if (su_dev
->pdata
->channel
->config
& SUDMAC_TX_BUFFER_MODE
)
264 sc
->cfg
|= SUDMAC_SENDBUFM
;
265 if (su_dev
->pdata
->channel
->config
& SUDMAC_RX_END_MODE
)
266 sc
->cfg
|= SUDMAC_RCVENDM
;
267 sc
->cfg
|= (su_dev
->pdata
->channel
->wait
<< 4) & SUDMAC_LBA_WAIT
;
269 if (su_dev
->pdata
->channel
->dint_end_bit
& SUDMAC_DMA_BIT_CH0
)
270 sc
->dint_end_bit
|= SUDMAC_CH0ENDE
;
271 if (su_dev
->pdata
->channel
->dint_end_bit
& SUDMAC_DMA_BIT_CH1
)
272 sc
->dint_end_bit
|= SUDMAC_CH1ENDE
;
274 /* set up channel irq */
276 snprintf(sc
->dev_id
, sizeof(sc
->dev_id
), "sudmac%d.%d",
279 snprintf(sc
->dev_id
, sizeof(sc
->dev_id
), "sudmac%d", id
);
281 err
= shdma_request_irq(schan
, irq
, flags
, sc
->dev_id
);
283 dev_err(sdev
->dma_dev
.dev
,
284 "DMA channel %d request_irq failed %d\n", id
, err
);
291 /* remove from dmaengine device node */
292 shdma_chan_remove(schan
);
296 static void sudmac_chan_remove(struct sudmac_device
*su_dev
)
298 struct shdma_chan
*schan
;
301 shdma_for_each_chan(schan
, &su_dev
->shdma_dev
, i
) {
304 shdma_chan_remove(schan
);
308 static dma_addr_t
sudmac_slave_addr(struct shdma_chan
*schan
)
310 /* SUDMAC doesn't need the address */
314 static struct shdma_desc
*sudmac_embedded_desc(void *buf
, int i
)
316 return &((struct sudmac_desc
*)buf
)[i
].shdma_desc
;
319 static const struct shdma_ops sudmac_shdma_ops
= {
320 .desc_completed
= sudmac_desc_completed
,
321 .halt_channel
= sudmac_halt
,
322 .channel_busy
= sudmac_channel_busy
,
323 .slave_addr
= sudmac_slave_addr
,
324 .desc_setup
= sudmac_desc_setup
,
325 .set_slave
= sudmac_set_slave
,
326 .setup_xfer
= sudmac_setup_xfer
,
327 .start_xfer
= sudmac_start_xfer
,
328 .embedded_desc
= sudmac_embedded_desc
,
329 .chan_irq
= sudmac_chan_irq
,
330 .get_partial
= sudmac_get_partial
,
333 static int sudmac_probe(struct platform_device
*pdev
)
335 struct sudmac_pdata
*pdata
= dev_get_platdata(&pdev
->dev
);
337 struct sudmac_device
*su_dev
;
338 struct dma_device
*dma_dev
;
339 struct resource
*chan
, *irq_res
;
341 /* get platform data */
345 irq_res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
350 su_dev
= devm_kzalloc(&pdev
->dev
, sizeof(struct sudmac_device
),
353 dev_err(&pdev
->dev
, "Not enough memory\n");
357 dma_dev
= &su_dev
->shdma_dev
.dma_dev
;
359 chan
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
360 su_dev
->chan_reg
= devm_ioremap_resource(&pdev
->dev
, chan
);
361 if (IS_ERR(su_dev
->chan_reg
))
362 return PTR_ERR(su_dev
->chan_reg
);
364 dma_cap_set(DMA_SLAVE
, dma_dev
->cap_mask
);
366 su_dev
->shdma_dev
.ops
= &sudmac_shdma_ops
;
367 su_dev
->shdma_dev
.desc_size
= sizeof(struct sudmac_desc
);
368 err
= shdma_init(&pdev
->dev
, &su_dev
->shdma_dev
, pdata
->channel_num
);
373 su_dev
->pdata
= dev_get_platdata(&pdev
->dev
);
375 platform_set_drvdata(pdev
, su_dev
);
377 /* Create DMA Channel */
378 for (i
= 0; i
< pdata
->channel_num
; i
++) {
379 err
= sudmac_chan_probe(su_dev
, i
, irq_res
->start
, IRQF_SHARED
);
384 err
= dma_async_device_register(&su_dev
->shdma_dev
.dma_dev
);
391 sudmac_chan_remove(su_dev
);
393 shdma_cleanup(&su_dev
->shdma_dev
);
398 static int sudmac_remove(struct platform_device
*pdev
)
400 struct sudmac_device
*su_dev
= platform_get_drvdata(pdev
);
401 struct dma_device
*dma_dev
= &su_dev
->shdma_dev
.dma_dev
;
403 dma_async_device_unregister(dma_dev
);
404 sudmac_chan_remove(su_dev
);
405 shdma_cleanup(&su_dev
->shdma_dev
);
410 static struct platform_driver sudmac_driver
= {
412 .name
= SUDMAC_DRV_NAME
,
414 .probe
= sudmac_probe
,
415 .remove
= sudmac_remove
,
417 module_platform_driver(sudmac_driver
);
419 MODULE_AUTHOR("Yoshihiro Shimoda");
420 MODULE_DESCRIPTION("Renesas SUDMAC driver");
421 MODULE_LICENSE("GPL v2");
422 MODULE_ALIAS("platform:" SUDMAC_DRV_NAME
);