the hardware resource form TRM
DMA capabilities and channels
get the DAMC information Part 8. DMA

DMA base address
regitser summary Part 8. DMA
acces DMA registers
DMA MAX_OFFSET
get the offset register

DMA clock
Enable the DMA clock before use Part2. CRU

DMA reset
release reset at initialization;recover form error Part2. CRU

Completion IRQ / Abort IRQ (request ID)
register the completion ISR
GIC ID 64; DMAC1 =66;DMAC2=69;
device-tree
Binding
/home/user/SDK/rk3xxx/kernel-6.1/Documentation/devicetree/bindings/dma/arm,pl330.yaml /home/user/SDK/rk3xxx/kernel-6.1/Documentation/devicetree/bindings/dma/dma-controller.yaml 查看DMA 设备树属性
dmac0: dma-controller@2ab90000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x0 0x2ab90000 0x0 0x4000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_DMAC0>;
clock-names = "apb_pclk";
#dma-cells = <1>;
arm,pl330-periph-burst;
};
dmac1: dma-controller@2abb0000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x0 0x2abb0000 0x0 0x4000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_DMAC1>;
clock-names = "apb_pclk";
#dma-cells = <1>;
arm,pl330-periph-burst;
};
dmac2: dma-controller@2abd0000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x0 0x2abd0000 0x0 0x4000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_DMAC2>;
clock-names = "apb_pclk";
#dma-cells = <1>;
arm,pl330-periph-burst;
};
Change the target dts
在同目录下Makefile
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-test1-dma.dtb
把设备树加入编译
Add target config
Add SDK defconfig
新增板级配置碎片文件: /home/user/SDK/rk3xxx/kernel-6.1/arch/arm64/configs/rk3576-myboard.config
CONFIG_CAN=y
CONFIG_CAN_ROCKCHIP_CANFD=y
CONFIG_DMADEVICES=y
CONFIG_ARM_AMBA=y
CONFIG_DMA_ENGINE=y
CONFIG_PL330_DMA=y
CONFIG_DMATEST=y
在新板 SDK defconfig 中引用它:/home/user/SDK/rk3xxx/device/rockchip/.chips/rk3576/rockchip_rk3576_myboard_v10_defconfig 选择编译的dts和功能配置
RK_UBOOT_SPL=y
RK_KERNEL_DTS_NAME="rk3576-myboard-v10-linux"
RK_KERNEL_CFG_FRAGMENTS="rk3576-myboard.config"
Change the SDK build target kernel
./build.sh lunch //切换配置
select target defconfig
DMATEST
测试命令
Parameter

- 调整测试参数
echo 262208 > test_buf_size
echo 262144 > transfer_size
echo 1 > norandom
echo 0 > noverify
echo 100 > iterations
echo 1 > threads_per_chan
echo 5000 > timeout
- 指定dmac和channel
echo dma0chan0 > channel
echo 1 > run
MEM_TO_MEM DMATEST
Channel application and capability mask
Consumer在准备DMA之前,必须线取得支持当前操作的channel 当前模块要完成内存复制,因此申请channel时需要带上DMA_MEMCPY能力条件:
dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY, mask);
chan = dma_request_channel(mask, cc_dma, channel);
mask是capability mask,能力掩码,类型为dma_cap_mask_t。 Consumer用mask说明需要什么DMA能力,DMAEngine会把这些要求与各个Provider注册的dma_device.cap_mask进行比较
capabilities
dma_cap_zero()会清空mask,dma_cap_set()再降入当前需要的能力
module只设置了DMA_MEMCPY,因此DMAEngine只会继续检查声明支持内存复制的Provider
常用的capabilities如下:

channel application and realse
Consumer通过下面的接口申请和释放channel
struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
dma_fliter_fn filter_fn,
void *filter_param);
void dma_release_channel(struct dma_chan *chan);
dma_request_channel()的参数和返回结果如下:
channel模块参数默认设置为dma0chan0。dma_request_channel()完成DMA_MEMCPY能力匹配后,还会通过cc_dma_filter()比较channel名称与这个参数,只有名称一致的channel才会返回。