#include <linux/interrupt.h>
#include <mach/dma.h>
+#include <asm/atomic.h>
#include <asm/blackfin.h>
#include <asm/page.h>
* Generic DMA Declarations
*
****************************************************************************/
-enum dma_chan_status {
- DMA_CHANNEL_FREE,
- DMA_CHANNEL_REQUESTED,
- DMA_CHANNEL_ENABLED,
-};
/*-------------------------
* config reg bits value
};
-struct mutex;
struct dma_channel {
- struct mutex dmalock;
const char *device_id;
- enum dma_chan_status chan_status;
+ atomic_t chan_status;
volatile struct dma_register *regs;
struct dmasg *sg; /* large mode descriptor */
unsigned int irq;
static inline int dma_channel_active(unsigned int channel)
{
- if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE)
- return 0;
- else
- return 1;
+ return atomic_read(&dma_ch[channel].chan_status);
}
static inline void disable_dma(unsigned int channel)
{
dma_ch[channel].regs->cfg &= ~DMAEN;
SSYNC();
- dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
}
static inline void enable_dma(unsigned int channel)
{
dma_ch[channel].regs->curr_x_count = 0;
dma_ch[channel].regs->curr_y_count = 0;
dma_ch[channel].regs->cfg |= DMAEN;
- dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
}
void free_dma(unsigned int channel);
int request_dma(unsigned int channel, const char *device_id);
printk(KERN_INFO "Blackfin DMA Controller\n");
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
- dma_ch[i].chan_status = DMA_CHANNEL_FREE;
+ atomic_set(&dma_ch[i].chan_status, 0);
dma_ch[i].regs = dma_io_base_addr[i];
- mutex_init(&(dma_ch[i].dmalock));
}
/* Mark MEMDMA Channel 0 as requested since we're using it internally */
request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy");
int i;
for (i = 0; i < MAX_DMA_CHANNELS; ++i)
- if (dma_ch[i].chan_status != DMA_CHANNEL_FREE)
+ if (dma_channel_active(i))
seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id);
return 0;
}
#endif
- mutex_lock(&(dma_ch[channel].dmalock));
-
- if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED)
- || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) {
- mutex_unlock(&(dma_ch[channel].dmalock));
+ if (atomic_cmpxchg(&dma_ch[channel].chan_status, 0, 1)) {
pr_debug("DMA CHANNEL IN USE \n");
return -EBUSY;
- } else {
- dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
- pr_debug("DMA CHANNEL IS ALLOCATED \n");
}
- mutex_unlock(&(dma_ch[channel].dmalock));
-
#ifdef CONFIG_BF54x
if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
unsigned int per_map;
int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
{
BUG_ON(channel >= MAX_DMA_CHANNELS ||
- dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
+ !atomic_read(&dma_ch[channel].chan_status));
if (callback != NULL) {
int ret;
{
pr_debug("freedma() : BEGIN \n");
BUG_ON(channel >= MAX_DMA_CHANNELS ||
- dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
+ !atomic_read(&dma_ch[channel].chan_status));
/* Halt the DMA */
disable_dma(channel);
free_irq(dma_ch[channel].irq, dma_ch[channel].data);
/* Clear the DMA Variable in the Channel */
- mutex_lock(&(dma_ch[channel].dmalock));
- dma_ch[channel].chan_status = DMA_CHANNEL_FREE;
- mutex_unlock(&(dma_ch[channel].dmalock));
+ atomic_set(&dma_ch[channel].chan_status, 0);
pr_debug("freedma() : END \n");
}
{
int i;
- for (i = 0; i < MAX_DMA_SUSPEND_CHANNELS; ++i) {
- if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
+ for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
+ if (dma_ch[i].regs->cfg & DMAEN) {
printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
return -EBUSY;
}
- dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
+ if (i < MAX_DMA_SUSPEND_CHANNELS)
+ dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
}
return 0;