2 * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
4 * SPDX-License-Identifier: GPL-2.0+
7 /* This is a basic implementation of the SDMA/DMA4 controller of OMAP3
8 * Tested on Silicon Revision major:0x4 minor:0x0
12 #include <asm/arch/cpu.h>
13 #include <asm/arch/omap3.h>
14 #include <asm/arch/dma.h>
16 #include <asm/errno.h>
18 static struct dma4 *dma4_cfg = (struct dma4 *)OMAP34XX_DMA4_BASE;
19 uint32_t dma_active; /* if a transfer is started the respective
20 bit is set for the logical channel */
22 /* Check if we have the given channel
24 * chan: Channel number
26 * RETURN of non-zero means error */
27 static inline int check_channel(uint32_t chan)
29 if (chan < CHAN_NR_MIN || chan > CHAN_NR_MAX)
34 static inline void reset_irq(uint32_t chan)
36 /* reset IRQ reason */
37 writel(0x1DFE, &dma4_cfg->chan[chan].csr);
39 writel((1 << chan), &dma4_cfg->irqstatus_l[0]);
40 dma_active &= ~(1 << chan);
43 /* Set Source, Destination and Size of DMA transfer for the
46 * chan: channel to use
47 * src: source of the transfer
48 * dst: destination of the transfer
49 * sze: Size of the transfer
51 * RETURN of non-zero means error */
52 int omap3_dma_conf_transfer(uint32_t chan, uint32_t *src, uint32_t *dst,
55 if (check_channel(chan))
58 writel((uint32_t)src, &dma4_cfg->chan[chan].cssa);
59 writel((uint32_t)dst, &dma4_cfg->chan[chan].cdsa);
60 writel(sze, &dma4_cfg->chan[chan].cen);
64 /* Start the DMA transfer */
65 int omap3_dma_start_transfer(uint32_t chan)
69 if (check_channel(chan))
72 val = readl(&dma4_cfg->chan[chan].ccr);
73 /* Test for channel already in use */
74 if (val & CCR_ENABLE_ENABLE)
77 writel((val | CCR_ENABLE_ENABLE), &dma4_cfg->chan[chan].ccr);
78 dma_active |= (1 << chan);
79 debug("started transfer...\n");
83 /* Busy-waiting for a DMA transfer
84 * This has to be called before another transfer is started
86 * chan: Channel to wait for
88 * RETURN of non-zero means error*/
89 int omap3_dma_wait_for_transfer(uint32_t chan)
93 if (!(dma_active & (1 << chan))) {
94 val = readl(&dma4_cfg->irqstatus_l[0]);
96 debug("dma: The channel you are trying to wait for "
97 "was never activated - ERROR\n");
98 return -1; /* channel was never active */
102 /* all irqs on line 0 */
103 while (!(readl(&dma4_cfg->irqstatus_l[0]) & (1 << chan)))
106 val = readl(&dma4_cfg->chan[chan].csr);
107 if ((val & CSR_TRANS_ERR) | (val & CSR_SUPERVISOR_ERR) |
108 (val & CSR_MISALIGNED_ADRS_ERR)) {
109 debug("err code: %X\n", val);
110 debug("dma: transfer error detected\n");
118 /* Get the revision of the DMA module
120 * minor: Address of minor revision to write
121 * major: Address of major revision to write
123 * RETURN of non-zero means error
125 int omap3_dma_get_revision(uint32_t *minor, uint32_t *major)
129 /* debug information */
130 val = readl(&dma4_cfg->revision);
131 *major = (val & 0x000000F0) >> 4;
132 *minor = (val & 0x0000000F);
133 debug("DMA Silicon revision (maj/min): 0x%X/0x%X\n", *major, *minor);
137 /* Initial config of omap dma
139 void omap3_dma_init(void)
142 /* All interrupts on channel 0 */
143 writel(0xFFFFFFFF, &dma4_cfg->irqenable_l[0]);
146 /* set channel config to config
148 * RETURN of non-zero means error */
149 int omap3_dma_conf_chan(uint32_t chan, struct dma4_chan *config)
151 if (check_channel(chan))
154 dma4_cfg->chan[chan] = *config;
158 /* get channel config to config
160 * RETURN of non-zero means error */
161 int omap3_dma_get_conf_chan(uint32_t chan, struct dma4_chan *config)
163 if (check_channel(chan))
165 *config = dma4_cfg->chan[chan];