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_chanobjects - 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.
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:
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:
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.
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:
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:
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.
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:
For example:
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:
dmasdma-names
Example:
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:
The names are defined by the client binding and driver expectations.
dma_request_chan() Lookup Flow¶
The lookup process is illustrated below.
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:
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 managesstruct dma_device, and DMA controller drivers implementstruct 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.