Zephyr ZDMA Driver Support

This page gives an overview of the ZDMA Zephyr driver which is available as part of the zephyr-amd repo.

Introduction

ZDMA is a general purpose DMA designed to support memory to memory and memory to IO buffer transfers. Zynq Ultrascale+ MPSoC has two instances of general purpose ZDMA. One is located in the FPD (full-power domain) and is usually called GDMA; the other is located in the LPD (low-power domain) and is usually called ADMA. Versal has one instance of general purpose DMA in the LPD (low-power domain), known as ADMA.

HW Features

Controller Features Supported

  • Each ADMA is configured with 8 DMA channels, and each channel can be programmed secure or non-secure.

  • It support two DMA Modes

    • Simple DMA mode

      • Normal data transfer from source to destination

      • Write Only mode

      • Read Only mode

    • Scatter Gather DMA mode

      • Normal data transfer from source to destination

  • In Scatter gather Mode there are three types of descriptors that h/w supports

    • Linear descriptor

    • Linked List descriptor

    • Hybrid descriptor

  • Interrupt Accounting Support

  • INCR and Fixed burst are supported.

For more details refer versal_trm

Design Notes

  • N/A

Implementation

Features Supported

  • Driver currently supports simple mode and SG mode transfer.

Missing Features

  • Read Only , Write Only mode.

  • SG mode support.

Known Issues

  • Lopper support is added for versalnet and Versal Gen 2 boards.

Limitations

  • N/A

Kernel Configuration

  • Configuration which needed to be enabled for DMA to be pulled.

    CONFIG_DMA = y
    

Device Tree

adma0: dma-controller@ebd00000 {
        phandle = <0x2d>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd00000 0x0 0x1000>;
        interrupts = <0x0 0x48 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};

adma1: dma-controller@ebd10000 {
        phandle = <0x2e>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd10000 0x0 0x1000>;
        interrupts = <0x0 0x49 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};

adma2: dma-controller@ebd20000 {
        phandle = <0x2f>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd20000 0x0 0x1000>;
        interrupts = <0x0 0x4a 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};

adma3: dma-controller@ebd30000 {
        phandle = <0x30>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd30000 0x0 0x1000>;
        interrupts = <0x0 0x4b 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};

adma4: dma-controller@ebd40000 {
        phandle = <0x31>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd40000 0x0 0x1000>;
        interrupts = <0x0 0x4c 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};

adma5: dma-controller@ebd50000 {
        phandle = <0x32>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd50000 0x0 0x1000>;
        interrupts = <0x0 0x4d 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};

adma6: dma-controller@ebd60000 {
        phandle = <0x33>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd60000 0x0 0x1000>;
        interrupts = <0x0 0x4e 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};

adma7: dma-controller@ebd70000 {
        phandle = <0x34>;
        compatible = "xlnx,zynqmp-dma-1.0";
        reg = <0x0 0xebd70000 0x0 0x1000>;
        interrupts = <0x0 0x4f 0x4 0xa0>;
        clock-names = "clk_main", "clk_apb";
        #dma-cells = <0x1>;
        xlnx,bus-width = <0x40>;
        clocks = <&adma_ref_clk>, <&adma_ref_clk>;
};
  • The DTS generated by SDTGEN has multiple properties for dma.

  • But the required properties are based on dt-bindings of dma driver and lopper filters it to only the required properties.

    • Lopper generates the current DT added here.

Driver Stack Size

  • TBA

Test Platform

  • VersalNet

  • Versal2

Test SoC Architecture

  • RPU - R52 core

  • APU - A78 core

Testing Sequence

We can use additional flags:

→ -G’Unix Makefile’ : To build by using Makefiles

→ -t run_qemu : To run the qemu which is wired to the SDK

→ -d : To map the build path

  • Build zephyr application for R52 or A78 core

    • west build -p -b <board> <sample application path>

  • Run zephyr elf on board or QEMU

Example Tests

Test Name

Example Source

Description

dmatest

zephyr/samples/drivers/dma/dmatest/

This example demonstrates how to use the DMAdriver API.

The current example test is created to test simple mode transfer in every channels. This same example
test application can be used to test other modes in the future by using their specific channels

chan_blen_transfer

zephyr/tests/drivers/dma/chan_blen_transfer/

This test application is used to check the simple memory to memory transfer for one channel

scatter_gather

zephyr/tests/drivers/dma/scatter_gather

This test application is used to test scatter gather mode of transfer from memory to memory.

Driver code coverage with dmatest -

Driver code coverage with chan_blen_transfer -

Driver code coverage with scatter_gather -

  • Report: <Needed to be added>

Expected Output

Dmatest

  • Versal2/Versalnet

    • samples/drivers/dma/dmatest

      • R52, A78

  • west build -p -b <board> samples/drivers/dma/dmatest/

  • Log:

