Skip to content

DMA Controller Driver and DMA Channel

Note

This topic explains how DMA controller drivers register hardware resources with the Linux DMA Engine Framework and how client drivers obtain DMA channels.

DMA descriptor preparation, transaction submission, execution, and completion are covered in the following chapters of the DMA Engine series.

Overview

A DMA controller is hardware that performs data transfers without requiring the CPU to copy every byte.

Because DMA controllers differ across SoCs, Linux uses hardware-specific DMA controller drivers behind the generic DMA Engine Framework.

The DMA controller driver:

  • Initializes the DMA controller hardware
  • Represents the controller using struct dma_device
  • Creates and manages struct dma_chan objects
  • Advertises supported DMA capabilities
  • Implements hardware-specific operation callbacks
  • Registers the controller with the DMA Engine Framework

Client drivers do not directly access DMA controller registers. They request a suitable DMA channel from the framework and use generic DMA Engine APIs.


Architecture

The DMA subsystem separates client-facing operations from hardware-specific control.

Client Driver
        │ Generic DMA Engine APIs
DMA Engine Framework
        │ Controller Operation Callbacks
DMA Controller Driver
        │ Register Access
DMA Controller Hardware
        │ Data Transfer
Memory  ◀──────────────▶  Peripheral

Responsibilities of each layer:

Layer Responsibility
Client Driver Requests DMA resources and describes the required transfer.
DMA Engine Framework Provides generic APIs and manages registered controllers and channels.
DMA Controller Driver Implements hardware-specific channel, descriptor, register, and interrupt handling.
DMA Controller Hardware Performs the actual transfer between memory and a peripheral or between memory regions.

The DMA Engine Framework does not understand the register layout or descriptor format of a specific controller. Instead, it invokes callbacks implemented by the corresponding DMA controller driver.

The overall architecture is illustrated below.

Linux DMA Engine architecture


Why DMA Controller Drivers Exist

Different DMA controllers vary in areas such as:

  • Register layout
  • Number and organization of channels
  • DMA request routing
  • Descriptor format
  • Interrupt handling
  • Transfer width and alignment restrictions
  • Scatter-gather support
  • Cyclic transfer support
  • Hardware offload capabilities

Without a hardware-independent framework, every UART, SPI, audio, storage, or networking driver would need controller-specific DMA code.

Linux therefore separates the subsystem into two driver roles:

Driver Role Purpose
DMA Client Driver Uses DMA services to transfer data.
DMA Controller Driver Provides DMA services by controlling controller-specific hardware.

DMA controller drivers are also called DMA providers. Client drivers are DMA consumers.


DMA Engine Framework and Controller Drivers

A DMA controller driver registers its controller with the DMA Engine Framework.

After registration, the framework can discover:

  • Which DMA controllers are available
  • Which transaction types each controller supports
  • Which channels belong to each controller
  • Which hardware-specific callbacks should be invoked
  • How firmware descriptions map a client request to a controller channel

The framework manages generic objects and resource relationships. It does not program controller registers directly.

This follows a common Linux design pattern:

Generic Framework
Operation Callbacks
Hardware-Specific Driver
Hardware

Similar patterns appear in VFS, gpiolib, networking, and other kernel subsystems.


struct dma_device

struct dma_device represents one DMA controller inside the DMA Engine Framework.

It is defined in:

include/linux/dmaengine.h

A controller driver initializes the object and registers it with the framework.

Responsibilities

The major responsibilities of struct dma_device can be grouped as follows:

Category Purpose
Identity Associates the DMA controller with the Linux Device Model.
Capabilities Describes the DMA transaction types supported by the controller.
Channels Maintains the channels provided by this controller.
Operations Exposes hardware-specific callback implementations to the framework.
Framework linkage Links the controller into the DMA Engine global device list.

struct dma_device does not represent an individual transfer. It represents the controller and the services that the controller can provide.

Capabilities

A DMA controller may support one or more transaction types, including:

  • Memory copy
  • Memory set
  • Slave DMA
  • Cyclic DMA
  • Interleaved DMA
  • XOR offload
  • RAID6 P/Q parity generation

The controller advertises supported transaction types through its capability mask.

Some controllers also report specialized capability limits.

Member Purpose
max_xor Maximum number of source buffers supported by one hardware XOR operation.
max_pq Maximum number of source buffers supported by one RAID6 P/Q parity operation.

These fields are mainly relevant to storage and RAID acceleration hardware. They are normally unrelated to ordinary UART, SPI, I2S, or other peripheral DMA transfers.

Operation Callbacks

The operation callbacks in struct dma_device are implemented by the DMA controller driver.

Examples include callbacks for:

  • Allocating channel resources
  • Releasing channel resources
  • Preparing memory-copy transactions
  • Preparing slave scatter-gather transactions
  • Issuing pending work
  • Reporting transaction status
  • Terminating active or queued work

A typical call path is:

Client Driver
Public DMA Engine API
DMA Engine Framework
struct dma_device Callback
DMA Controller Driver
DMA Controller Hardware

The device_* callback members are controller-facing operations. They are not normally called directly by DMA client drivers.


DMA Device and Channel Lists

Two struct list_head members in struct dma_device participate in different list hierarchies.

Member Purpose
channels List head for all struct dma_chan objects owned by this controller.
global_node Node that links this struct dma_device into the framework's global DMA device list.

The relationship between registered DMA controllers and their channel lists is illustrated below.

DMA device and channel relationship

The DMA Engine Framework owns the global controller list, while each struct dma_device maintains its own local list of struct dma_chan objects.


struct dma_chan

struct dma_chan represents one DMA channel provided by a DMA controller.

It is also defined in:

include/linux/dmaengine.h

