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

📄 dma.c

📁 TI达芬奇 arm+dsp双核平台Davinci 6446 EVM板的linux下的 处理器平台底层代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		if (free_intr_no < 32) {			ptr_edmacc_regs->dra[0].drae =			    ptr_edmacc_regs->dra[0].drae | (1 << free_intr_no);		} else {			ptr_edmacc_regs->dra[0].draeh =			    ptr_edmacc_regs->dra[0].			    draeh | (1 << (free_intr_no - 32));		}	}	if (free_intr_no >= 0 && free_intr_no < 64) {		(free_intr_no < 32) ?		    (ptr_edmacc_regs->shadow[0].iesr |= (1UL << free_intr_no))		    : (ptr_edmacc_regs->shadow[0].iesrh |=		       (1UL << (free_intr_no - 32)));		intr_data[free_intr_no].callback = callback;		intr_data[free_intr_no].data = data;	}	return free_intr_no;}/****************************************************************************** * * Free the dma interrupt: Releases the dma interrupt on the channel * * Arguments: *      intr_no - interrupt number on the channel to be released or freed out * * Return: N/A * *****************************************************************************/static void free_dma_interrupt(int intr_no){	if (intr_no >= 0 && intr_no < 64) {		(intr_no < 32) ? (ptr_edmacc_regs->shadow[0].icr |=				  (1UL << (intr_no))) : (ptr_edmacc_regs->							 shadow[0].icrh |=							 (1UL <<							  (intr_no - 32)));		LOCK;		/* Global structure and could be modified by several task */		dma_intr_use_status[intr_no / 32] |= (1 << (intr_no % 32));		UNLOCK;		intr_data[intr_no].callback = NULL;		intr_data[intr_no].data = NULL;	}}/****************************************************************************** * * DMA interrupt handler * *****************************************************************************/static void dma_irq_handler(void){	int i;	unsigned int cnt;	cnt = 0;	if ((ptr_edmacc_regs->shadow[0].ipr == 0)	    && (ptr_edmacc_regs->shadow[0].iprh == 0))		return;	while (1) {		if (ptr_edmacc_regs->shadow[0].ipr) {			dev_dbg(&edma_dev.dev, "IPR =%d\r\n",				ptr_edmacc_regs->shadow[0].ipr);			for (i = 0; i < 32; i++) {				if (ptr_edmacc_regs->shadow[0].ipr & (1 << i)) {					/* Clear the corresponding IPR bits */					ptr_edmacc_regs->shadow[0].icr |=					    (1 << i);					if (intr_data[i].callback) {						intr_data[i].callback(i,								      DMA_COMPLETE,								      intr_data								      [i].data);					}				}			}		} else if (ptr_edmacc_regs->shadow[0].iprh) {			dev_dbg(&edma_dev.dev, "IPRH =%d\r\n",				ptr_edmacc_regs->shadow[0].iprh);			for (i = 0; i < 32; i++) {				if (ptr_edmacc_regs->shadow[0].iprh & (1 << i)) {					/* Clear the corresponding IPR bits */					ptr_edmacc_regs->shadow[0].icrh |=					    (1 << i);					if (intr_data[32 + i].callback) {						intr_data[32 + i].callback(32 +									   i,									   DMA_COMPLETE,									   intr_data									   [32 +									    i].									   data);					}				}			}		}		if ((ptr_edmacc_regs->shadow[0].ipr == 0)		    && (ptr_edmacc_regs->shadow[0].iprh == 0)) {			break;		}		cnt++;		if (cnt > 10) {			break;		}	}	ptr_edmacc_regs->shadow[0].ieval = 0x1;}/****************************************************************************** * * DMA error interrupt handler * *****************************************************************************/static void dma_ccerr_handler(void){	int i;	unsigned int cnt;	cnt = 0;	if ((ptr_edmacc_regs->emr == 0) && (ptr_edmacc_regs->emr == 0) &&	    (ptr_edmacc_regs->qemr == 0) && (ptr_edmacc_regs->ccerr == 0))		return;	while (1) {		if (ptr_edmacc_regs->emr) {			dev_dbg(&edma_dev.dev, "EMR =%d\r\n", ptr_edmacc_regs->emr);			for (i = 0; i < 32; i++) {				if (ptr_edmacc_regs->emr & (1 << i)) {					/* Clear the corresponding EMR bits */					ptr_edmacc_regs->emcr |= (1 << i);					/* Clear any SER */					ptr_edmacc_regs->shadow[0].secr |=					    (1 << i);					if (intr_data[i].callback) {						intr_data[i].callback(i,								      DMA_CC_ERROR,								      intr_data								      [i].data);					}				}			}		} else if (ptr_edmacc_regs->emrh) {			dev_dbg(&edma_dev.dev, "EMRH =%d\r\n",				ptr_edmacc_regs->emrh);			for (i = 0; i < 32; i++) {				if (ptr_edmacc_regs->emrh & (1 << i)) {					/* Clear the corresponding IPR bits */					ptr_edmacc_regs->emcrh |= (1 << i);					/* Clear any SER */					ptr_edmacc_regs->shadow[0].secrh |=					    (1 << i);					if (intr_data[i].callback) {						intr_data[i].callback(i,								      DMA_CC_ERROR,								      intr_data								      [i].data);					}				}			}		} else if (ptr_edmacc_regs->qemr) {			dev_dbg(&edma_dev.dev, "QEMR =%d\r\n",				ptr_edmacc_regs->qemr);			for (i = 0; i < 8; i++) {				if (ptr_edmacc_regs->qemr & (1 << i)) {					/* Clear the corresponding IPR bits */					ptr_edmacc_regs->qemcr |= (1 << i);					ptr_edmacc_regs->shadow[0].qsecr |=					    (1 << i);				}			}		} else if (ptr_edmacc_regs->ccerr) {			dev_dbg(&edma_dev.dev, "CCERR =%d\r\n",				ptr_edmacc_regs->ccerr);			for (i = 0; i < 8; i++) {				if (ptr_edmacc_regs->ccerr & (1 << i)) {					/* Clear the corresponding IPR bits */					ptr_edmacc_regs->ccerrclr |= (1 << i);				}			}		}		if ((ptr_edmacc_regs->emr == 0)		    && (ptr_edmacc_regs->emrh == 0)		    && (ptr_edmacc_regs->qemr == 0)		    && (ptr_edmacc_regs->ccerr == 0)) {			break;		}		cnt++;		if (cnt > 10) {			break;		}	}	ptr_edmacc_regs->eeval = 0x1;}/****************************************************************************** * * DMA error interrupt handler * *****************************************************************************/static void dma_tc1err_handler(void){}/****************************************************************************** * * DMA error interrupt handler * *****************************************************************************/static void dma_tc2err_handler(void){}/****************************************************************************** * * DMA initialisation on davinci * *****************************************************************************/int __init arch_dma_init(void){	int i;	edma_driver.name = "edma";	edma_dev.name = "dma";	edma_dev.id = -1;	edma_dev.dev.driver = &edma_driver;	ptr_edmacc_regs = get_edma_base();	dev_dbg(&edma_dev.dev, "DMA REG BASE ADDR=%x\n", ptr_edmacc_regs);	memset(dma_chan, 0x00, sizeof(dma_chan));	memset((void *)&(ptr_edmacc_regs->paramentry[0]), 0x00,	       sizeof(ptr_edmacc_regs->paramentry));	i = 0;	/* Channel to queue mapping */	while (channel_queue_mapping[i][0] != -1) {		map_dmach_queue(channel_queue_mapping[i][0],				channel_queue_mapping[i][1]);		i++;	}	i = 0;	/* Event queue to TC mapping */	while (queue_tc_mapping[i][0] != -1) {		map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]);		i++;	}	i = 0;	/* Event queue priority mapping */	while (queue_priority_mapping[i][0] != -1) {		assign_priority_to_queue(queue_priority_mapping[i][0],					 queue_priority_mapping[i][1]);		i++;	}	for (i = 0; i < DAVINCI_EDMA_NUM_REGIONS; i++) {		ptr_edmacc_regs->dra[i].drae = 0x0;		ptr_edmacc_regs->dra[i].draeh = 0x0;		ptr_edmacc_regs->qrae[i] = 0x0;	}	LOCK_INIT;	return 0;}/****************************************************************************** * * DMA channel requests: Requests for the dma device passed if it is free * * Arguments: *      dev_id     - request for the param entry device id *      dev_name   - device name *      callback   - pointer to the channel callback. *      Arguments: *          lch  - channel no, which is the IPR bit position, *		   indicating from which channel the interrupt arised. *          data - channel private data, which is received as one of the *		   arguments in davinci_request_dma. *      data - private data for the channel to be requested, which is used to *                   pass as a parameter in the callback function *		     in irq handler. *      lch - contains the device id allocated *  tcc        - Transfer Completion Code, used to set the IPR register bit *                   after transfer completion on that channel. *  eventq_no  - Event Queue no to which the channel will be associated with *               (valied only if you are requesting for a DMA MasterChannel) *               Values : 0 to 7 *                       -1 for Default queue * INPUT:   dev_id * OUTPUT:  *dma_ch_out * * Return: zero on success, or corresponding error no on failure * *****************************************************************************/int davinci_request_dma(int dev_id, const char *dev_name,			void (*callback) (int lch, unsigned short ch_status,					  void *data),			void *data, int *lch,			int *tcc, enum dma_event_q eventq_no){	int ret_val = 0, i = 0;	static int req_flag = 0;	int temp_ch = 0;	/* checking the ARM side events */	if (dev_id >= 0 && (dev_id < DAVINCI_EDMA_NUM_DMACH)) {		if (!(edma_channels_arm[dev_id / 32] & (0x1 << (dev_id % 32)))) {			dev_dbg(&edma_dev.dev,				"dev_id = %d not supported on ARM side\r\n",				dev_id);			return -EINVAL;		}	} else if (dev_id >= DAVINCI_EDMA_NUM_DMACH		   && dev_id <=		   (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		if (!(qdma_channels_arm[0] &		      (0x1 << (dev_id - DAVINCI_EDMA_NUM_DMACH)))) {			dev_dbg(&edma_dev.dev,				"dev_id = %d not supported on ARM side\r\n",				dev_id);			return -EINVAL;		}	}	if ((dev_id != DAVINCI_DMA_CHANNEL_ANY)	    && (dev_id != DAVINCI_EDMA_PARAM_ANY)) {		if (dev_id >= DAVINCI_EDMA_NUM_DMACH		    &&		    dev_id < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)		    ) {			ptr_edmacc_regs->qrae[0] =			    ptr_edmacc_regs->qrae[0] |			    (1 << (dev_id - DAVINCI_EDMA_NUM_DMACH));		} else {			if (dev_id < 32) {				ptr_edmacc_regs->dra[0].drae =				    ptr_edmacc_regs->dra[0].drae |				    (1 << dev_id);			} else {				ptr_edmacc_regs->dra[0].draeh =				    ptr_edmacc_regs->dra[0].draeh |				    (1 << (dev_id - 32));			}		}	}	if (!req_flag) {		if (register_dma_interrupts		    (dma_irq_handler, dma_ccerr_handler,		     dma_tc1err_handler, dma_tc2err_handler)) {			dev_dbg(&edma_dev.dev,				"register_dma_interrupts failed\r\n");			return -EINVAL;		} else			req_flag = 1;	}	if (dev_id >= 0 && dev_id < (DAVINCI_EDMA_NUM_DMACH)) {		/* The 64 Channels are mapped to the first 64 PARAM entries */		if (!dma_chan[dev_id].in_use) {			*lch = dev_id;			dma_chan[*lch].param_no = request_param(*lch, dev_id);			if (dma_chan[*lch].param_no == -1) {				return -EINVAL;			} else				dev_dbg(&edma_dev.dev, "param_no=%d\r\n",					dma_chan[*lch].param_no);			if (callback) {				dma_chan[*lch].tcc =				    request_dma_interrupt(*lch, callback, data,							  dma_chan[*lch].							  param_no, *tcc);				if (dma_chan[*lch].tcc == -1) {					return -EINVAL;				} else {					*tcc = dma_chan[*lch].tcc;					dev_dbg(&edma_dev.dev, "tcc_no=%d\r\n",						dma_chan[*lch].tcc);				}			} else				dma_chan[*lch].tcc = -1;			map_dmach_queue(dev_id, eventq_no);			ret_val = 0;		} else			ret_val = -EINVAL;	}	else if (dev_id >= DAVINCI_EDMA_NUM_DMACH && dev_id <		 (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {		if ((qdam_to_param_mapping[dev_id - DAVINCI_EDMA_NUM_DMACH] !=		     -1)		    &&		    (dma_chan		     [qdam_to_param_mapping[dev_id - DAVINCI_EDMA_NUM_DMACH]].		     in_use)		    ) {			ret_val = -EINVAL;		} else {			*lch = dev_id;			dma_chan[*lch].param_no = request_param(*lch, dev_id);			if (dma_chan[*lch].param_no == -1) {				dev_dbg(&edma_dev.dev, "request_param failed\r\n");				return -EINVAL;			} else {				dev_dbg(&edma_dev.dev, "param_no=%d\r\n",					dma_chan[*lch].param_no);				map_dmach_param(*lch, dma_chan[*lch].param_no);			}			if (callback) {				dma_chan[*lch].tcc =				    request_dma_interrupt(*lch, callback, data,							  dma_chan[*lch].							  param_no, *tcc);				if (dma_chan[*lch].tcc == -1) {					return -EINVAL;				} else {					*tcc = dma_chan[*lch].tcc;					dev_dbg(&edma_dev.dev, "tcc_no=%d\r\n",						dma_chan[*lch].tcc);				}			} else				dma_chan[*lch].tcc = -1;			map_dmach_queue(dev_id, eventq_no);			ret_val = 0;		}	} else if (dev_id == DAVINCI_DMA_CHANNEL_ANY) {		i = 0;		ret_val = 0;		while (dma_chan_no_event[i] != -1) {			if (!dma_chan[dma_chan_no_event[i]].in_use) {				*lch = dma_chan_no_event[i];				dma_chan[*lch].param_no =				    request_param(*lch, dev_id);				if (dma_chan[*lch].param_no == -1) {					return -EINVAL;

⌨️ 快捷键说明

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