📄 dma.c
字号:
} dev_dbg(&edma_dev.dev, "param_no=%d\r\n", dma_chan[*lch].param_no); if (dma_chan[*lch].param_no >= DAVINCI_EDMA_NUM_DMACH && dma_chan[*lch].param_no < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH) ) { ptr_edmacc_regs->qrae[0] = ptr_edmacc_regs->qrae[0] | (1 << (dma_chan[*lch].param_no - DAVINCI_EDMA_NUM_DMACH)); } else { if (dma_chan[*lch].param_no < 32) { ptr_edmacc_regs->dra[0].drae = ptr_edmacc_regs->dra[0].drae | (1 << dma_chan[*lch]. param_no); } else { ptr_edmacc_regs->dra[0].draeh = ptr_edmacc_regs->dra[0]. draeh | (1 << (dma_chan[*lch]. param_no - 32)); } } 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; } } else { dma_chan[*lch].tcc = -1; } map_dmach_queue(dev_id, eventq_no); ret_val = 0; break; } i++; } } else if (dev_id == DAVINCI_EDMA_PARAM_ANY) { ret_val = 0; for (i = (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH); i < DAVINCI_EDMA_NUM_PARAMENTRY; i++) { if (!dma_chan[i].in_use) { dev_dbg(&edma_dev.dev, "any link = %d\r\n", i); *lch = i; 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); } if (*tcc != -1) dma_chan[*lch].tcc = *tcc; else dma_chan[*lch].tcc = -1; ret_val = 0; break; } } } else { ret_val = -EINVAL; } if (!ret_val) { if (dev_id >= DAVINCI_EDMA_NUM_DMACH && dev_id < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { /* Master Channel */ qdam_to_param_mapping[dev_id - DAVINCI_EDMA_NUM_DMACH] = dma_chan[*lch].param_no; LOCK; /* It's used global data structure and used to find out whether channel is available or not */ dma_chan[qdam_to_param_mapping [dev_id - DAVINCI_EDMA_NUM_DMACH]].in_use = 1; UNLOCK; dma_chan[qdam_to_param_mapping [dev_id - DAVINCI_EDMA_NUM_DMACH]].dev_id = *lch; dma_chan[qdam_to_param_mapping [dev_id - DAVINCI_EDMA_NUM_DMACH]].tcc = dma_chan[*lch].tcc; temp_ch = qdam_to_param_mapping[dev_id - DAVINCI_EDMA_NUM_DMACH]; dma_chan[temp_ch].param_no = dma_chan[*lch].param_no; if (dma_chan[*lch].tcc != -1) { ptr_edmacc_regs->paramentry[dma_chan[temp_ch]. param_no].opt &= (~TCC); ptr_edmacc_regs->paramentry[dma_chan[temp_ch]. param_no].opt |= ((0x3f & dma_chan[*lch].tcc) << 12); /* set TCINTEN bit in PARAM entry */ ptr_edmacc_regs-> paramentry[dma_chan[temp_ch].param_no]. opt |= TCINTEN; } else { ptr_edmacc_regs->paramentry[dma_chan[temp_ch]. param_no].opt &= ~TCINTEN; } /* assign the link field to no link. i.e 0xffff */ ptr_edmacc_regs->paramentry[dma_chan[temp_ch]. param_no]. link_bcntrld |= 0xffff; } else { /* Slave Channel */ LOCK; /* Global structure to identify whether resoures is available or not */ dma_chan[*lch].in_use = 1; UNLOCK; dma_chan[*lch].dev_id = *lch; if (dma_chan[*lch].tcc != -1) { ptr_edmacc_regs->paramentry[dma_chan[*lch]. param_no].opt &= (~TCC); ptr_edmacc_regs->paramentry[dma_chan[*lch]. param_no].opt |= ((0x3f & dma_chan[*lch].tcc) << 12); /* set TCINTEN bit in PARAM entry */ ptr_edmacc_regs->paramentry[dma_chan[*lch]. param_no].opt |= TCINTEN; } else { ptr_edmacc_regs->paramentry[dma_chan[*lch]. param_no].opt &= ~TCINTEN; } /* assign the link field to no link. i.e 0xffff */ ptr_edmacc_regs->paramentry[dma_chan[*lch]. param_no]. link_bcntrld |= 0xffff; } } return ret_val;}/****************************************************************************** * * DMA channel free: Free dma channle * Arguments: * dev_id - request for the param entry device id * * Return: zero on success, or corresponding error no on failure * *****************************************************************************/void davinci_free_dma(int lch){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } LOCK; dma_chan[lch].in_use = 0; UNLOCK; free_param(dma_chan[lch].param_no); if (lch >= 0 && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { free_dma_interrupt(dma_chan[lch].tcc); }}/****************************************************************************** * * DMA source parameters setup * ARGUMENTS: * lch - channel for which the source parameters to be configured * src_port - Source port address * addressMode - indicates wether addressing mode is fifo. * *****************************************************************************/void davinci_set_dma_src_params(int lch, unsigned long src_port, enum address_mode mode, enum fifo_width width){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) { /* set the source port address in source register of param structure */ ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src = src_port; /* set the fifo addressing mode */ if (mode) { /* reset SAM and FWID */ ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt &= (~(SAM | EDMA_FWID)); /* set SAM and program FWID */ ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt |= (mode | ((width & 0x7) << 8)); } }}/****************************************************************************** * * DMA destination parameters setup * ARGUMENTS: * lch - channel or param device for destination parameters to be configured * dest_port - Destination port address * addressMode - indicates wether addressing mode is fifo. * *****************************************************************************/void davinci_set_dma_dest_params(int lch, unsigned long dest_port, enum address_mode mode, enum fifo_width width){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) { /* set the destination port address in dest register of param structure */ ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].dst = dest_port; /* set the fifo addressing mode */ if (mode) { /* reset DAM and FWID */ ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt &= (~(DAM | EDMA_FWID)); /* set DAM and program FWID */ ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt |= ((mode << 1) | ((width & 0x7) << 8)); } }}/****************************************************************************** * * DMA source index setup * ARGUMENTS: * lch - channel or param device for configuration of source index * srcbidx - source B-register index * srccidx - source C-register index * *****************************************************************************/void davinci_set_dma_src_index(int lch, short src_bidx, short src_cidx){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) { ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx &= 0xffff0000; ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx |= src_bidx; ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx &= 0xffff0000; ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx |= src_cidx; }}/****************************************************************************** * * DMA destination index setup * ARGUMENTS: * lch - channel or param device for configuration of destination index * srcbidx - dest B-register index * srccidx - dest C-register index * *****************************************************************************/void davinci_set_dma_dest_index(int lch, short dest_bidx, short dest_cidx){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) { ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx &= 0x0000ffff; ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx |= ((unsigned long)dest_bidx << 16); ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx &= 0x0000ffff; ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx |= ((unsigned long)dest_cidx << 16); }}/****************************************************************************** * * DMA transfer parameters setup * ARGUMENTS: * lch - channel or param device for configuration of aCount, bCount and * cCount regs. * acnt - acnt register value to be configured * bcnt - bcnt register value to be configured * ccnt - ccnt register value to be configured * *****************************************************************************/void davinci_set_dma_transfer_params(int lch, unsigned short acnt, unsigned short bcnt, unsigned short ccnt, unsigned short bcntrld, enum sync_dimension sync_mode){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) { ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].link_bcntrld &= 0x0000ffff; ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].link_bcntrld |= (bcntrld << 16); if (sync_mode == ASYNC) ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt &= (~SYNCDIM); else ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt |= SYNCDIM; /* Set the acount, bcount, ccount registers */ ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].a_b_cnt = (bcnt << 16) | acnt; ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].ccnt = ccnt; }}/****************************************************************************** * * davinci_set_dma_params - * ARGUMENTS: * lch - logical channel number * *****************************************************************************/void davinci_set_dma_params(int lch, edmacc_paramentry_regs * temp){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) { memcpy((void *) &(ptr_edmacc_regs-> paramentry[dma_chan[lch].param_no].opt), (void *)temp, sizeof(edmacc_paramentry_regs)); }}/****************************************************************************** * * davinci_get_dma_params - * ARGUMENTS: * lch - logical channel number * *****************************************************************************/void davinci_get_dma_params(int lch, edmacc_paramentry_regs * temp){ int temp_ch = 0; if (lch >= DAVINCI_EDMA_NUM_DMACH && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) { temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH]; lch = temp_ch; } if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) { memcpy((void *)temp, (void *)&(ptr_edmacc_regs-> paramentry[dma_chan[lch].param_no].opt), sizeof(edmacc_paramentry_regs)); }}/****************************************************************************** * * DMA Strat - Starts the dma on the channel passed * ARGUMENTS: * lch - logical channel number * *****************************************************************************/int davinci_start_dma(int lch){ int ret_val; if (lch >= 0 && (lch < DAVINCI_EDMA_NUM_DMACH)) { int i = 0; int flag = 0; /* If the dma start 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 */ dev_dbg(&edma_dev.dev, "ESR=%x\r\n", ptr_edmacc_regs->shadow[0].esr); (lch < 32) ? (ptr_edmacc_regs->shadow[0].esr |= (1UL << lch)) : (ptr_edmacc_regs-> shadow[0].esrh |= (1UL << (lch - 32))); flag = 1; ret_val = 0; break; } i++; } if (!flag) { /* EDMA channel with event association */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -