⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dma-omap24xx.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	return IRQ_HANDLED;}/* enable interrupts for this channel*/void omap_enable_irq_lch(int lch){	u32 w;	w = readl(OMAP_DMA4_IRQENABLE_L0);	w |= 1 << lch;	writel(w, OMAP_DMA4_IRQENABLE_L0);}int omap_request_dma(int dev_id, const char *dev_name,		     void (*callback) (int lch, u16 ch_status, void *data),		     void *data, int *dma_ch_out){	int ch, free_ch = -1;	unsigned long flags;	spin_lock_irqsave(&dma_chan_lock, flags);	for (ch = 0; ch < dma_chan_count; ch++) {		if (free_ch == -1 && dma_chan[ch].dev_id == -1		    && dma_chan[ch].reserved == -1) {			free_ch = ch;			if (dev_id == 0)				break;		}		/*		   if (dev_id != 0 && dma_chan[ch].dev_id == dev_id) {		   spin_unlock_irqrestore(&dma_chan_lock, flags);		   return -EAGAIN;		   }		 */	}	if (free_ch == -1) {		spin_unlock_irqrestore(&dma_chan_lock, flags);		return -EBUSY;	}	dma_chan[free_ch].dev_id = dev_id;	dma_chan[free_ch].reserved = 1;	clear_lch_regs(free_ch);	spin_unlock_irqrestore(&dma_chan_lock, flags);	dma_chan[free_ch].dev_name = dev_name;	dma_chan[free_ch].callback = callback;	dma_chan[free_ch].data = data;	dma_chan[free_ch].enabled_irqs =	    OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;	omap_enable_irq_lch(free_ch);	omap_enable_dma_irq(free_ch);	/* clear the CSR register and IRQ status register */	writel(0x0, OMAP_DMA4_CSR_REG(free_ch));	writel(~0x0, OMAP_DMA4_IRQSTATUS_L0);	*dma_ch_out = free_ch;	return 0;}int omap_request_dma_chain(int dev_id, const char *dev_name, int num_transfers,	/* if num_transfer > 1 ... chaining logic will be used */			   void (*callback) (int lch, u16 ch_status,					     void *data), void *data,			   int *dma_ch_out, lch_chain ** chain){	int ch;	unsigned long flags;	u8 chan_allocated = 0;	int firstch = -1;	int lastch = 0;	int i;	local_irq_save(flags);	/* trying to allocate logical channels from the pool */	for (ch = 0; ch < dma_chan_count; ch++) {		if (dma_chan[ch].dev_id == -1 && dma_chan[ch].reserved == -1) {			dma_chan[ch].reserved = 1;			chan_allocated++;			if (firstch == -1)				firstch = ch;			else				dma_chan[lastch].next_channel = ch;			lastch = ch;		}		if (chan_allocated >= num_transfers)			break;	}	dma_chan[ch].next_channel = firstch;	/* num channels requested less than the free channels in the pool */	if (chan_allocated < num_transfers) {		for (ch = 0; ch < dma_chan_count; ch++) {			if (dma_chan[ch].dev_id == dev_id) {				dma_chan[ch].dev_id = -1;				dma_chan[ch].reserved = -1;			}		}		local_irq_restore(flags);		return -EBUSY;	}	*chain = kmalloc(sizeof(lch_chain), GFP_KERNEL);	if (chain == NULL)		return -ENOMEM;	(*chain)->queue_head = firstch;	(*chain)->queue_tail = firstch;	(*chain)->num_channels = num_transfers;	(*chain)->started = 0;	(*chain)->queued = 0;	/* logical channels allocated , initialize the channels */	ch = firstch;	for (i = 0; i < num_transfers; i++) {		dma_chan[ch].dev_id = dev_id;		dma_chan[ch].callback = callback;		dma_chan[ch].data = data;		dma_chan[ch].dev_name = dev_name;		dma_chan[ch].params_set = 0;		dma_chan[ch].mychain = *chain;		clear_lch_regs(ch);		setup_chain(ch, dma_chan[ch].next_channel);		/* enable interrupts for this channel */		omap_enable_irq_lch(ch);		dma_chan[ch].enabled_irqs =		    OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;		/* enable some nice interrupts */		/* enable DROP event and End of Block */		omap_enable_dma_irq(ch);		/* clear the CSR register and IRQ status register */		writel(0x0, OMAP_DMA4_CSR_REG(ch));		writel(~0x0, OMAP_DMA4_IRQSTATUS_L0);		ch = dma_chan[ch].next_channel;		/* one common ISR for all the channels is inserted upfront in the init routine */	}	local_irq_restore(flags);	*dma_ch_out = firstch;	return 0;}void omap_free_dma(int lch){	u32 w;	if (dma_chan[lch].reserved == -1) {		printk(KERN_INFO		       "omap_dma: trying to free nonallocated DMA channel %d\n",		       lch);		return;	}	dma_chan[lch].reserved = -1;	dma_chan[lch].dev_id = -1;	dma_chan[lch].callback = NULL;	/* disable interrupts */	w = readl(OMAP_DMA4_IRQENABLE_L0);	w &= ~(1 << lch);	writel(w, OMAP_DMA4_IRQENABLE_L0);	/* clear the CSR register and IRQ status register */	writel(0x0, OMAP_DMA4_CSR_REG(lch));	w = readl(OMAP_DMA4_IRQSTATUS_L0);	w |= 1 << lch;	writel(w, OMAP_DMA4_IRQSTATUS_L0);	/* Disable all DMA interrupts for the channel. */	writel(0, OMAP_DMA4_CICR_REG(lch));	/* Make sure the DMA transfer is stopped. */	writel(0, OMAP_DMA4_CCR_REG(lch));	clear_lch_regs(lch);}void omap_free_dma_chain(lch_chain * chain){	int i;	int ch = chain->queue_head;	int num_ch = chain->num_channels;	int lch = ch;	for (i = 0; i < num_ch; i++) {		ch = lch;		omap_free_dma(lch);		lch = dma_chan[lch].next_channel;		dma_chan[ch].next_channel = 0;	}	kfree(chain);	return;}void omap_clear_dma_chain(lch_chain * chain){	int i;	int ch = chain->queue_head;	int num_ch = chain->num_channels;	int lch = ch;	for (i = 0; i < num_ch; i++) {		clear_lch_regs(lch);		lch = dma_chan[lch].next_channel;	}	return;}static struct irqaction omap24xx_dma4_irq = {	.name = "OMAP24XX DMA IRQ demux",	.handler = omap24xx_dma4_irq_demux,	.flags = SA_INTERRUPT};int __init omap_init_dma(void){	int ch;	printk(KERN_INFO "OMAP DMA4 hardware Initialized ");	dma_chan_count = OMAP24XX_LOGICAL_DMA_CH_COUNT;	memset(&dma_chan, 0, sizeof(dma_chan));	spin_lock_init(&dma_chan_lock);	for (ch = 0; ch < dma_chan_count; ch++) {		clear_lch_regs(ch);		dma_chan[ch].reserved = -1;		dma_chan[ch].dev_id = -1;	}	/* register the ISR */	/* for 24xx we register a common ISR and then demuxing will be done inside the ISR */	setup_irq(INT_SDMA_IRQ0, &omap24xx_dma4_irq);#ifdef DMA_TEST	/*test */	dma_24xx_framework_test();#endif	return 0;}#ifdef DMA_TESTint dma_24xx_framework_test(){#define dev_name "dummy dev"	lch_chain *chain;	int dev_id = 1234;	//dummy	int dma_ch, ch1, ch2, ch3;	int ret;	int dummy_private_data;	int *buf1, *buf2, *buf3, *buf4;	int buf1_phys, buf2_phys;	dma_channel_params params;	buf1 = kmalloc(30000, GFP_KERNEL);	buf2 = kmalloc(30000, GFP_KERNEL);	buf1_phys = __virt_to_phys((int)buf1);	buf2_phys = __virt_to_phys((int)buf2);	printk(KERN_INFO	       "\n buf1 = %x, buf2 = %x  buf1_phys = %x buf2_phys = %x", buf1,	       buf2, buf1_phys, buf2_phys);/* simple chained dma transfer */#if 0	printk("\n simple dma chained transfer test ");	ret =	    omap_request_dma(dev_id, dev_name, NULL, &dummy_private_data, &ch1);	ret =	    omap_request_dma(dev_id, dev_name, NULL, &dummy_private_data, &ch2);	ret =	    omap_request_dma(dev_id, dev_name, NULL, &dummy_private_data, &ch3);	printk("\n dma channel allocated ch1= %d, ch2 = %d, ch3 = %d", ch1, ch2,	       ch3);	params.data_type = 0x1;	/* data type 16 */	params.elem_count = 1000;	params.frame_count = 1;	params.src_amode = 1;	/* post increment */	params.src_start = buf1_phys;	params.src_ei = 0;	params.src_fi = 0;	params.dst_amode = 1;	params.dst_start = buf2_phys;	/* source address : physical */	params.dst_ei = 0;	params.dst_fi = 0;	/* source frame index */	params.trigger = 0;	params.sync_mode = 0;	params.src_or_dst_synch = 0;	omap_set_dma_params(ch1, params);	params.src_start = buf1_phys + 1000;	params.dst_start = buf2_phys + 1000;	omap_set_dma_params(ch2, params);	params.src_start = buf1_phys + 2000;	params.dst_start = buf2_phys + 2000;	omap_set_dma_params(ch3, params);	setup_chain(ch1, ch2);	enable_chain(ch1, ch2);	setup_chain(ch2, ch3);	enable_chain(ch2, ch3);	omap_start_dma(ch1);	//printk(KERN_INFO "\n dma channel started waiting for interrupt");#endif/* simple dma transfer */#if 1	printk("\n simple dma transfer test");	ret =	    omap_request_dma(dev_id, dev_name, NULL, &dummy_private_data,			     &dma_ch);	printk("\n dma channel allocated = %d", dma_ch);	params.data_type = 0x1;	/* data type 16 */	params.elem_count = 4096;	params.frame_count = 1;	params.src_amode = 1;	/* post increment */	params.src_start = buf1_phys;	params.src_ei = 0;	params.src_fi = 0;	params.dst_amode = 1;	params.dst_start = buf2_phys;	/* source address : physical */	params.dst_ei = 0;	params.dst_fi = 0;	/* source frame index */	params.trigger = 0;	params.sync_mode = 0;	params.src_or_dst_synch = 0;	omap_set_dma_params(dma_ch, params);	omap_start_dma(dma_ch);	printk(KERN_INFO "\n dma channel started waiting for interrupt");#endif#if 0	printk("\n queued chained dma transfer test");	ret =	    omap_request_dma_chain(dev_id, dev_name, 3, NULL,				   &dummy_private_data, &dma_ch, &chain);	printk("\n dma channel allocated chained= %d", dma_ch);	params.data_type = 0x1;	/* data type 16 */	params.elem_count = 10000;	params.frame_count = 1;	params.src_amode = 1;	/* post increment */	params.src_start = buf1_phys;	params.src_ei = 0;	params.src_fi = 0;	params.dst_amode = 1;	params.dst_start = buf2_phys;	/* source address : physical */	params.dst_ei = 0;	params.dst_fi = 0;	/* source frame index */	params.trigger = 0;	params.sync_mode = 0;	params.src_or_dst_synch = 0;	ret = omap_set_dma_params_chain(chain, params);	ret = omap_start_dma_chain(chain);	params.src_start = buf1_phys + 10000;	params.dst_start = buf2_phys + 10000;	ret = omap_set_dma_params_chain(chain, params);	ret = omap_start_dma_chain(chain);	params.src_start = buf1_phys + 20000;	params.dst_start = buf2_phys + 20000;	ret = omap_set_dma_params_chain(chain, params);	ret = omap_start_dma_chain(chain);#endif	kfree(buf1);	kfree(buf2);	return 0;}#endif//#endif__initcall(omap_init_dma);EXPORT_SYMBOL(omap_request_dma);EXPORT_SYMBOL(omap_free_dma);EXPORT_SYMBOL(omap_start_dma);EXPORT_SYMBOL(omap_stop_dma);EXPORT_SYMBOL(omap_set_dma_transfer_params);EXPORT_SYMBOL(omap_set_dma_src_params);EXPORT_SYMBOL(omap_set_dma_dest_params);EXPORT_SYMBOL(omap_set_dma_params);EXPORT_SYMBOL(omap_get_dma_pos_src);EXPORT_SYMBOL(omap_get_dma_pos_dst);EXPORT_SYMBOL(omap_request_dma_chain);EXPORT_SYMBOL(omap_free_dma_chain);EXPORT_SYMBOL(omap_start_dma_chain);EXPORT_SYMBOL(omap_stop_dma_chain);EXPORT_SYMBOL(omap_set_dma_params_chain);EXPORT_SYMBOL(omap_clear_dma_chain);EXPORT_SYMBOL(omap_disable_dma_irq);EXPORT_SYMBOL(disable_chain);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -