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

Reply via email to