diff options
Diffstat (limited to 'firmware/target/arm/as3525/dma-pl081.c')
-rw-r--r-- | firmware/target/arm/as3525/dma-pl081.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/firmware/target/arm/as3525/dma-pl081.c b/firmware/target/arm/as3525/dma-pl081.c index fbe488ce05..3de4e73c12 100644 --- a/firmware/target/arm/as3525/dma-pl081.c +++ b/firmware/target/arm/as3525/dma-pl081.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "kernel.h" | 27 | #include "kernel.h" |
28 | 28 | ||
29 | static struct wakeup transfer_completion_signal[2]; /* 2 channels */ | 29 | static struct wakeup transfer_completion_signal[2]; /* 2 channels */ |
30 | static void (*dma_callback[2])(void); /* 2 channels */ | ||
30 | 31 | ||
31 | inline void dma_wait_transfer(int channel) | 32 | inline void dma_wait_transfer(int channel) |
32 | { | 33 | { |
@@ -45,10 +46,17 @@ void dma_init(void) | |||
45 | wakeup_init(&transfer_completion_signal[1]); | 46 | wakeup_init(&transfer_completion_signal[1]); |
46 | } | 47 | } |
47 | 48 | ||
49 | inline void dma_disable_channel(int channel) | ||
50 | { | ||
51 | DMAC_CH_CONFIGURATION(channel) &= ~(1<<0); | ||
52 | } | ||
53 | |||
48 | void dma_enable_channel(int channel, void *src, void *dst, int peri, | 54 | void dma_enable_channel(int channel, void *src, void *dst, int peri, |
49 | int flow_controller, bool src_inc, bool dst_inc, | 55 | int flow_controller, bool src_inc, bool dst_inc, |
50 | size_t size, int nwords) | 56 | size_t size, int nwords, void (*callback)(void)) |
51 | { | 57 | { |
58 | dma_callback[channel] = callback; | ||
59 | |||
52 | int control = 0; | 60 | int control = 0; |
53 | 61 | ||
54 | DMAC_CH_SRC_ADDR(channel) = (int)src; | 62 | DMAC_CH_SRC_ADDR(channel) = (int)src; |
@@ -92,12 +100,21 @@ void dma_enable_channel(int channel, void *src, void *dst, int peri, | |||
92 | /* isr */ | 100 | /* isr */ |
93 | void INT_DMAC(void) | 101 | void INT_DMAC(void) |
94 | { | 102 | { |
95 | int channel = (DMAC_INT_STATUS & (1<<0)) ? 0 : 1; | 103 | unsigned int channel; |
104 | |||
105 | /* SD channel is serviced first */ | ||
106 | for(channel = 0; channel < 2; channel++) | ||
107 | if(DMAC_INT_STATUS & (1<<channel)) | ||
108 | { | ||
109 | if(DMAC_INT_ERROR_STATUS & (1<<channel)) | ||
110 | panicf("DMA error, channel %d", channel); | ||
96 | 111 | ||
97 | if(DMAC_INT_ERROR_STATUS & (1<<channel)) | 112 | /* clear terminal count interrupt */ |
98 | panicf("DMA error, channel %d", channel); | 113 | DMAC_INT_TC_CLEAR |= (1<<channel); |
99 | 114 | ||
100 | DMAC_INT_TC_CLEAR |= (1<<channel); /* clear terminal count interrupt */ | 115 | if(dma_callback[channel]) |
116 | dma_callback[channel](); | ||
101 | 117 | ||
102 | wakeup_signal(&transfer_completion_signal[channel]); | 118 | wakeup_signal(&transfer_completion_signal[channel]); |
119 | } | ||
103 | } | 120 | } |