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

📄 dma.c

📁 TI达芬奇 arm+dsp双核平台Davinci 6446 EVM板的linux下的 处理器平台底层代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			dev_dbg(&edma_dev.dev, "ER=%d\r\n",				ptr_edmacc_regs->shadow[0].er);			/* Clear any pedning error */			(lch < 32) ?			    (ptr_edmacc_regs->emcr |=			     (1UL << lch)) :			    (ptr_edmacc_regs->emcrh |= (1UL << (lch - 32)));			/* Clear any SER */			(lch < 32) ?			    (ptr_edmacc_regs->shadow[0].secr |=			     (1UL << lch)) :			    (ptr_edmacc_regs->shadow[0].secrh |=			     (1UL << (lch - 32)));			(lch < 32) ?			    (ptr_edmacc_regs->shadow[0].eesr |=			     (1UL << lch)) :			    (ptr_edmacc_regs->shadow[0].eesrh |=			     (1UL << (lch - 32)));			dev_dbg(&edma_dev.dev, "EER=%d\r\n",				ptr_edmacc_regs->shadow[0].eer);			ret_val = 0;		}	} else if ((lch >= DAVINCI_EDMA_NUM_DMACH)		   && (lch <		       (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))) {		ptr_edmacc_regs->shadow[0].qeesr |=		    (1 << (lch - DAVINCI_EDMA_NUM_DMACH));		ret_val = 0;	} else {		/* for slaveChannels */		ret_val = EINVAL;	}	return ret_val;}/****************************************************************************** * * DMA Stop - Stops the dma on the channel passed * ARGUMENTS: *      lch - logical channel number * *****************************************************************************/void davinci_stop_dma(int lch){	if (lch < DAVINCI_EDMA_NUM_DMACH) {		int flag = 0;		int i = 0;		/* If the dma stop request is for the unused events */		while (dma_chan_no_event[i] != -1) {			if (dma_chan_no_event[i] == lch) {				/* EDMA channels without event association */				/* if the requested channel is one of the				   unused channels then reset the coresponding				   bit of ESR-Event Set Register */				flag = 1;				break;			}			i++;		}		if (!flag) {			/* EDMA channel with event association */			(lch < 32) ? (ptr_edmacc_regs->shadow[0].eecr |=				      (1UL << lch)) :			    (ptr_edmacc_regs->shadow[0].eecrh |=			     (1UL << (lch - 32)));			if (lch < 32) {				if (ptr_edmacc_regs->shadow[0].er & (1 << lch)) {					dev_dbg(&edma_dev.dev, "ER=%x\n",						ptr_edmacc_regs->shadow[0].er);					ptr_edmacc_regs->shadow[0].ecr |=					    (1 << lch);				}			} else {				if (ptr_edmacc_regs->shadow[0].erh				    & (1 << (lch - 32))) {					dev_dbg(&edma_dev.dev, "ERH=%x\n",						ptr_edmacc_regs->shadow[0].erh);					ptr_edmacc_regs->shadow[0].ecrh |=					    (1 << (lch - 32));				}			}			if (lch < 32) {				if (ptr_edmacc_regs->shadow[0].ser & (1 << lch)) {					dev_dbg(&edma_dev.dev, "SER=%x\n",						ptr_edmacc_regs->shadow[0].ser);					ptr_edmacc_regs->shadow[0].secr |=					    (1 << lch);				} else {				}			} else {				if (ptr_edmacc_regs->				    shadow[0].serh & (1 << (lch - 32))) {					dev_dbg(&edma_dev.dev, "SERH=%x\n",						ptr_edmacc_regs->shadow[0].						serh);					ptr_edmacc_regs->shadow[0].secrh |=					    (1 << (lch - 32));				}			}			if (lch < 32) {				if (ptr_edmacc_regs->emr & (1 << lch)) {					dev_dbg(&edma_dev.dev, "EMR=%x\n",						ptr_edmacc_regs->emr);					ptr_edmacc_regs->emcr |= (1 << lch);				}			} else {				if (ptr_edmacc_regs->emrh & (1 << (lch - 32))) {					dev_dbg(&edma_dev.dev, "EMRH=%x\n",						ptr_edmacc_regs->emrh);					ptr_edmacc_regs->emcrh |=					    (1 << (lch - 32));				}			}			dev_dbg(&edma_dev.dev, "EER=%d\r\n",				ptr_edmacc_regs->shadow[0].eer);			/* if the requested channel is one of the event channels			   then just set the link field of the corresponding			   param entry to 0xffff */		}	} else if ((lch >= DAVINCI_EDMA_NUM_DMACH)		   &&		   (lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))) {		/* for QDMA channels */		ptr_edmacc_regs->qeecr |= (1 << (lch - DAVINCI_EDMA_NUM_DMACH));		dev_dbg(&edma_dev.dev, "QER=%d\r\n", ptr_edmacc_regs->qer);		dev_dbg(&edma_dev.dev, "QEER=%d\r\n", ptr_edmacc_regs->qeer);	} else if ((lch >= (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))		   && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {		/* for slaveChannels */		ptr_edmacc_regs->paramentry[lch].link_bcntrld &= 0xffff0000;		ptr_edmacc_regs->paramentry[lch].link_bcntrld |= 0xffff;	} else {	}}/****************************************************************************** * * DMA channel link - link the two logical channels passed through by linking *                    the link field of head to the param pointed by the lch_queue. * ARGUMENTS: *      lch_head  - logical channel number, in which the link field is linked *                  to the param pointed to by lch_queue * lch_queue - logical channel number or the param entry number, which is to be *                  linked to the lch_head * *****************************************************************************/void davinci_dma_link_lch(int lch_head, int lch_queue){	unsigned long link;	int temp_ch = 0;	if (lch_head >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];		lch_head = temp_ch;	}	if (lch_queue >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];		lch_queue = temp_ch;	}	if ((lch_head >= 0 && lch_head < DAVINCI_EDMA_NUM_PARAMENTRY)	    && (lch_queue >= 0 && lch_queue < DAVINCI_EDMA_NUM_PARAMENTRY)) {		/* program LINK */		link =		    (unsigned		     long)(&			   (ptr_edmacc_regs->			    paramentry[dma_chan[lch_queue].param_no].opt));		ptr_edmacc_regs->		    paramentry[dma_chan			       [lch_head].param_no].link_bcntrld &= 0xffff0000;		ptr_edmacc_regs->		    paramentry[dma_chan			       [lch_head].			       param_no].link_bcntrld |= ((unsigned short)							  link);		dma_chan[lch_head].link_lch = lch_queue;	}}/****************************************************************************** * * DMA channel unlink - unlink the two logical channels passed through by *                   setting the link field of head to 0xffff. * ARGUMENTS: * lch_head - logical channel number, from which the link field is to be removed * lch_queue - logical channel number or the param entry number, which is to be *             unlinked from lch_head * *****************************************************************************/void davinci_dma_unlink_lch(int lch_head, int lch_queue){	int temp_ch = 0;	if (lch_head >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];		lch_head = temp_ch;	}	if (lch_queue >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];		lch_queue = temp_ch;	}	if ((lch_head >= 0 && lch_head < DAVINCI_EDMA_NUM_PARAMENTRY)	    && (lch_queue >= 0 && lch_queue < DAVINCI_EDMA_NUM_PARAMENTRY)) {		ptr_edmacc_regs->		    paramentry[dma_chan			       [lch_head].param_no].link_bcntrld |= 0xffff;		dma_chan[lch_head].link_lch = -1;	}}/****************************************************************************** * * DMA channel chain - chains the two logical channels passed through by * ARGUMENTS: * lch_head - logical channel number, from which the link field is to be removed * lch_queue - logical channel number or the param entry number, which is to be *             unlinked from lch_head * *****************************************************************************/void davinci_dma_chain_lch(int lch_head, int lch_queue){	int temp_ch = 0;	if (lch_head >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];		lch_head = temp_ch;	}	if (lch_queue >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];		lch_queue = temp_ch;	}	if ((lch_head >= 0	     && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))	    &&	    (lch_queue >= 0	     && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))	    ) {			/* set TCCHEN */		/* set TCCHEN */		ptr_edmacc_regs->paramentry[lch_head].opt |= TCCHEN;		/* program tcc */		ptr_edmacc_regs->paramentry[lch_head].opt &= (~TCC);		ptr_edmacc_regs->		    paramentry[lch_head].opt |= (lch_queue & 0x3f) << 12;	}}/****************************************************************************** * * DMA channel unchain - unchain the two logical channels passed through by * ARGUMENTS: * lch_head - logical channel number, from which the link field is to be removed * lch_queue - logical channel number or the param entry number, which is to be *             unlinked from lch_head * *****************************************************************************/void davinci_dma_unchain_lch(int lch_head, int lch_queue){	int temp_ch = 0;	if (lch_head >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];		lch_head = temp_ch;	}	if (lch_queue >=	    DAVINCI_EDMA_NUM_DMACH	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		temp_ch =		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];		lch_queue = temp_ch;	}	if ((lch_head >= 0	     && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))	    && (lch_queue >= 0		&& lch_queue <		(DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))) {		/* reset TCCHEN */		ptr_edmacc_regs->paramentry[lch_head].opt &= ~TCCHEN;	}}/****************************************************************************** * * It cleans ParamEntry qand bring back EDMA to initial state if media has * been removed before EDMA has finished.It is usedful for removable media. * Arguments: *      ch_no     - channel no * * Return: zero on success, or corresponding error no on failure * *****************************************************************************/void davinci_clean_channel(int ch_no){	int i;	dev_dbg(&edma_dev.dev, "EMR =%d\r\n", ptr_edmacc_regs->emr);	if (ch_no < 32) {		for (i = 0; i < 32; i++) {			if (ch_no == i) {				ptr_edmacc_regs->shadow[0].ecr |= (1 << i);				/* Clear the corresponding EMR bits */				ptr_edmacc_regs->emcr |= (1 << i);				/* Clear any SER */				ptr_edmacc_regs->shadow[0].secr |= (1 << i);				ptr_edmacc_regs->ccerrclr |= ((1 << 16) | 0x3);			}		}	}	if (ch_no > 32) {		dev_dbg(&edma_dev.dev, "EMRH =%d\r\n", ptr_edmacc_regs->emrh);		for (i = 0; i < 32; i++) {			if (ch_no == (i + 32)) {				ptr_edmacc_regs->shadow[0].ecrh |= (1 << i);				/* Clear the corresponding IPR bits */				ptr_edmacc_regs->emcrh |= (1 << i);				/* Clear any SER */				ptr_edmacc_regs->shadow[0].secrh |= (1 << i);				ptr_edmacc_regs->ccerrclr |= ((1 << 16) | 0x3);			}		}	}}/****************************************************************************** * * DMA interrupt handlers * *****************************************************************************/static int dma_irq_handler_l(int sound_curr_lch, void			     *ch_status, struct			     pt_regs			     *data){	dev_dbg(&edma_dev.dev, "dma_irq_handler\n");	(*cb[0]) ();	return IRQ_HANDLED;}static int    dma_ccerr_handler_l    (int sound_curr_lch, void *ch_status, struct pt_regs *data) {	dev_dbg(&edma_dev.dev, "dma_ccerr_handler\n");	(*cb[1]) ();	return IRQ_HANDLED;}static int    dma_tc1err_handler_l    (int sound_curr_lch, void *ch_status, struct pt_regs *data) {	dev_dbg(&edma_dev.dev, "dma_tc1err_handler\n");	(*cb[2]) ();	return IRQ_HANDLED;}static int    dma_tc2err_handler_l    (int sound_curr_lch, void *ch_status, struct pt_regs *data) {	dev_dbg(&edma_dev.dev, "dma_tc2err_handler\n");	(*cb[3]) ();	return IRQ_HANDLED;}int register_dma_interrupts    (intr_callback cb1,     intr_callback cb2, intr_callback cb3, intr_callback cb4) {	cb[0] = cb1;	cb[1] = cb2;	cb[2] = cb3;	cb[3] = cb4;	if (!cb1 || !cb2 || !cb3 || !cb4) {		dev_dbg(&edma_dev.dev, "NULL callback\n");		return -1;	}	if (request_irq(IRQ_CCINT0, dma_irq_handler_l, 0, "EDMA", NULL)) {		dev_dbg(&edma_dev.dev, "request_irq failed\n");		return -1;	}	if (request_irq	    (IRQ_CCERRINT, dma_ccerr_handler_l, 0, "EDMA CC Err", NULL)) {		dev_dbg(&edma_dev.dev, "request_irq failed\n");		return -1;	}	if (request_irq	    (IRQ_TCERRINT0, dma_tc1err_handler_l, 0, "EDMA TC1 Err", NULL)) {		dev_dbg(&edma_dev.dev, "request_irq failed\n");		return -1;	}	if (request_irq	    (IRQ_TCERRINT, dma_tc2err_handler_l, 0, "EDMA TC2 Err", NULL)) {		dev_dbg(&edma_dev.dev, "request_irq failed\n");		return -1;	}	return 0;}arch_initcall(arch_dma_init);EXPORT_SYMBOL(davinci_start_dma);EXPORT_SYMBOL(davinci_dma_link_lch);EXPORT_SYMBOL(davinci_set_dma_params);EXPORT_SYMBOL(davinci_get_dma_params);EXPORT_SYMBOL(davinci_set_dma_transfer_params);EXPORT_SYMBOL(davinci_set_dma_dest_index);EXPORT_SYMBOL(davinci_set_dma_src_index);EXPORT_SYMBOL(davinci_set_dma_dest_params);EXPORT_SYMBOL(davinci_set_dma_src_params);EXPORT_SYMBOL(davinci_request_dma);EXPORT_SYMBOL(davinci_stop_dma);EXPORT_SYMBOL(davinci_clean_channel);EXPORT_SYMBOL(davinci_free_dma);EXPORT_SYMBOL(davinci_dma_chain_lch);EXPORT_SYMBOL(davinci_dma_unchain_lch);EXPORT_SYMBOL(davinci_dma_unlink_lch);

⌨️ 快捷键说明

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