Hi,
I'm trying to get out of a problem with a driver using EDMA.
In first instance, I wrote a simple module, that simply take from a fixed
address of a EMIF device and put it in RAM.
The transaction seems to go well, but I'm not able to have an interrupt
when the EDMA cycle ends.
In fact, when I exec rmmod it shows me the buffer full of what I expected.
Someone has a working example for EDMA?
Or have already walked through similar issues?
For clarity, that's my console output:
# insmod dma_test.ko
### dma test module ###
dmatest - davinci_acquire_dma_channels() acquired lch: 0, tcc: 0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00
...
DMA started on lch:0
...
# rmmod dma_test.ko
11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11
00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00
11 00 11 00 11 00 11 00 11 00 11 00 11 00
And I expected to see something like this (and without necessity of rmmod):
DMA started on lch:0
**** davinci_dma_cb - ending DMA - ****
11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11
00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00 11 00
11 00 11 00 11 00 11 00 11 00 11 00 11 00
I'm using the code attached to this mail.
Thanks for any suggestions.
Bye!
--
Andrea Gasparini
---- ImaVis S.r.l. ----
web: www.imavis.com
#include <linux/module.h>
#include <asm/io.h>
#include <linux/dma-mapping.h>
#include <asm/dma-mapping.h>
#include <asm/arch/edma.h>
#include <asm/dma.h>
unsigned long emif_addr = 0x0400c200;
char *inputbuffer=NULL;
dma_addr_t dmabuffer=NULL;
int lch,tcc;
// ############### DEBUG FUNCS
#define EDMA_CC 0x01C00000
#define EDMA_TC0 0x01C10000
#define EDMA_TC1 0x01C10400
void *dmaregs[5] = {NULL,NULL,NULL,NULL,NULL};
static void mapdmaregs(){
// GLOBAL Registers
dmaregs[0] = ioremap_nocache(EDMA_CC+0x1000,0x6A);
// Shadow Region 0
dmaregs[1] = ioremap_nocache(EDMA_CC+0x2000,0x6A);
// PaRam set (stesso numero del chan dma) [4000h-4FFFh]
dmaregs[3] = ioremap_nocache(EDMA_CC+0x4000,0x20);
}
static void printdmaregs(void){
int i;
printk("Global Event Reg: %.8x @%p\n",readl(dmaregs[0]),dmaregs[0]);
printk("Global Set Event Reg: %.8x \n",readl(dmaregs[0]+0x10));
printk("Global Event Enable Reg: %.8x \n",readl(dmaregs[0]+0x20));
printk("Global Interrupt Enable Reg: %.8x \n",readl(dmaregs[0]+0x50));
printk("Global Interrupt Pending Reg: %.8x \n",readl(dmaregs[0]+0x68));
printk("Shadow 0 Event Reg: %.8x @%p\n",readl(dmaregs[1]),dmaregs[1]);
printk("Shadow 0 Set Event Reg: %.8x \n",readl(dmaregs[1]+0x10));
printk("Shadow 0 Event Enable Set Reg: %.8x \n",readl(dmaregs[1]+0x30));
printk("Shadow 0 Interrupt Pending Reg: %.8x \n",readl(dmaregs[1]+0x68));
printk("PaRam Set num 0 dump: ");
for( i = 0; i< 0x20 ; i+=4 ){
printk(" %.2x - %.8x ",i,readl(dmaregs[3]+i));
}
printk("\n");
}
static void unmapdmaregs(void){
int i;
for ( i=0; i<5 ; i++ ) {
if( dmaregs[i] != NULL )
iounmap(dmaregs[i]);
}
}
// ############### END DEBUG FUNCS
// EMIF -> RAM Transfer
static int davinci_send_dma_request(void* inputbuffer,unsigned int len){
u32 src_port, dst_port;
unsigned short acnt, bcnt, src_bidx, dst_bidx;
edmacc_paramentry_regs paregs;
dmabuffer = dma_map_single(NULL,inputbuffer,len,DMA_FROM_DEVICE);
acnt = 1;
bcnt = len/2;
dst_port = (u32) dmabuffer;
src_port = (u32) emif_addr;
src_bidx = 0;
dst_bidx = 2;
davinci_set_dma_src_params(lch, src_port, FIFO, W16BIT );
davinci_set_dma_dest_params(lch, dst_port, INCR, W16BIT );
davinci_set_dma_src_index(lch, src_bidx, 0);
davinci_set_dma_dest_index(lch, dst_bidx, 0);
davinci_set_dma_transfer_params(lch, acnt, bcnt, 1, 0, ABSYNC);
davinci_get_dma_params(lch, &paregs);
paregs.opt |= STATIC;
paregs.opt &= ~ITCCHEN;
paregs.opt &= ~TCCHEN;
paregs.opt &= ~ITCINTEN;
paregs.opt |= TCINTEN;
davinci_set_dma_params(lch, &paregs);
printk("DMA starting on lch: %d \n",lch);
printdmaregs();
davinci_start_dma(lch);
printk("DMA started on lch:%d \n",lch);
printdmaregs();
return 0;
}
static void davinci_abort_dma() {
davinci_stop_dma(lch);
davinci_clean_channel(lch);
}
static void davinci_dmatest_cb(int lch, u16 ch_status, void *data){
int i;
if (DMA_COMPLETE != ch_status) {
printk("fpga_net - DMA FAILED\n");
davinci_abort_dma();
return;
}
printk("davinci_dma_cb - ending DMA -\n");
for ( i = 0; i< 0x40 ; i++ ){
printk("%.2x ",inputbuffer[i]);
}
printk("\n");
dma_unmap_single(NULL,(void*)inputbuffer,0x40,DMA_FROM_DEVICE);
}
static int __init dmatest_init(void)
{
int r,i;
enum dma_event_q queue_no = EVENTQ_0;
int len = 0x40;
mapdmaregs();
printk(KERN_INFO "### dma test module ###\n");
lch = -1; //invalid
if ( (r = davinci_request_dma(EDMA_DMA_CHANNEL_ANY, "DMATEST", davinci_dmatest_cb, NULL,
&lch, &tcc, queue_no)) != 0) {
printk("dmatest - davinci_acquire_dma_channels() could not request channel -> %d\n",r);
return r;
}
printk("dmatest - davinci_acquire_dma_channels() acquired lch: %d, tcc: %d\n",lch,tcc);
// SETUP transmission:
inputbuffer = kmalloc(len*2,GFP_KERNEL);
memset(inputbuffer,0,len);
for ( i = 0; i< 0x40 ; i++ ){
printk("%.2x ",inputbuffer[i]);
}
davinci_send_dma_request(inputbuffer,len);
return 0;
}
static void __exit dmatest_cleanup(void)
{
int i;
for ( i = 0; i< 0x40 ; i++ ){
printk("%.2x ",inputbuffer[i]);
}
printk("\n");
davinci_free_dma(lch);
unmapdmaregs();
}
module_init(dmatest_init);
module_exit(dmatest_cleanup);
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source