int dma_release_channel (unsigned int chn)
{
	unsigned int mask = (0x3 << (chn * 2));
	unsigned long flags;

	if (chn >= DMA_MAX_CHANNELS || !dma_channels[chn].name) {
		return -EINVAL;
	}

	lpc313x_dma_lock();
	
	local_irq_save(flags);

	/* Otherwise an unexpected interrupt can occur when the channel is reallocated for another purpose */
	DMACH_IRQ_STATUS = mask;
	dma_irq_mask |= mask;
	DMACH_IRQ_MASK = dma_irq_mask;
	/* reset counter */
	DMACH_TCNT(chn) = 0;
	local_irq_restore(flags);

	dma_channels[chn].name = NULL;
	dma_channels[chn].callback_handler = NULL;
	dma_channels[chn].data = NULL;

	lpc313x_dma_unlock();
	dma_decrement_usage();
	
	return 0;
}
int dma_release_sg_channel (unsigned int chn)
{
	unsigned long flags;

	if (chn >= DMA_MAX_CHANNELS || !dma_channels[chn].name) {
		return -EINVAL;
	}

	lpc313x_dma_lock();

	if (softirqmask[chn] != 0) {
		local_irq_save(flags);
		softirqen = 0;
		softirqmask[chn] = 0;
		dma_irq_mask |= DMA_IRQS_SOFT;
		DMACH_IRQ_MASK = dma_irq_mask;
		local_irq_restore(flags);
	}
	
	dma_channels[chn].name = NULL;
	dma_channels[chn].callback_handler = NULL;
	dma_channels[chn].data = NULL;
	
	chn--;
	dma_channels[chn].name = NULL;
	dma_channels[chn].callback_handler = NULL;
	dma_channels[chn].data = NULL;
	
	sg_higher_channel[chn] = 0;

	lpc313x_dma_unlock();
	dma_decrement_usage();
	return 0;
}
Esempio n. 3
0
void pnx4008_free_channel(int ch)
{
	if (!dma_channels[ch].name) {
		printk(KERN_CRIT
		       "%s: trying to free channel %d which is already freed\n",
		       __FUNCTION__, ch);
		return;
	}

	pnx4008_dma_lock();
	pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll);
	dma_channels[ch].ll = NULL;
	dma_decrement_usage();

	dma_channels[ch].name = NULL;
	pnx4008_dma_unlock();
}