*** Booting Zephyr OS build xilinx_v2024.2-228-g4c8616f9d1fe ***
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 0
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 1
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 2
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 3
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 4
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 5
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 6
I: Soft-resetting the DMA core!
I: DMA transfer completed on channel 7
I: DMA transfer verified successfully on channel 0
I: DMA transfer verified successfully on channel 1
I: DMA transfer verified successfully on channel 2
I: DMA transfer verified successfully on channel 3
I: DMA transfer verified successfully on channel 4
I: DMA transfer verified successfully on channel 5
I: DMA transfer verified successfully on channel 6
I: DMA transfer verified successfully on channel 7
I: DMA transfer verified all on channels
  • Versal Net RPU (Twister)

    • samples/drivers/dma/dmatest

      • R52:

  • ./scripts/twister -v -p versalnet_rpu -T ./samples/drivers/dma/dmatest/

  • Log Report:

> ./scripts/twister -v -p versalnet_rpu -T ./samples/drivers/dma/dmatest/
ZEPHYR_BASE unset, using "/home/user/zephyrprojects/zephyrproject/zephyr"
Renaming output directory to /home/user/zephyrprojects/zephyrproject/zephyr/twister-out.2
INFO    - Using Ninja..
INFO    - Zephyr version: xilinx_v2024.2-9-g67c2ab7f40e2
INFO    - Using 'zephyr' toolchain.
INFO    - Building initial testsuite list...
INFO    - Writing JSON report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/testplan.json
INFO    - JOBS: 20
INFO    - Adding tasks to the queue...
INFO    - Added initial list of jobs to queue
INFO    - 1/2 versalnet_rpu             samples/drivers/dma/dmatest/sample.drivers.dma     SKIPPED (runtime filter)
INFO    - 2/2 versalnet_rpu             samples/drivers/dma/dmatest/sample.drivers.dma.versalnet_rpu PASSED (build)
INFO    - 2 test scenarios (2 test instances) selected, 1 configurations skipped (0 by static filter, 1 at runtime).
INFO    - 1 of 2 test configurations passed (100.00%), 0 failed, 0 errored, 1 skipped with 0 warnings in 44.98 seconds
INFO    - In total 0 test cases were executed, 2 skipped on 1 out of total 1 platforms (100.00%)
INFO    - 0 test configurations executed on platforms, 1 test configurations were only built.
INFO    - Saving reports...
INFO    - Writing JSON report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/twister.json
INFO    - Writing xunit report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/twister.xml...
INFO    - Writing xunit report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/twister_report.xml...
INFO    - Run completed
  • Expected Output is the same as in the preceding test. Tested manually on the elf generated from the twister build; the twister command has not been tried to directly run it on the board.

Chan_blen Transfer

  • Versal2/Versalnet

    • tests/drivers/dma/chan_blen_transfer/

      • R52, A78

  • west build -p -b <board> tests/drivers/dma/chan_blen_transfer/ -DDTC_OVERLAY_FILE=/home/user/zephyrprojects/zephyrproject/zephyr/tests/drivers/dma/chan_blen_transfer/boards/versal2.overlay

  • Log:

*** Booting Zephyr OS build xilinx_v2024.2-9-g67c2ab7f40e2 ***
Running TESTSUITE dma_m2m
===================================================================
START - test_tst_dma0_m2m_chan0_burst16
Preparing DMA Controller: Name=dma-controller@ebd00000, Chan_ID=0, BURST_LEN=2
Starting the transfer
I: Soft-resetting the DMA core!
DMA transfer done
It is harder to be kind than to be wise........
 PASS - test_tst_dma0_m2m_chan0_burst16 in 2.006 seconds
===================================================================
START - test_tst_dma0_m2m_chan0_burst8
Preparing DMA Controller: Name=dma-controller@ebd00000, Chan_ID=0, BURST_LEN=1
Starting the transfer
DMA transfer done
It is harder to be kind than to be wise........
 PASS - test_tst_dma0_m2m_chan0_burst8 in 2.004 seconds
===================================================================
START - test_tst_dma0_m2m_chan1_burst16
Preparing DMA Controller: Name=dma-controller@ebd00000, Chan_ID=1, BURST_LEN=2
Starting the transfer
DMA transfer done
It is harder to be kind than to be wise........
 PASS - test_tst_dma0_m2m_chan1_burst16 in 2.004 seconds
===================================================================
START - test_tst_dma0_m2m_chan1_burst8
Preparing DMA Controller: Name=dma-controller@ebd00000, Chan_ID=1, BURST_LEN=1
Starting the transfer
DMA transfer done
It is harder to be kind than to be wise........
 PASS - test_tst_dma0_m2m_chan1_burst8 in 2.004 seconds
