DEV Community

Ripan Deuri
Ripan Deuri

Posted on

PCIe Configuration Space Explained: ECAM, iATU, and Config TLPs

Introduction

PCI Express (PCIe) devices expose a standardized Configuration Space that allows software to discover, identify, and configure hardware. Accessing this space involves multiple layers:

  • CPU MMIO access (ECAM)
  • Root Complex translation (iATU)
  • PCIe Transaction Layer (Config TLPs)

This article explains how these pieces fit together with a concrete example.

What is Config Space

Every PCIe device implements a Configuration Space—a standardized register layout used to describe device capabilities and control its behavior.

  • Minimum size: 256 bytes
  • PCIe Extended Configuration Space: up to 4 KB per function

The Linux PCI subsystem uses this space to:

  • Discover devices (by reading Vendor ID / Device ID)
  • Determine resource requirements (by probing BARs)
  • Configure devices (by programming BARs and control registers)

Configuration space is accessed by issuing Configuration Read/Write TLPs on the PCIe link. From the CPU perspective, these accesses are initiated as MMIO transactions, which the Root Complex translates into PCIe TLPs.

For Coniguration Space layout, refer to PCIe Overview

BDF Address Scheme

Each PCIe function is uniquely identified using the BDF (Bus:Device:Function) tuple:

BDF = Bus[7:0] : Device[4:0] : Function[2:0]
Enter fullscreen mode Exit fullscreen mode

Examples:

  • 00:00.0 → Root Complex integrated endpoint (typical)
  • 00:01.0 → Endpoint on the root bus

Field breakdown:

  • Bus: 8 bits → up to 256 buses
  • Device: 5 bits → up to 32 devices per bus
  • Function: 3 bits → up to 8 functions per device

Enhanced Configuration Access Mechanism (ECAM)

ECAM provides a standardized way to access PCIe configuration space using CPU MMIO. It maps configuration space into a contiguous region of the CPU’s physical address space.

ECAM Address Formula

Physical Address = ECAM_BASE
                 + (Bus << 20)
                 + (Device << 15)
                 + (Function << 12)
                 + Register
Enter fullscreen mode Exit fullscreen mode

Field mapping:

  • Bus → bits [27:20]
  • Device → bits [19:15]
  • Function → bits [14:12]
  • Register offset → bits [11:0]

Each function occupies exactly 4 KB of address space.

ECAM Region Size

Maximum possible ECAM size:

256 buses × 32 devices × 8 functions × 4KB = 256 MB
Enter fullscreen mode Exit fullscreen mode

ECAM in Device Tree

pcie@10000 {
    reg = <0x10000000 0x1000>,        /* DBI registers */
          <0x20000000 0x10000000>,    /* ECAM window */
    reg-names = "dbi","config"
}
Enter fullscreen mode Exit fullscreen mode
  • DBI region → internal controller registers
  • ECAM region → CPU-visible configuration space window

Internal Address Translation Unit (iATU)

The iATU is a hardware block within the Root Complex responsible for translating CPU physical addresses into PCIe transaction attributes.

Role of iATU

When the CPU accesses an address within the ECAM window:

  • The transaction is routed to the Root Complex
  • iATU compares the address against configured regions
  • Based on the matched region, the controller generates a Configuration TLP

The mapping between ECAM address bits and BDF follows the ECAM specification, while the iATU region configuration determines:

  • Transaction type (Cfg0 / Cfg1 / Memory)
  • Target PCIe address space

iATU Regions

Outbound (CPU → PCIe):

  • Region 0 → Config Type-0 (same bus devices)
  • Region 1 → Config Type-1 (downstream buses via bridges)
  • Region 2 → Memory transactions (BAR access)

Inbound (PCIe → CPU):

  • Used for endpoint-initiated transactions (e.g., DMA writes)

Example iATU Programming (Config Type-0)

Region 0:
  LOWER_BASE_ADDR = 0x20000000
  UPPER_BASE_ADDR = 0x00000000
  LIMIT_ADDR      = 0x200FFFFF   (1 MB window for Bus 0)
  REGION_CTRL_1   = TYPE = CFG0
  REGION_CTRL_2   = ENABLE = 1
Enter fullscreen mode Exit fullscreen mode
  • 1 MB corresponds to Bus 0 ECAM space:

    • 32 devices × 8 functions × 4KB

Example: Config Read Transaction

Read Vendor ID (offset 0x00) from device: 00:01.0

Step 1: CPU Issues MMIO Read

ECAM address = 0x20000000
             + (0 << 20)
             + (1 << 15)
             + (0 << 12)
             + 0x000

             = 0x20008000
Enter fullscreen mode Exit fullscreen mode

Step 2: Address Hits Root Complex

  • AXI interconnect routes the access to RC
  • iATU checks region match:
0x20000000 ≤ 0x20008000 ≤ 0x200FFFFF → Match
Enter fullscreen mode Exit fullscreen mode

Step 3: ECAM Address Decoding

From address:

Bus        = bits [27:20] = 0
Device     = bits [19:15] = 1
Function   = bits [14:12] = 0
Register   = bits [11:0]  = 0x000
Enter fullscreen mode Exit fullscreen mode

Step 4: Transaction Layer Generates CfgRd0 TLP

CfgRd0 TLP Header (3 DW):

DW0

  • Fmt = 000 (3 DW, no data)
  • Type = 00100 (CfgRd0)
  • Length = 1 DW

DW1

  • Requester ID = 00:00.0 (Root Complex)
  • Last BE = 0000
  • First BE = 0011 (16-bit access → Vendor ID)

DW2

[31:24] Bus Number        = 0x00
[23:19] Device Number     = 0x01
[18:16] Function Number   = 0x00
[15:12] Register Number   = 0x0
[11:2]  Register Number   = 0x00
[1:0]   Reserved          = 00
Enter fullscreen mode Exit fullscreen mode
  • Register offset = 0x00
  • Extended register field = 0x0 (within first 256 bytes)

End-to-End Flow

CPU MMIO Read (ECAM)
        ↓
AXI Interconnect
        ↓
Root Complex (Host Bridge)
        ↓
iATU Region Match
        ↓
CfgRd0 TLP Generation
        ↓
PCIe Link
        ↓
Endpoint
Enter fullscreen mode Exit fullscreen mode

Top comments (0)