TI论坛
直播中

望艳妮

7年用户 190经验值
私信 关注

Linux/AM3352: GPMC DMA transfer triggered by GPIO

本帖最后由 一只耳朵怪 于 2018-6-21 09:23 编辑

原来在e2e上发的问题,tony让我在这边发一下,麻烦帮我解答一下,谢谢。
Part Number: AM3352
Tool/software: Linux
CPU:AM335x
Linux Kernel:4.4.10
I'm working on am335x's dma, my goal is to use a gpio interrupt to trigger a EDMA's mem to mem transfer, that copying 8 bytes from GPMC SRAM to ram.
The trigger gpio is GP2[29], which is a indirect mapped dma event.
I add the dma binding code in dts file:
       When I use dma_request_chanl() API, I get a hw triggered dma channel but it does not have device_prep_dma_memcpy() function registed.
The cap_mask is 0x1E00, which DMA_MEMCPY bit is not set.

回帖(4)

李维兴

2018-6-21 06:40:34
可以发整体的文件给我吗?我这边测试一下
举报

望艳妮

2018-6-21 06:54:38
引用: uuwufydsw 发表于 2018-6-21 06:40
可以发整体的文件给我吗?我这边测试一下

附件是测试代码
有点乱,没怎么整理

有个init_dma函数有两份,一个是从dts申请通道的的,一个是直接request的
dts配置在上面帖子上
举报

望艳妮

2018-6-21 07:10:52
引用: uuwufydsw 发表于 2018-6-21 06:40
可以发整体的文件给我吗?我这边测试一下

any update?
举报

望艳妮

2018-6-21 07:21:00

问题自己已经解决
通过自己修改driver/edma.c,为edma的非memcpy通道也配置上mem_to_mem函数指针即可
static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)[        struct dma_device *s_ddev = &ecc->dma_slave;        struct dma_device *m_ddev = NULL;        s32 *memcpy_channels = ecc->info->memcpy_channels;        int i, j;        dma_cap_zero(s_ddev->cap_mask);        dma_cap_set(DMA_SLAVE, s_ddev->cap_mask);        dma_cap_set(DMA_CYCLIC, s_ddev->cap_mask);        if (ecc->legacy_mode && !memcpy_channels) [                dev_warn(ecc->dev,                         "Legacy memcpy is enabled, things might not workn");                dma_cap_set(DMA_MEMCPY, s_ddev->cap_mask);                s_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy;                s_ddev->directions = BIT(DMA_MEM_TO_MEM);        ]        s_ddev->device_prep_slave_sg = edma_prep_slave_sg;        s_ddev->device_prep_dma_cyclic = edma_prep_dma_cyclic;        s_ddev->device_alloc_chan_resources = edma_alloc_chan_resources;        s_ddev->device_free_chan_resources = edma_free_chan_resources;        s_ddev->device_issue_pending = edma_issue_pending;        s_ddev->device_tx_status = edma_tx_status;        s_ddev->device_config = edma_slave_config;        s_ddev->device_pause = edma_dma_pause;        s_ddev->device_resume = edma_dma_resume;        s_ddev->device_terminate_all = edma_terminate_all;        s_ddev->device_synchronize = edma_synchronize;        s_ddev->src_addr_widths = EDMA_DMA_BUSWIDTHS;        s_ddev->dst_addr_widths = EDMA_DMA_BUSWIDTHS;        s_ddev->directions |= (BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV));        s_ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;//////////////////////////////////////////////////////        /* cet,liudachuan: try to support mem_to_mem transfer */        s_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy;        s_ddev->directions |= BIT(DMA_MEM_TO_MEM);        /* end of mod *///////////////////////////////////////////////////////        s_ddev->dev = ecc->dev;        INIT_LIST_HEAD(&s_ddev->channels);        if (memcpy_channels) [                m_ddev = devm_kzalloc(ecc->dev, sizeof(*m_ddev), GFP_KERNEL);                ecc->dma_memcpy = m_ddev;                dma_cap_zero(m_ddev->cap_mask);                dma_cap_set(DMA_MEMCPY, m_ddev->cap_mask);                m_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy;                m_ddev->device_alloc_chan_resources = edma_alloc_chan_resources;                m_ddev->device_free_chan_resources = edma_free_chan_resources;                m_ddev->device_issue_pending = edma_issue_pending;                m_ddev->device_tx_status = edma_tx_status;                m_ddev->device_config = edma_slave_config;                m_ddev->device_pause = edma_dma_pause;                m_ddev->device_resume = edma_dma_resume;                m_ddev->device_terminate_all = edma_terminate_all;                m_ddev->device_synchronize = edma_synchronize;                m_ddev->src_addr_widths = EDMA_DMA_BUSWIDTHS;                m_ddev->dst_addr_widths = EDMA_DMA_BUSWIDTHS;                m_ddev->directions = BIT(DMA_MEM_TO_MEM);                m_ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;                m_ddev->dev = ecc->dev;                INIT_LIST_HEAD(&m_ddev->channels);        ] else if (!ecc->legacy_mode) [                dev_info(ecc->dev, "memcpy is disabledn");        ]        for (i = 0; i < ecc->num_channels; i++) [                struct edma_chan *echan = &ecc->slave_chans;                echan->ch_num = EDMA_CTLR_CHAN(ecc->id, i);                echan->ecc = ecc;                echan->vchan.desc_free = edma_desc_free;                if (m_ddev && edma_is_memcpy_channel(i, memcpy_channels))                        vchan_init(&echan->vchan, m_ddev);                else                        vchan_init(&echan->vchan, s_ddev);                INIT_LIST_HEAD(&echan->node);                for (j = 0; j < EDMA_MAX_SLOTS; j++)                        echan->slot[j] = -1;        ]]
举报

更多回帖

×
20
完善资料,
赚取积分