Hi everybody.
I want to transfer data between FPGA and DM3730 using GPMC.
My linux platform driver works fine when I read from and write to FPGA using __reg_read and __reg_write functions.
However, when I want to use DMA over GPMC, I get two different problems:
1- if I use "omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, 0, OMAP_DMA_SRC_SYNC);"
after starting DMA, I will see that data transfer between FPGA and DM3730 takes place,
but I get this error: info: trying to register non-static key and kernel crashes.
2- if I use "omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);"
after starting DMA, nothing will happen between FPGA and DM3730 and DMA_callback function will not be called.
I appreciate any help or hint.
Here are important parts of my code:
*************************************************************
if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) { pr_err("Failed to request GPMC mem region\n"); return; } gpmc_fpga_resources[0].start = cs_mem_base + 0x0; gpmc_fpga_resources[0].end = cs_mem_base + 0x10000;
***************************************************************
static int fpga_probe(struct platform_device *p) {
struct fpga_device_data *pdata = p->dev.platform_data; res = platform_get_resource_byname(p, IORESOURCE_MEM, "fpga-memory"); request_mem_region(res->start, res_size, FPGA_CHIPNAME); pdata->phys_base = res->start; pdata->ioaddr = ioremap(res->start, res_size); err = omap_request_dma(OMAP24XX_DMA_GPMC, pdata->name, fpga_dma_callback, pdata, &pdata->dma_ch); return err; }
****************************************************
static void fpga_dma_callback(int channel_num, u16 ch_status, void *data) { struct fpga_device_data *pdata; pdata = (struct fpga_device_data *)data; complete(&pdata->dma_complete); }
*******************************************************
static int fpga_read(struct file *filp, char *buffer, size_t length, loff_t *offset) { struct miscdevice *misc; struct fpga_device_data *pdata; int size = 2048; char *DMA_buf = kmalloc(size, GFP_KERNEL | GFP_DMA); misc = filp->private_data; pdata = misc->this_device->platform_data; pdata->dma_phys_addr = dma_map_single(&pdata->dev, DMA_buf, size, DMA_FROM_DEVICE); if (dma_mapping_error(&pdata->dev, pdata->dma_phys_addr)) { pr_info("dma_map_single() failed\n"); kfree(DMA_buf); return -1; } else { pr_info("dma_map_single() succeeded: %d", pdata->dma_phys_addr); } omap_set_dma_src_params(pdata->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, pdata->phys_base, 0, 0); omap_set_dma_dest_params(pdata->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, pdata->dma_phys_addr, 0, 0); omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, 0, OMAP_DMA_SRC_SYNC); //omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC); //wait for interrupt line from FPGA
wait_event_interruptible(fpga_queue, fpga_flag != 0); init_completion(&pdata->dma_complete); omap_start_dma(pdata->dma_ch); wait_for_completion(&pdata->dma_complete); dma_unmap_single(&pdata->dev, pdata->dma_phys_addr, size, DMA_FROM_DEVICE); kfree(DMA_buf); fpga_flag =0; return 0; }