EDMA allows simple transfers for block less than 64K. This program performs 2d transfer to copy large segments of memory. MVL Linux kernel already has this solution. This programs is for open source git kernel (tested on Arago Linux 2.6.32).
struct completion done;
#define trace(m) printk("%s:%i %s %s\n",__FILE__,__LINE__,__func__,m)
static void edma_copy_api_cb(unsigned lch, u16 ch_status, void *data)
{
trace("");
switch (ch_status) {
case DMA_COMPLETE:
break;
default:
trace("error");
break;
}
complete(&done);
}
int edma_copy(dma_addr_t dst, dma_addr_t src, int size)
{
volatile struct edma_param *par;
int chan = 0;
struct edmacc_param p_ram;
trace("");
init_completion(&done);
chan = edma_alloc_channel(EDMA_CHANNEL_ANY, edma_copy_api_cb, NULL, EVENTQ_DEFAULT);
edma_set_src(chan, src, INCR, W8BIT);
edma_set_dest(chan, dst, INCR, W8BIT);
edma_set_src_index(chan, 0, 0);
edma_set_dest_index(chan, 0, 0);
if (size < 0x10000) {
edma_set_transfer_params(chan, size, 1, 1, 0, ASYNC);
} else {
int chunk = 0x1000;
edma_set_transfer_params(chan, chunk, size / chunk, 1, 0, ABSYNC);
edma_set_src_index(chan, chunk, 0);
edma_set_dest_index(chan, chunk, 0);
}
edma_read_slot(chan, &p_ram);
p_ram.opt |= TCINTEN;
edma_write_slot(chan, &p_ram);
edma_clear_event(chan);
edma_start(chan);
if (! wait_for_completion_timeout(&done, 10)) {
// timed out
}
edma_stop(chan);
edma_free_channel(chan);
return 0;
}
If you found this program useful, please leave a note.
Regards
Constantine
http://www.LinuxDriver.co.il/
http://www.linux-davinci.info/