===================================================================
TESTSUITE dma_m2m succeeded
------ TESTSUITE SUMMARY START ------
SUITE PASS - 100.00% [dma_m2m]: pass = 4, fail = 0, skip = 0, total = 4 duration = 8.018 seconds
 - PASS - [dma_m2m.test_tst_dma0_m2m_chan0_burst16] duration = 2.006 seconds
 - PASS - [dma_m2m.test_tst_dma0_m2m_chan0_burst8] duration = 2.004 seconds
 - PASS - [dma_m2m.test_tst_dma0_m2m_chan1_burst16] duration = 2.004 seconds
 - PASS - [dma_m2m.test_tst_dma0_m2m_chan1_burst8] duration = 2.004 seconds
------ TESTSUITE SUMMARY END ------
===================================================================
PROJECT EXECUTION SUCCESSFUL
  • Versal Net RPU (Twister)

    • tests/drivers/dma/chan_blen_transfer/

      • R52:

  • ./scripts/twister -v -p versalnet_rpu -T ./tests/drivers/dma/chan_blen_transfer/

  • Log Report:

> ./scripts/twister -v -p versalnet_rpu -T ./tests/drivers/dma/chan_blen_transfer/
ZEPHYR_BASE unset, using "/home/user/zephyrprojects/zephyrproject/zephyr"
INFO    - Using Ninja..
INFO    - Zephyr version: xilinx_v2024.2-9-g67c2ab7f40e2
INFO    - Using 'zephyr' toolchain.
INFO    - Building initial testsuite list...
INFO    - Writing JSON report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/testplan.json
INFO    - JOBS: 20
INFO    - Adding tasks to the queue...
INFO    - Added initial list of jobs to queue
INFO    - 2/3 versalnet_rpu             tests/drivers/dma/chan_blen_transfer/drivers.dma.chan_blen_transfer SKIPPED (runtime filter)
INFO    - 3/3 versalnet_rpu             tests/drivers/dma/chan_blen_transfer/drivers.dma.chan_blen_transfer.versalnet_rpu PASSED (build)
INFO    - 3 test scenarios (3 test instances) selected, 2 configurations skipped (1 by static filter, 1 at runtime).
INFO    - 1 of 3 test configurations passed (100.00%), 0 failed, 0 errored, 2 skipped with 0 warnings in 46.52 seconds
INFO    - In total 4 test cases were executed, 2 skipped on 1 out of total 1 platforms (100.00%)
INFO    - 0 test configurations executed on platforms, 1 test configurations were only built.
INFO    - Saving reports...
INFO    - Writing JSON report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/twister.json
INFO    - Writing xunit report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/twister.xml...
INFO    - Writing xunit report /home/user/zephyrprojects/zephyrproject/zephyr/twister-out/twister_report.xml...
INFO    - Run completed
  • Expected Output is the same as in the preceding test. Tested manually on the elf generated from the twister build; the twister command has not been tried to directly run it on the board.

Scatter Gather Transfer

  • Versal2/Versalnet

    • tests/drivers/dma/scatter_gather/

      • R52, A78

  • west build -p -b <board> tests/drivers/dma/scatter_gather/

  • Log:

*** Booting Zephyr OS build xilinx_v2024.2-228-g4c8616f9d1fe ***
Running TESTSUITE dma_m2m_sg
===================================================================
START - test_dma_m2m_sg
DMA memory to memory transfer started
Preparing DMA Controller
Platform does not support dma request channel, using Kconfig DMA_SG_CHANNEL_NR
dma block 0 block_size 8192, source addr 1024000, dest addr 101c000
set next block pointer to 0x1026028
dma block 1 block_size 8192, source addr 1024000, dest addr 101e000
set next block pointer to 0x1026050
dma block 2 block_size 8192, source addr 1024000, dest addr 1020000
set next block pointer to 0x1026078
dma block 3 block_size 8192, source addr 1024000, dest addr 1022000
Configuring the scatter-gather transfer on channel 0
I: Soft-resetting the DMA core!
I: Configured SG mode with 4 descriptors
Starting the transfer on channel 0 and waiting completion
giving xfer_sem
Verify RX buffer should contain the full TX buffer string.
rx_data[0]
rx_data[1]
rx_data[2]
rx_data[3]
Finished: DMA Scatter-Gather
 PASS - test_dma_m2m_sg in 0.007 seconds
===================================================================
TESTSUITE dma_m2m_sg succeeded
------ TESTSUITE SUMMARY START ------
SUITE PASS - 100.00% [dma_m2m_sg]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.007 seconds
 - PASS - [dma_m2m_sg.test_dma_m2m_sg] duration = 0.007 seconds
------ TESTSUITE SUMMARY END ------
===================================================================
PROJECT EXECUTION SUCCESSFUL

Performance Metric

  • TBA

Mainline Status

  • Not in mainline as of 25-Feb-2025

Driver Source Path

  • Currently in local path

Misra C Report

  • Per coding guidelines of Zephyr

    • TBA