diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/blackfin/include/asm/dma.h | 17 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_dma_5xx.c | 31 |
2 files changed, 13 insertions, 35 deletions
diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h index c9a59622e23f..e3c0dfa73d1b 100644 --- a/arch/blackfin/include/asm/dma.h +++ b/arch/blackfin/include/asm/dma.h | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <mach/dma.h> | 12 | #include <mach/dma.h> |
13 | #include <asm/atomic.h> | ||
13 | #include <asm/blackfin.h> | 14 | #include <asm/blackfin.h> |
14 | #include <asm/page.h> | 15 | #include <asm/page.h> |
15 | 16 | ||
@@ -19,11 +20,6 @@ | |||
19 | * Generic DMA Declarations | 20 | * Generic DMA Declarations |
20 | * | 21 | * |
21 | ****************************************************************************/ | 22 | ****************************************************************************/ |
22 | enum dma_chan_status { | ||
23 | DMA_CHANNEL_FREE, | ||
24 | DMA_CHANNEL_REQUESTED, | ||
25 | DMA_CHANNEL_ENABLED, | ||
26 | }; | ||
27 | 23 | ||
28 | /*------------------------- | 24 | /*------------------------- |
29 | * config reg bits value | 25 | * config reg bits value |
@@ -104,11 +100,9 @@ struct dma_register { | |||
104 | 100 | ||
105 | }; | 101 | }; |
106 | 102 | ||
107 | struct mutex; | ||
108 | struct dma_channel { | 103 | struct dma_channel { |
109 | struct mutex dmalock; | ||
110 | const char *device_id; | 104 | const char *device_id; |
111 | enum dma_chan_status chan_status; | 105 | atomic_t chan_status; |
112 | volatile struct dma_register *regs; | 106 | volatile struct dma_register *regs; |
113 | struct dmasg *sg; /* large mode descriptor */ | 107 | struct dmasg *sg; /* large mode descriptor */ |
114 | unsigned int irq; | 108 | unsigned int irq; |
@@ -220,24 +214,19 @@ static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize | |||
220 | 214 | ||
221 | static inline int dma_channel_active(unsigned int channel) | 215 | static inline int dma_channel_active(unsigned int channel) |
222 | { | 216 | { |
223 | if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE) | 217 | return atomic_read(&dma_ch[channel].chan_status); |
224 | return 0; | ||
225 | else | ||
226 | return 1; | ||
227 | } | 218 | } |
228 | 219 | ||
229 | static inline void disable_dma(unsigned int channel) | 220 | static inline void disable_dma(unsigned int channel) |
230 | { | 221 | { |
231 | dma_ch[channel].regs->cfg &= ~DMAEN; | 222 | dma_ch[channel].regs->cfg &= ~DMAEN; |
232 | SSYNC(); | 223 | SSYNC(); |
233 | dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED; | ||
234 | } | 224 | } |
235 | static inline void enable_dma(unsigned int channel) | 225 | static inline void enable_dma(unsigned int channel) |
236 | { | 226 | { |
237 | dma_ch[channel].regs->curr_x_count = 0; | 227 | dma_ch[channel].regs->curr_x_count = 0; |
238 | dma_ch[channel].regs->curr_y_count = 0; | 228 | dma_ch[channel].regs->curr_y_count = 0; |
239 | dma_ch[channel].regs->cfg |= DMAEN; | 229 | dma_ch[channel].regs->cfg |= DMAEN; |
240 | dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED; | ||
241 | } | 230 | } |
242 | void free_dma(unsigned int channel); | 231 | void free_dma(unsigned int channel); |
243 | int request_dma(unsigned int channel, const char *device_id); | 232 | int request_dma(unsigned int channel, const char *device_id); |
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 3946aff4f414..639dcee5611c 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c | |||
@@ -37,9 +37,8 @@ static int __init blackfin_dma_init(void) | |||
37 | printk(KERN_INFO "Blackfin DMA Controller\n"); | 37 | printk(KERN_INFO "Blackfin DMA Controller\n"); |
38 | 38 | ||
39 | for (i = 0; i < MAX_DMA_CHANNELS; i++) { | 39 | for (i = 0; i < MAX_DMA_CHANNELS; i++) { |
40 | dma_ch[i].chan_status = DMA_CHANNEL_FREE; | 40 | atomic_set(&dma_ch[i].chan_status, 0); |
41 | dma_ch[i].regs = dma_io_base_addr[i]; | 41 | dma_ch[i].regs = dma_io_base_addr[i]; |
42 | mutex_init(&(dma_ch[i].dmalock)); | ||
43 | } | 42 | } |
44 | /* Mark MEMDMA Channel 0 as requested since we're using it internally */ | 43 | /* Mark MEMDMA Channel 0 as requested since we're using it internally */ |
45 | request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy"); | 44 | request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy"); |
@@ -60,7 +59,7 @@ static int proc_dma_show(struct seq_file *m, void *v) | |||
60 | int i; | 59 | int i; |
61 | 60 | ||
62 | for (i = 0; i < MAX_DMA_CHANNELS; ++i) | 61 | for (i = 0; i < MAX_DMA_CHANNELS; ++i) |
63 | if (dma_ch[i].chan_status != DMA_CHANNEL_FREE) | 62 | if (dma_channel_active(i)) |
64 | seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id); | 63 | seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id); |
65 | 64 | ||
66 | return 0; | 65 | return 0; |
@@ -107,20 +106,11 @@ int request_dma(unsigned int channel, const char *device_id) | |||
107 | } | 106 | } |
108 | #endif | 107 | #endif |
109 | 108 | ||
110 | mutex_lock(&(dma_ch[channel].dmalock)); | 109 | if (atomic_cmpxchg(&dma_ch[channel].chan_status, 0, 1)) { |
111 | |||
112 | if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED) | ||
113 | || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) { | ||
114 | mutex_unlock(&(dma_ch[channel].dmalock)); | ||
115 | pr_debug("DMA CHANNEL IN USE \n"); | 110 | pr_debug("DMA CHANNEL IN USE \n"); |
116 | return -EBUSY; | 111 | return -EBUSY; |
117 | } else { | ||
118 | dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED; | ||
119 | pr_debug("DMA CHANNEL IS ALLOCATED \n"); | ||
120 | } | 112 | } |
121 | 113 | ||
122 | mutex_unlock(&(dma_ch[channel].dmalock)); | ||
123 | |||
124 | #ifdef CONFIG_BF54x | 114 | #ifdef CONFIG_BF54x |
125 | if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) { | 115 | if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) { |
126 | unsigned int per_map; | 116 | unsigned int per_map; |
@@ -149,7 +139,7 @@ EXPORT_SYMBOL(request_dma); | |||
149 | int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data) | 139 | int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data) |
150 | { | 140 | { |
151 | BUG_ON(channel >= MAX_DMA_CHANNELS || | 141 | BUG_ON(channel >= MAX_DMA_CHANNELS || |
152 | dma_ch[channel].chan_status == DMA_CHANNEL_FREE); | 142 | !atomic_read(&dma_ch[channel].chan_status)); |
153 | 143 | ||
154 | if (callback != NULL) { | 144 | if (callback != NULL) { |
155 | int ret; | 145 | int ret; |
@@ -184,7 +174,7 @@ void free_dma(unsigned int channel) | |||
184 | { | 174 | { |
185 | pr_debug("freedma() : BEGIN \n"); | 175 | pr_debug("freedma() : BEGIN \n"); |
186 | BUG_ON(channel >= MAX_DMA_CHANNELS || | 176 | BUG_ON(channel >= MAX_DMA_CHANNELS || |
187 | dma_ch[channel].chan_status == DMA_CHANNEL_FREE); | 177 | !atomic_read(&dma_ch[channel].chan_status)); |
188 | 178 | ||
189 | /* Halt the DMA */ | 179 | /* Halt the DMA */ |
190 | disable_dma(channel); | 180 | disable_dma(channel); |
@@ -194,9 +184,7 @@ void free_dma(unsigned int channel) | |||
194 | free_irq(dma_ch[channel].irq, dma_ch[channel].data); | 184 | free_irq(dma_ch[channel].irq, dma_ch[channel].data); |
195 | 185 | ||
196 | /* Clear the DMA Variable in the Channel */ | 186 | /* Clear the DMA Variable in the Channel */ |
197 | mutex_lock(&(dma_ch[channel].dmalock)); | 187 | atomic_set(&dma_ch[channel].chan_status, 0); |
198 | dma_ch[channel].chan_status = DMA_CHANNEL_FREE; | ||
199 | mutex_unlock(&(dma_ch[channel].dmalock)); | ||
200 | 188 | ||
201 | pr_debug("freedma() : END \n"); | 189 | pr_debug("freedma() : END \n"); |
202 | } | 190 | } |
@@ -210,13 +198,14 @@ int blackfin_dma_suspend(void) | |||
210 | { | 198 | { |
211 | int i; | 199 | int i; |
212 | 200 | ||
213 | for (i = 0; i < MAX_DMA_SUSPEND_CHANNELS; ++i) { | 201 | for (i = 0; i < MAX_DMA_CHANNELS; ++i) { |
214 | if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) { | 202 | if (dma_ch[i].regs->cfg & DMAEN) { |
215 | printk(KERN_ERR "DMA Channel %d failed to suspend\n", i); | 203 | printk(KERN_ERR "DMA Channel %d failed to suspend\n", i); |
216 | return -EBUSY; | 204 | return -EBUSY; |
217 | } | 205 | } |
218 | 206 | ||
219 | dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map; | 207 | if (i < MAX_DMA_SUSPEND_CHANNELS) |
208 | dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map; | ||
220 | } | 209 | } |
221 | 210 | ||
222 | return 0; | 211 | return 0; |