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/init.h>
18 #include <linux/module.h>
19 #include <linux/slab.h>
20 #include <linux/interrupt.h>
21 #include <linux/dmaengine.h>
22 #include <linux/platform_device.h>
23 #include <linux/sudmac.h>
26 struct shdma_chan shdma_chan
;
28 char dev_id
[16]; /* unique name per DMAC of channel */
30 u32 offset
; /* for CFG, BA, BBC, CA, CBC, DEN */
35 struct sudmac_device
{
36 struct shdma_dev shdma_dev
;
37 struct sudmac_pdata
*pdata
;
38 void __iomem
*chan_reg
;
47 struct sudmac_regs hw
;
48 struct shdma_desc shdma_desc
;
51 #define to_chan(schan) container_of(schan, struct sudmac_chan, shdma_chan)
52 #define to_desc(sdesc) container_of(sdesc, struct sudmac_desc, shdma_desc)
53 #define to_sdev(sc) container_of(sc->shdma_chan.dma_chan.device, \
54 struct sudmac_device, shdma_dev.dma_dev)
57 #define SUDMAC_CH0CFG 0x00
58 #define SUDMAC_CH0BA 0x10
59 #define SUDMAC_CH0BBC 0x18
60 #define SUDMAC_CH0CA 0x20
61 #define SUDMAC_CH0CBC 0x28
62 #define SUDMAC_CH0DEN 0x30
63 #define SUDMAC_DSTSCLR 0x38
64 #define SUDMAC_DBUFCTRL 0x3C
65 #define SUDMAC_DINTCTRL 0x40
66 #define SUDMAC_DINTSTS 0x44
67 #define SUDMAC_DINTSTSCLR 0x48
68 #define SUDMAC_CH0SHCTRL 0x50
70 /* Definitions for the sudmac_channel.config */
71 #define SUDMAC_SENDBUFM 0x1000 /* b12: Transmit Buffer Mode */
72 #define SUDMAC_RCVENDM 0x0100 /* b8: Receive Data Transfer End Mode */
73 #define SUDMAC_LBA_WAIT 0x0030 /* b5-4: Local Bus Access Wait */
75 /* Definitions for the sudmac_channel.dint_end_bit */
76 #define SUDMAC_CH1ENDE 0x0002 /* b1: Ch1 DMA Transfer End Int Enable */
77 #define SUDMAC_CH0ENDE 0x0001 /* b0: Ch0 DMA Transfer End Int Enable */
79 #define SUDMAC_DRV_NAME "sudmac"
81 static void sudmac_writel(struct sudmac_chan
*sc
, u32 data
, u32 reg
)
83 iowrite32(data
, sc
->base
+ reg
);
86 static u32
sudmac_readl(struct sudmac_chan
*sc
, u32 reg
)
88 return ioread32(sc
->base
+ reg
);
91 static bool sudmac_is_busy(struct sudmac_chan
*sc
)
93 u32 den
= sudmac_readl(sc
, SUDMAC_CH0DEN
+ sc
->offset
);
96 return true; /* working */
98 return false; /* waiting */
101 static void sudmac_set_reg(struct sudmac_chan
*sc
, struct sudmac_regs
*hw
,
102 struct shdma_desc
*sdesc
)
104 sudmac_writel(sc
, sc
->cfg
, SUDMAC_CH0CFG
+ sc
->offset
);
105 sudmac_writel(sc
, hw
->base_addr
, SUDMAC_CH0BA
+ sc
->offset
);
106 sudmac_writel(sc
, hw
->base_byte_count
, SUDMAC_CH0BBC
+ sc
->offset
);
109 static void sudmac_start(struct sudmac_chan
*sc
)
111 u32 dintctrl
= sudmac_readl(sc
, SUDMAC_DINTCTRL
);
113 sudmac_writel(sc
, dintctrl
| sc
->dint_end_bit
, SUDMAC_DINTCTRL
);
114 sudmac_writel(sc
, 1, SUDMAC_CH0DEN
+ sc
->offset
);
117 static void sudmac_start_xfer(struct shdma_chan
*schan
,
118 struct shdma_desc
*sdesc
)
120 struct sudmac_chan
*sc
= to_chan(schan
);
121 struct sudmac_desc
*sd
= to_desc(sdesc
);
123 sudmac_set_reg(sc
, &sd
->hw
, sdesc
);
127 static bool sudmac_channel_busy(struct shdma_chan
*schan
)
129 struct sudmac_chan
*sc
= to_chan(schan
);
131 return sudmac_is_busy(sc
);
134 static void sudmac_setup_xfer(struct shdma_chan
*schan
, int slave_id
)
138 static const struct sudmac_slave_config
*sudmac_find_slave(
139 struct sudmac_chan
*sc
, int slave_id
)
141 struct sudmac_device
*sdev
= to_sdev(sc
);
142 struct sudmac_pdata
*pdata
= sdev
->pdata
;
143 const struct sudmac_slave_config
*cfg
;
146 for (i
= 0, cfg
= pdata
->slave
; i
< pdata
->slave_num
; i
++, cfg
++)
147 if (cfg
->slave_id
== slave_id
)
153 static int sudmac_set_slave(struct shdma_chan
*schan
, int slave_id
,
154 dma_addr_t slave_addr
, bool try)
156 struct sudmac_chan
*sc
= to_chan(schan
);
157 const struct sudmac_slave_config
*cfg
= sudmac_find_slave(sc
, slave_id
);
165 static inline void sudmac_dma_halt(struct sudmac_chan
*sc
)
167 u32 dintctrl
= sudmac_readl(sc
, SUDMAC_DINTCTRL
);
169 sudmac_writel(sc
, 0, SUDMAC_CH0DEN
+ sc
->offset
);
170 sudmac_writel(sc
, dintctrl
& ~sc
->dint_end_bit
, SUDMAC_DINTCTRL
);
171 sudmac_writel(sc
, sc
->dint_end_bit
, SUDMAC_DINTSTSCLR
);
174 static int sudmac_desc_setup(struct shdma_chan
*schan
,
175 struct shdma_desc
*sdesc
,
176 dma_addr_t src
, dma_addr_t dst
, size_t *len
)
178 struct sudmac_chan
*sc
= to_chan(schan
);
179 struct sudmac_desc
*sd
= to_desc(sdesc
);
181 dev_dbg(sc
->shdma_chan
.dev
, "%s: src=%x, dst=%x, len=%d\n",
182 __func__
, src
, dst
, *len
);
184 if (*len
> schan
->max_xfer_len
)
185 *len
= schan
->max_xfer_len
;
188 sd
->hw
.base_addr
= dst
;
190 sd
->hw
.base_addr
= src
;
191 sd
->hw
.base_byte_count
= *len
;
196 static void sudmac_halt(struct shdma_chan
*schan
)
198 struct sudmac_chan
*sc
= to_chan(schan
);
203 static bool sudmac_chan_irq(struct shdma_chan
*schan
, int irq
)
205 struct sudmac_chan
*sc
= to_chan(schan
);
206 u32 dintsts
= sudmac_readl(sc
, SUDMAC_DINTSTS
);
208 if (!(dintsts
& sc
->dint_end_bit
))
217 static size_t sudmac_get_partial(struct shdma_chan
*schan
,
218 struct shdma_desc
*sdesc
)
220 struct sudmac_chan
*sc
= to_chan(schan
);
221 struct sudmac_desc
*sd
= to_desc(sdesc
);
222 u32 current_byte_count
= sudmac_readl(sc
, SUDMAC_CH0CBC
+ sc
->offset
);
224 return sd
->hw
.base_byte_count
- current_byte_count
;
227 static bool sudmac_desc_completed(struct shdma_chan
*schan
,
228 struct shdma_desc
*sdesc
)
230 struct sudmac_chan
*sc
= to_chan(schan
);
231 struct sudmac_desc
*sd
= to_desc(sdesc
);
232 u32 current_addr
= sudmac_readl(sc
, SUDMAC_CH0CA
+ sc
->offset
);
234 return sd
->hw
.base_addr
+ sd
->hw
.base_byte_count
== current_addr
;
237 static int sudmac_chan_probe(struct sudmac_device
*su_dev
, int id
, int irq
,
240 struct shdma_dev
*sdev
= &su_dev
->shdma_dev
;
241 struct platform_device
*pdev
= to_platform_device(sdev
->dma_dev
.dev
);
242 struct sudmac_chan
*sc
;
243 struct shdma_chan
*schan
;
246 sc
= devm_kzalloc(&pdev
->dev
, sizeof(struct sudmac_chan
), GFP_KERNEL
);
248 dev_err(sdev
->dma_dev
.dev
,
249 "No free memory for allocating dma channels!\n");
253 schan
= &sc
->shdma_chan
;
254 schan
->max_xfer_len
= 64 * 1024 * 1024 - 1;
256 shdma_chan_probe(sdev
, schan
, id
);
258 sc
->base
= su_dev
->chan_reg
;
260 /* get platform_data */
261 sc
->offset
= su_dev
->pdata
->channel
->offset
;
262 if (su_dev
->pdata
->channel
->config
& SUDMAC_TX_BUFFER_MODE
)
263 sc
->cfg
|= SUDMAC_SENDBUFM
;
264 if (su_dev
->pdata
->channel
->config
& SUDMAC_RX_END_MODE
)
265 sc
->cfg
|= SUDMAC_RCVENDM
;
266 sc
->cfg
|= (su_dev
->pdata
->channel
->wait
<< 4) & SUDMAC_LBA_WAIT
;
268 if (su_dev
->pdata
->channel
->dint_end_bit
& SUDMAC_DMA_BIT_CH0
)
269 sc
->dint_end_bit
|= SUDMAC_CH0ENDE
;
270 if (su_dev
->pdata
->channel
->dint_end_bit
& SUDMAC_DMA_BIT_CH1
)
271 sc
->dint_end_bit
|= SUDMAC_CH1ENDE
;
273 /* set up channel irq */
275 snprintf(sc
->dev_id
, sizeof(sc
->dev_id
), "sudmac%d.%d",
278 snprintf(sc
->dev_id
, sizeof(sc
->dev_id
), "sudmac%d", id
);
280 err
= shdma_request_irq(schan
, irq
, flags
, sc
->dev_id
);
282 dev_err(sdev
->dma_dev
.dev
,
283 "DMA channel %d request_irq failed %d\n", id
, err
);
290 /* remove from dmaengine device node */
291 shdma_chan_remove(schan
);
295 static void sudmac_chan_remove(struct sudmac_device
*su_dev
)
297 struct dma_device
*dma_dev
= &su_dev
->shdma_dev
.dma_dev
;
298 struct shdma_chan
*schan
;
301 shdma_for_each_chan(schan
, &su_dev
->shdma_dev
, i
) {
304 shdma_chan_remove(schan
);
306 dma_dev
->chancnt
= 0;
309 static dma_addr_t
sudmac_slave_addr(struct shdma_chan
*schan
)
311 /* SUDMAC doesn't need the address */
315 static struct shdma_desc
*sudmac_embedded_desc(void *buf
, int i
)
317 return &((struct sudmac_desc
*)buf
)[i
].shdma_desc
;
320 static const struct shdma_ops sudmac_shdma_ops
= {
321 .desc_completed
= sudmac_desc_completed
,
322 .halt_channel
= sudmac_halt
,
323 .channel_busy
= sudmac_channel_busy
,
324 .slave_addr
= sudmac_slave_addr
,
325 .desc_setup
= sudmac_desc_setup
,
326 .set_slave
= sudmac_set_slave
,
327 .setup_xfer
= sudmac_setup_xfer
,
328 .start_xfer
= sudmac_start_xfer
,
329 .embedded_desc
= sudmac_embedded_desc
,
330 .chan_irq
= sudmac_chan_irq
,
331 .get_partial
= sudmac_get_partial
,
334 static int sudmac_probe(struct platform_device
*pdev
)
336 struct sudmac_pdata
*pdata
= dev_get_platdata(&pdev
->dev
);
338 struct sudmac_device
*su_dev
;
339 struct dma_device
*dma_dev
;
340 struct resource
*chan
, *irq_res
;
342 /* get platform data */
346 irq_res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
351 su_dev
= devm_kzalloc(&pdev
->dev
, sizeof(struct sudmac_device
),
354 dev_err(&pdev
->dev
, "Not enough memory\n");
358 dma_dev
= &su_dev
->shdma_dev
.dma_dev
;
360 chan
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
361 su_dev
->chan_reg
= devm_ioremap_resource(&pdev
->dev
, chan
);
362 if (IS_ERR(su_dev
->chan_reg
))
363 return PTR_ERR(su_dev
->chan_reg
);
365 dma_cap_set(DMA_SLAVE
, dma_dev
->cap_mask
);
367 su_dev
->shdma_dev
.ops
= &sudmac_shdma_ops
;
368 su_dev
->shdma_dev
.desc_size
= sizeof(struct sudmac_desc
);
369 err
= shdma_init(&pdev
->dev
, &su_dev
->shdma_dev
, pdata
->channel_num
);
374 su_dev
->pdata
= dev_get_platdata(&pdev
->dev
);
376 platform_set_drvdata(pdev
, su_dev
);
378 /* Create DMA Channel */
379 for (i
= 0; i
< pdata
->channel_num
; i
++) {
380 err
= sudmac_chan_probe(su_dev
, i
, irq_res
->start
, IRQF_SHARED
);
385 err
= dma_async_device_register(&su_dev
->shdma_dev
.dma_dev
);
392 sudmac_chan_remove(su_dev
);
394 shdma_cleanup(&su_dev
->shdma_dev
);
399 static int sudmac_remove(struct platform_device
*pdev
)
401 struct sudmac_device
*su_dev
= platform_get_drvdata(pdev
);
402 struct dma_device
*dma_dev
= &su_dev
->shdma_dev
.dma_dev
;
404 dma_async_device_unregister(dma_dev
);
405 sudmac_chan_remove(su_dev
);
406 shdma_cleanup(&su_dev
->shdma_dev
);
411 static struct platform_driver sudmac_driver
= {
413 .owner
= THIS_MODULE
,
414 .name
= SUDMAC_DRV_NAME
,
416 .probe
= sudmac_probe
,
417 .remove
= sudmac_remove
,
419 module_platform_driver(sudmac_driver
);
421 MODULE_AUTHOR("Yoshihiro Shimoda");
422 MODULE_DESCRIPTION("Renesas SUDMAC driver");
423 MODULE_LICENSE("GPL v2");
424 MODULE_ALIAS("platform:" SUDMAC_DRV_NAME
);