工具/软件:
尊敬的同事:
在这一刻,我正在努力将源代码从 3.2 Linux 内核移植到 6.12(是的,这是相当大的跳跃:))。
我使用的内核来自: git.ti.com/.../
在我的器件中、我使用 GPMC 总线与 FPGA 进行通信。 为了加快传输过程、我使用 DMA。
下面展示了 3.2 内核的代码片段:
dma_ch = edma_alloc_channel(EDMA_CHANNEL_ANY, dma_complete_callback, NULL, EVENTQ_DEFAULT);
edma_set_src (dma_ch, (dma_addr_t)(FPGA_BASE_DMA), INCR, W16BIT);
edma_set_dest(dma_ch, dmaphysdest + (bufnum * frame_size) +
(portion * dma_transfer_size), INCR, W16BIT);
edma_set_src_index(dma_ch, dma_transfer_size, dma_transfer_size);
edma_set_dest_index(dma_ch, dma_transfer_size, dma_transfer_size);
// Use A-Sync Transfer Mode
edma_set_transfer_params(dma_ch, dma_transfer_size,
dma_bcount,
dma_ccount,
dma_bcount_reload, ASYNC);
edma_read_slot(dma_ch, ¶m_set);
// disable the Intermediate Int's
param_set.opt &= ~(ITCINTEN);
if ((dma_bcount > 1) || (dma_ccount > 1)){
// enable the Intermediate Int's
//param_set.opt |= (ITCINTEN);
// enable chaining
param_set.opt |= (ITCCHEN);
}else{
// disable the Intermediate Int's
param_set.opt &= ~(ITCINTEN);
// disble chaining
param_set.opt &= ~(ITCCHEN);
}
// enable the final int tc
param_set.opt |= (TCINTEN);
param_set.opt |= EDMA_TCC((dma_ch & 0x3f));
param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(dma_ch));
edma_write_slot(dma_ch, ¶m_set);
edma_start(dma_ch);
3.2 上的代码运行良好。
在 6.12 上、我必须使用 dmaengine。
我的器件树相关 GPMC 如下所示:
&gpmc {
pinctrl-names = "default";
pinctrl-0 = <&gpmc_pins>;
compatible = "test,fpga";
interrupts = <100>;
gpmc,num-cs = <2>;
gpmc,num-waitpins = <2>;
status = "okay";
dmas = <&edma 52 0>;
dma-names = "rx";
interrupt-controller;
#interrupt-cells = <2>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x08000000 0x01000000 /* CS0 @addr 0x08000000, size 0x1000000 */
1 0 0x09000000 0x01000000>; /* CS1 @addr 0x09000000, size 0x1000000 */
fpga_control@0,0 {
status = "okay";
#address-cells = <1>;
#size-cells = <1>;
reg = <0 0 0x01000000>;
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
};
fpga_stream@1,0 {
status = "okay";
#address-cells = <1>;
#size-cells = <1>;
reg = <1 0 0x01000000>;
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
};
};
我从源代码中配置 GPMC 寄存器、就像之前在 3.2 上配置的一样、如下所示:
CS[0] GPMC_CONFIG1 0xA9401001 CS[0] GPMC_CONFIG2 0x00060800 CS[0] GPMC_CONFIG3 0x00020200 CS[0] GPMC_CONFIG4 0x04020600 CS[0] GPMC_CONFIG5 0x0204080A CS[0] GPMC_CONFIG6 0x040702C0 CS[0] GPMC_CONFIG7 0x00000F48 CS[1] GPMC_CONFIG1 0xE9401001 CS[1] GPMC_CONFIG2 0x00060800 CS[1] GPMC_CONFIG3 0x00020200 CS[1] GPMC_CONFIG4 0x04020600 CS[1] GPMC_CONFIG5 0x0204080A CS[1] GPMC_CONFIG6 0x040702C0 CS[1] GPMC_CONFIG7 0x00000F49
负责启动 DMA 的源代码:
void __iomem* dma_virt_addr = dma_alloc_coherent(dev->parent, 1024*1024, &dma_addr, GFP_KERNEL);
memset(&dma_cfg, 0, sizeof(dma_cfg));
dma_cfg.direction = DMA_DEV_TO_MEM;
dma_cfg.src_addr = fpga_stream.gpmc_base.start; //0x09000000
dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
dma_cfg.src_maxburst = 16;
ret = dmaengine_slave_config(fpga_stream.dma_ch, &dma_cfg);
if (ret) {
DRV_MSG("DMA engine slave config failed: %d\n", ret);
return -1;
}
dma_desc = dmaengine_prep_slave_single(fpga_stream.dma_ch, dma_addr, 1024, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!dma_desc)
{
DRV_MSG("DMA busy\n");
return -1;
}
dma_desc->callback = dma_complete_callback;
dma_desc->callback_param = NULL;
dma_cookie = dmaengine_submit(dma_desc);
if (dma_submit_error(dma_cookie)) {
DRV_MSG("DMA transaction submission FAILED\n");
return -1;
}
DRV_MSG("DMA transaction submission SUCCESS\n");
dma_async_issue_pending(fpga_stream.dma_ch);
DRV_MSG("DMA start\n");
在 dmesg 上、我看到 DMA 通道已配置:
[ 67.974832] edma 49000000.dma: Got eDMA channel 52 for virt channel 50 (HW trigger) [ 68.056257] edma 49000000.dma: vchan a74ee4d7: txd fd8f725f[2]: submitted [ 68.062970] edma 49000000.dma: [ 68.062970] pset[0]: [ 68.062970] chnum 52 [ 68.062970] slot 49 [ 68.062970] opt 00134004 [ 68.062970] src 09000000 [ 68.062970] dst 95100000 [ 68.062970] abcnt 00100004 [ 68.062970] ccnt 00000010 [ 68.062970] bidx 00040000 [ 68.062970] cidx 00400000 [ 68.062970] lkrld ffffffff [ 68.062995] edma 49000000.dma: first transfer starting on channel 52 [ 68.063008] edma 49000000.dma: ER1 00000000 [ 68.063021] edma 49000000.dma: EER1 00100000
我的问题是我看不到 DMA 完全回调。 在 3.2 内核回调中正确执行、没有任何问题。
我将感谢任何关于这种行为的原因的建议。
提前感谢!
