diff options
Diffstat (limited to 'arch/arm/kernel/dma.c')
| -rw-r--r-- | arch/arm/kernel/dma.c | 119 | 
1 files changed, 67 insertions, 52 deletions
| diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index d006085ed7e7..7d5b9fb01e71 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -15,6 +15,7 @@  #include <linux/init.h>  #include <linux/spinlock.h>  #include <linux/errno.h> +#include <linux/scatterlist.h>  #include <asm/dma.h> @@ -23,19 +24,40 @@  DEFINE_SPINLOCK(dma_spin_lock);  EXPORT_SYMBOL(dma_spin_lock); -static dma_t dma_chan[MAX_DMA_CHANNELS]; +static dma_t *dma_chan[MAX_DMA_CHANNELS]; + +static inline dma_t *dma_channel(unsigned int chan) +{ +	if (chan >= MAX_DMA_CHANNELS) +		return NULL; + +	return dma_chan[chan]; +} + +int __init isa_dma_add(unsigned int chan, dma_t *dma) +{ +	if (!dma->d_ops) +		return -EINVAL; + +	sg_init_table(&dma->buf, 1); + +	if (dma_chan[chan]) +		return -EBUSY; +	dma_chan[chan] = dma; +	return 0; +}  /*   * Request DMA channel   *   * On certain platforms, we have to allocate an interrupt as well...   */ -int request_dma(dmach_t channel, const char *device_id) +int request_dma(unsigned int chan, const char *device_id)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	int ret; -	if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) +	if (!dma)  		goto bad_dma;  	if (xchg(&dma->lock, 1) != 0) @@ -47,7 +69,7 @@ int request_dma(dmach_t channel, const char *device_id)  	ret = 0;  	if (dma->d_ops->request) -		ret = dma->d_ops->request(channel, dma); +		ret = dma->d_ops->request(chan, dma);  	if (ret)  		xchg(&dma->lock, 0); @@ -55,7 +77,7 @@ int request_dma(dmach_t channel, const char *device_id)  	return ret;  bad_dma: -	printk(KERN_ERR "dma: trying to allocate DMA%d\n", channel); +	printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan);  	return -EINVAL;  busy: @@ -68,42 +90,42 @@ EXPORT_SYMBOL(request_dma);   *   * On certain platforms, we have to free interrupt as well...   */ -void free_dma(dmach_t channel) +void free_dma(unsigned int chan)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan); -	if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) +	if (!dma)  		goto bad_dma;  	if (dma->active) { -		printk(KERN_ERR "dma%d: freeing active DMA\n", channel); -		dma->d_ops->disable(channel, dma); +		printk(KERN_ERR "dma%d: freeing active DMA\n", chan); +		dma->d_ops->disable(chan, dma);  		dma->active = 0;  	}  	if (xchg(&dma->lock, 0) != 0) {  		if (dma->d_ops->free) -			dma->d_ops->free(channel, dma); +			dma->d_ops->free(chan, dma);  		return;  	} -	printk(KERN_ERR "dma%d: trying to free free DMA\n", channel); +	printk(KERN_ERR "dma%d: trying to free free DMA\n", chan);  	return;  bad_dma: -	printk(KERN_ERR "dma: trying to free DMA%d\n", channel); +	printk(KERN_ERR "dma: trying to free DMA%d\n", chan);  }  EXPORT_SYMBOL(free_dma);  /* Set DMA Scatter-Gather list   */ -void set_dma_sg (dmach_t channel, struct scatterlist *sg, int nr_sg) +void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	if (dma->active)  		printk(KERN_ERR "dma%d: altering DMA SG while " -		       "DMA active\n", channel); +		       "DMA active\n", chan);  	dma->sg = sg;  	dma->sgcount = nr_sg; @@ -115,13 +137,13 @@ EXPORT_SYMBOL(set_dma_sg);   *   * Copy address to the structure, and set the invalid bit   */ -void __set_dma_addr (dmach_t channel, void *addr) +void __set_dma_addr (unsigned int chan, void *addr)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	if (dma->active)  		printk(KERN_ERR "dma%d: altering DMA address while " -		       "DMA active\n", channel); +		       "DMA active\n", chan);  	dma->sg = NULL;  	dma->addr = addr; @@ -133,13 +155,13 @@ EXPORT_SYMBOL(__set_dma_addr);   *   * Copy address to the structure, and set the invalid bit   */ -void set_dma_count (dmach_t channel, unsigned long count) +void set_dma_count (unsigned int chan, unsigned long count)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	if (dma->active)  		printk(KERN_ERR "dma%d: altering DMA count while " -		       "DMA active\n", channel); +		       "DMA active\n", chan);  	dma->sg = NULL;  	dma->count = count; @@ -149,13 +171,13 @@ EXPORT_SYMBOL(set_dma_count);  /* Set DMA direction mode   */ -void set_dma_mode (dmach_t channel, dmamode_t mode) +void set_dma_mode (unsigned int chan, unsigned int mode)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	if (dma->active)  		printk(KERN_ERR "dma%d: altering DMA mode while " -		       "DMA active\n", channel); +		       "DMA active\n", chan);  	dma->dma_mode = mode;  	dma->invalid = 1; @@ -164,42 +186,42 @@ EXPORT_SYMBOL(set_dma_mode);  /* Enable DMA channel   */ -void enable_dma (dmach_t channel) +void enable_dma (unsigned int chan)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	if (!dma->lock)  		goto free_dma;  	if (dma->active == 0) {  		dma->active = 1; -		dma->d_ops->enable(channel, dma); +		dma->d_ops->enable(chan, dma);  	}  	return;  free_dma: -	printk(KERN_ERR "dma%d: trying to enable free DMA\n", channel); +	printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan);  	BUG();  }  EXPORT_SYMBOL(enable_dma);  /* Disable DMA channel   */ -void disable_dma (dmach_t channel) +void disable_dma (unsigned int chan)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	if (!dma->lock)  		goto free_dma;  	if (dma->active == 1) {  		dma->active = 0; -		dma->d_ops->disable(channel, dma); +		dma->d_ops->disable(chan, dma);  	}  	return;  free_dma: -	printk(KERN_ERR "dma%d: trying to disable free DMA\n", channel); +	printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan);  	BUG();  }  EXPORT_SYMBOL(disable_dma); @@ -207,45 +229,38 @@ EXPORT_SYMBOL(disable_dma);  /*   * Is the specified DMA channel active?   */ -int dma_channel_active(dmach_t channel) +int dma_channel_active(unsigned int chan)  { -	return dma_chan[channel].active; +	dma_t *dma = dma_channel(chan); +	return dma->active;  }  EXPORT_SYMBOL(dma_channel_active); -void set_dma_page(dmach_t channel, char pagenr) +void set_dma_page(unsigned int chan, char pagenr)  { -	printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel); +	printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan);  }  EXPORT_SYMBOL(set_dma_page); -void set_dma_speed(dmach_t channel, int cycle_ns) +void set_dma_speed(unsigned int chan, int cycle_ns)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	int ret = 0;  	if (dma->d_ops->setspeed) -		ret = dma->d_ops->setspeed(channel, dma, cycle_ns); +		ret = dma->d_ops->setspeed(chan, dma, cycle_ns);  	dma->speed = ret;  }  EXPORT_SYMBOL(set_dma_speed); -int get_dma_residue(dmach_t channel) +int get_dma_residue(unsigned int chan)  { -	dma_t *dma = dma_chan + channel; +	dma_t *dma = dma_channel(chan);  	int ret = 0;  	if (dma->d_ops->residue) -		ret = dma->d_ops->residue(channel, dma); +		ret = dma->d_ops->residue(chan, dma);  	return ret;  }  EXPORT_SYMBOL(get_dma_residue); - -static int __init init_dma(void) -{ -	arch_dma_init(dma_chan); -	return 0; -} - -core_initcall(init_dma); |