aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/blackfin/include/asm/dma.h17
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c31
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****************************************************************************/
22enum 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
107struct mutex;
108struct dma_channel { 103struct 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
221static inline int dma_channel_active(unsigned int channel) 215static 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
229static inline void disable_dma(unsigned int channel) 220static 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}
235static inline void enable_dma(unsigned int channel) 225static 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}
242void free_dma(unsigned int channel); 231void free_dma(unsigned int channel);
243int request_dma(unsigned int channel, const char *device_id); 232int 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);
149int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data) 139int 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;