One struct dma_device normally owns one or more channel objects.

As shown in the previous diagram, one struct dma_device normally owns one or more struct dma_chan objects.

Responsibilities

A channel object has several conceptual responsibilities:

Responsibility Description
Parent controller Refers to the struct dma_device that provides the channel.
DMA resource Represents a controller-provided transfer resource.
Channel identity Distinguishes the channel within the framework or controller driver.
Client handle Provides the object returned to a DMA client driver.
Transfer context Becomes the starting point for later descriptor and transaction operations.

A client driver normally stores channel pointers such as:

struct dma_chan *rx_chan;
struct dma_chan *tx_chan;

The client driver does not create these objects. The DMA controller driver creates and initializes them, and the DMA Engine Framework manages their allocation to clients.

The value in a Device Tree DMA specifier must not be assumed to match dma_chan->chan_id. DMA specifiers are interpreted according to the controller binding.


DMA Controller Registration Lifecycle

DMA controller registration normally occurs during the controller driver's probe() function.

The overall registration lifecycle is illustrated below.

DMA controller probe lifecycle

During probe(), the controller driver initializes hardware resources, creates the controller and channel objects, and finally registers the DMA controller with the DMA Engine Framework.

After registration, the DMA Engine Framework can use the controller when a client driver requests a channel.

If a client driver probes before its DMA provider is ready, channel acquisition may return -EPROBE_DEFER. The client probe can then be retried after the provider has registered.


DMA Channel Allocation

Client drivers normally request DMA channels through:

struct dma_chan *dma_request_chan(struct device *dev,
                                  const char *name);

For example:

rx_chan = dma_request_chan(dev, "rx");

The name "rx" is a logical DMA connection name. It is not a hardware channel number.

dma_request_chan() does not create a new channel. It resolves the client's firmware description and returns an existing struct dma_chan provided by a registered DMA controller.


Device Tree Integration

Device Tree commonly describes the relationship between a peripheral and its DMA provider using:

  • dmas
  • dma-names

Example:

uart0 {
    dmas = <&dma0 5>,
           <&dma0 6>;
    dma-names = "rx", "tx";
};

The two properties correspond by index:

Index dma-names dmas
0 "rx" <&dma0 5>
1 "tx" <&dma0 6>

When the UART driver requests "rx", the lookup resolves index 0 and uses the corresponding dmas entry.

dmas

Each dmas entry contains:

  • A phandle referencing a DMA controller provider
  • One or more provider-specific DMA specifier cells

The meaning of the specifier cells is defined by the DMA controller's Device Tree binding.

Depending on the hardware, the cells may describe:

  • DMA request line
  • Physical channel or stream
  • DMA multiplexer selection
  • Routing information
  • Priority
  • Transfer configuration flags

The generic framework does not assign a universal meaning to these values.

dma-names

dma-names assigns logical names to the entries in dmas.

The client driver uses these names without depending on controller-specific channel numbering or routing details.

Typical logical names include:

rx
tx
memcpy
capture
playback

The names are defined by the client binding and driver expectations.


dma_request_chan() Lookup Flow

The lookup process is illustrated below.

dma_request_chan lookup flow

When a client driver calls dma_request_chan(), the DMA Engine Framework:

  • Looks up the requested logical name in dma-names.
  • Reads the corresponding entry in dmas.
  • Locates the referenced DMA controller provider.
  • Invokes the provider-specific translation function.
  • Returns the matching struct dma_chan.

Therefore, channel acquisition is not simply:

Scan Every Controller
Return the First Free Channel

The firmware description identifies the intended DMA provider and connection before provider-specific translation resolves the corresponding channel resource.


Complete Resource Lifecycle

The complete controller and channel acquisition lifecycle is:

DMA Controller Driver
        │ probe()
Create struct dma_device
Create struct dma_chan Objects
Register with DMA Engine Framework
Client Driver probe()
        │ dma_request_chan()
Resolve Firmware DMA Connection
Return Existing struct dma_chan *
Client Prepares DMA Transactions
Descriptor Preparation
(Continued in Day101)

No DMA transfer has started when the client receives the channel.

Channel acquisition only establishes which DMA resource the client will use. Descriptor preparation, submission, hardware execution, and completion occur later in the DMA transaction lifecycle.

A concise mental model is:

Client drivers use struct dma_chan, the DMA Engine Framework manages struct dma_device, and DMA controller drivers implement struct dma_device.


Linux Source Layout

Important source locations include:

Location Purpose
include/linux/dmaengine.h Defines DMA Engine objects, capabilities, callbacks, and public interfaces.
drivers/dma/dmaengine.c Implements DMA Engine core behavior and registered-device management.
drivers/dma/of-dma.c Implements Device Tree DMA provider registration and channel lookup support.
drivers/dma/virt-dma.c Provides reusable virtual-channel and descriptor-queue helpers.
drivers/dma/ Contains hardware-specific DMA controller drivers.

When reading drivers/dma/, distinguish framework support files from hardware-specific controller implementations.

include/linux/dma-mapping.h belongs primarily to the DMA mapping subsystem. DMA mapping and DMA Engine solve related but different problems and should not be treated as the same framework.


Summary

Linux uses DMA controller drivers to hide hardware-specific DMA implementation details behind the DMA Engine Framework.

One DMA controller is normally represented by one struct dma_device. The controller object advertises capabilities, provides operation callbacks, and owns one or more struct dma_chan objects.

The controller driver creates and registers these objects during probe. A client driver later calls dma_request_chan() with a logical name. The framework uses the client's firmware description, such as Device Tree dmas and dma-names, to locate the intended provider and obtain an existing DMA channel.

This establishes the DMA resource relationship before any descriptor is prepared or transfer is submitted.