1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright © 2008 Rafaël Carré
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 #include "dma-target.h"
29 static int dma_used
= 0;
30 static void (*dma_callback
[2])(void); /* 2 channels */
36 CGU_PERI
|= CGU_DMA_CLOCK_ENABLE
;
37 DMAC_CONFIGURATION
|= (1<<0);
41 void dma_release(void)
45 DMAC_CONFIGURATION
&= ~(1<<0);
46 CGU_PERI
&= ~CGU_DMA_CLOCK_ENABLE
;
52 #if CONFIG_CPU == AS3525
53 DMAC_SYNC
= 0xffff; /* disable synchronisation logic */
55 VIC_INT_ENABLE
= INTERRUPT_DMAC
;
58 inline void dma_disable_channel(int channel
)
60 DMAC_CH_CONFIGURATION(channel
) &= ~(1<<0);
63 void dma_enable_channel(int channel
, void *src
, void *dst
, int peri
,
64 int flow_controller
, bool src_inc
, bool dst_inc
,
65 size_t size
, int nwords
, void (*callback
)(void))
67 dma_callback
[channel
] = callback
;
69 /* Clear any pending interrupts leftover from previous operation */
70 DMAC_INT_TC_CLEAR
= (1<<channel
);
71 DMAC_INT_ERR_CLEAR
= (1<<channel
);
73 DMAC_CH_SRC_ADDR(channel
) = (int)src
;
74 DMAC_CH_DST_ADDR(channel
) = (int)dst
;
76 /* When LLI is 0 channel is disabled upon transfer completion */
77 DMAC_CH_LLI(channel
) = 0;
79 /* Channel Control Register */
80 DMAC_CH_CONTROL(channel
) =
81 ((1<<31) /* LLI triggers terminal count interrupt */
82 /* | (1<<30) */ /* cacheable = 1, non = 0 */
83 /* | (1<<29) */ /* bufferable = 1, non = 0 */
84 /* | (1<<28) */ /* privileged = 1, user = 0 */
85 | (dst_inc
? (1<<27): 0) /* specify address increment */
86 | (src_inc
? (1<<26): 0) /* specify address increment */
87 /* [25:24] */ /* undefined */
88 | (2<<21) /* dst width = word, 32bit */
89 | (2<<18) /* src width = word, 32bit */
90 /* OF uses transfers of 4 * 32 bits words on memory, i2sin, i2sout */
91 /* OF uses transfers of 8 * 32 bits words on SD */
92 | (nwords
<<15) /* dst size */
93 | (nwords
<<12) /* src size */
94 | ((size
& 0x7ff)<<0)); /* transfer size */
96 /* Channel Config Register */
97 DMAC_CH_CONFIGURATION(channel
) =
98 /* [31:19] */ /* Read undefined. Write as zero */
99 /* (0<<18) */ /* Halt Bit */
100 /* (0<<17) */ /* Active Bit */
101 /* (0<<16) */ /* Lock Bit */
102 (1<<15) /* terminal count interrupt mask */
103 | (1<<14) /* interrupt error mask */
104 | (flow_controller
<<11) /* flow controller is peripheral or SDMAC */
105 /* we set the same peripheral as source and destination because we
106 * always use memory-to-peripheral or peripheral-to-memory transfers */
107 | (peri
<<6) /* dst peripheral */
108 | (peri
<<1) /* src peripheral */
109 | (1<<0); /* enable channel */
115 unsigned int channel
;
117 /* SD channel is serviced first */
118 for(channel
= 0; channel
< 2; channel
++)
119 if(DMAC_INT_STATUS
& (1<<channel
))
121 if(DMAC_INT_ERROR_STATUS
& (1<<channel
))
122 panicf("DMA error, channel %d", channel
);
124 /* clear terminal count interrupt */
125 DMAC_INT_TC_CLEAR
= (1<<channel
);
127 if(dma_callback
[channel
])
128 dma_callback
[channel
]();