PCIe User Guide¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 01/04/2026 |
1. Overview¶
PCIe (Peripheral Component Interconnect Express) is a high-speed serial computer expansion bus standard used to connect various peripheral devices to computer systems. PCIe uses point-to-point serial connections and supports full-duplex communication through lanes. Each lane contains two pairs of differential signal lines for transmitting and receiving, which can operate at different rates independently.
The SGS PCIe controller complies with PCI Express base specifications and supports various link widths and rate configurations. The controller supports Root Complex (RC) and Endpoint (EP) modes, functioning as a root complex to connect downstream devices or as an endpoint device to connect to an upstream root complex. It supports multiple rate specifications including Gen1 and Gen2, providing high-performance data transfer capabilities.
2. Key Terms¶
-
Lane
The basic unit of a PCIe link, containing a pair of differential transmit signal lines and a pair of differential receive signal lines, supporting full-duplex communication. PCIe links can be configured as x1, x2, and other widths.
-
Root Complex (RC)
The core component in PCIe topology, connecting CPU and memory subsystems, responsible for initiating and receiving PCIe transactions. RC can connect multiple Switch and Endpoint devices.
-
Endpoint (EP)
The terminal device in PCIe topology, participating in PCIe transactions as a requester or completer. EP can be various peripherals such as network cards, storage controllers, graphics cards, etc.
-
Gen1/Gen2 (Generation)
Different rate specifications of PCIe. Gen1: 2.5GT/s, Gen2: 5GT/s. The theoretical bandwidth per lane increases with the rate.
-
TLP (Transaction Layer Packet)
The packet format used by the PCIe transaction layer to transmit information between requesters and completers. Includes Memory Read/Write, IO Read/Write, Configuration Read/Write, and other types.
-
BAR (Base Address Register)
Used to configure the memory or IO mapped addresses of PCIe devices. Through BAR, the CPU can access internal registers and memory space of PCIe devices.
-
MSI/MSI-X (Message Signaled Interrupts)
The interrupt mechanism used by PCIe devices, triggering interrupts by writing to specific memory addresses, replacing traditional pin-based interrupt methods. MSI-X supports more interrupt vectors.
-
LTSSM (Link Training and Status State Machine)
The training and management state machine of PCIe links, responsible for link initialization, rate negotiation, width negotiation, and fault recovery.
-
Completion Timeout
The timeout mechanism for PCIe transactions, triggered when the requester does not receive a completion packet within the specified time.
3. Feature Description¶
3.1 PCIe Resources¶
The MHERA PCIe controller provides 2 independent PCIe controllers (PCIe0 and PCIe1), each configurable as RC (Root Complex) or EP (Endpoint) mode.
The register address mapping for each PCIe controller is as follows (based on mhera.dtsi):
| Register Region | PCIe0 | PCIe1 | Description |
|---|---|---|---|
| DBI | 0x1F356000 (4KB) | 0x1F35a000 (4KB) | Data Bus Interface, configuration space |
| DBI2 | 0x1F357000 (512B) | 0x1F35b000 (512B) | DBI extension registers |
| ATU | 0x1F358000 (4KB) | 0x1F35c000 (4KB) | Address Translation Unit |
| CFG | 0x10000000 (4KB) | 0x40000000 (4KB) | Configuration space (RC mode) |
| Configuration Space | 0x10000000 (1GB) | 0x40000000 (1GB) | EP mode configuration space |
| MAC | 0x1F2C7800 (512B) | 0x1F2C7a00 (512B) | MAC registers |
| MAC2 | 0x1F2CD400 (512B) | 0x1F2CD600 (512B) | MAC extension registers |
| DMA | 0x1F359000 (4KB) | 0x1F35d000 (4KB) | DMA registers |
Note: The MHERA chip is configured with 2 PCIe controllers, both supporting x2 link width and Gen2 rate.
3.2 Feature Support¶
The following table shows the feature support of each PCIe controller
| Feature | RC Mode | EP Mode | Link Width | Max Rate | MSI | MSI-X |
|---|---|---|---|---|---|---|
| Support Status | Supported | Supported | x1, x2 | Gen2 (5GT/s) | Supported | Supported |
Link rate support is shown in the following table:
PCIe Generation |
Encoding | Raw Rate | Single Lane Bandwidth(x1) |
|---|---|---|---|
| Gen1 | 8b/10b | 2.5 GT/s | 250 MB/s |
| Gen2 | 8b/10b | 5.0 GT/s | 500 MB/s |
Link width configuration support is shown below:
Link Width |
Lane Count | Theoretical Bandwidth(Gen2) |
|---|---|---|
| x1 | 1 | 500 MB/s |
| x2 | 2 | 1.0 GB/s |
PCIe Topology:
PCIe topology adopts a tree hierarchy with Root Complex (RC) as the core, connecting multiple Endpoint devices through Switches. RC connects to CPU and memory subsystems, responsible for initiating and receiving PCIe transactions.
3.3 Considerations¶
-
Differential Signal Routing
PCIe uses differential signal pairs, requiring strict control of impedance matching (typically 100Ω differential impedance), and the two lines of the same differential pair need equal length and equal spacing routing.
-
Interrupt Configuration
MSI-X interrupts support more interrupt vectors than MSI interrupts, so it is recommended to prioritize MSI-X in high-performance scenarios.
3.4 Bandwidth Calculation¶
The effective bandwidth of PCIe depends on link rate, link width, and coding efficiency. The theoretical bandwidth calculation formula is as follows:
Theoretical Bandwidth = Link Rate × Link Width × Coding Efficiency
For Gen2 x2 link:
- Raw Rate: 5 GT/s
- Link Width: 2 Lanes
- Coding Efficiency: 8/10 = 80%
- Theoretical Bandwidth: 5 GT/s × 2 × 0.8 = 8.0 Gb/s ≈ 1.0 GB/s
Link Rate Configuration
The link rate can be configured through the max-link-speed property in the device tree (DTS), and can also be viewed and adjusted at runtime using PCIe tools.
View current link rate:
lspci -vv -s <device_id> | grep LnkCap
4. Hardware Connection¶
-
PCIe connections use high-speed differential signal pairs. Each lane contains a pair of transmit differential lines (TXP/TXN) and a pair of receive differential lines (RXP/RXN). Transmission and reception achieve full-duplex communication through independent differential pairs.
-
PCIe link width can be configured as x1, x2, etc. Different widths correspond to different numbers of differential pairs. For example, x2 link requires 2 pairs of transmit differential lines and 2 pairs of receive differential lines.
-
The PCIe hardware configuration of the MHERA chip is as follows:
PCIe0 Configuration:
- Link Width: x2
- Supported Rate: Gen1, Gen2
- Differential Signal Pairs: PCIe0_TX0_P/N, PCIe0_TX1_P/N, PCIe0_RX0_P/N, PCIe0_RX1_P/N
PCIe1 Configuration:
- Link Width: x2
- Supported Rate: Gen1, Gen2
- Differential Signal Pairs: PCIe1_TX0_P/N, PCIe1_TX1_P/N, PCIe1_RX0_P/N, PCIe1_RX1_P/N
PCIe Connection Description: PCIe implements point-to-point serial connections through high-speed differential signal pairs. Each lane contains a pair of transmit differential lines (TXP/TXN) and a pair of receive differential lines (RXP/RXN), supporting full-duplex communication. Differential signals require strict control of impedance matching (100Ω) and equal-length routing.
5. Kernel Usage Guide¶
5.1 Kernel Config Configuration¶
When compiling the Kernel, you need to enable PCIe-related configurations through menuconfig. The method to enter the kernel configuration interface:
make menuconfig
Then follow the path below to enable PCIe drivers:
Device Drivers --->
Sgs SoC platform drivers --->
Sgs PCIe Support --->
[*] Sgs PCIe Controller - RC mode # PCIe RC mode support
[*] Sgs PCIe Controller - EP mode # PCIe EP mode support
[*] Sgs PCIe HOTPLUG # PCIe hotplug support
Sgs PCIe Rpmsg-lite ---> # Rpmsg-lite communication support (optional)
Sgs PCIe Verify ---> # PCIe verification function (optional)
Configuration Item Description:
- Sgs PCIe Controller - RC mode: Enable PCIe Root Complex mode, allowing the chip to connect downstream PCIe devices as a root complex
- Sgs PCIe Controller - EP mode: Enable PCIe Endpoint mode, allowing the chip to connect to an upstream Root Complex as an endpoint device
- Sgs PCIe HOTPLUG: Enable PCIe hotplug function, supporting dynamic addition/removal of PCIe devices at runtime
- Sgs PCIe Rpmsg-lite: Communication protocol based on RPMsg for inter-device communication over PCIe (optional feature)
- Sgs PCIe Verify: PCIe verification function for debugging and testing (optional feature)
Note: The above configuration items are enabled in the default defconfig (RC, EP, and HOTPLUG). If modifications are needed, follow the above path for configuration.
After configuration is complete, save and recompile the kernel:
make -j$(nproc)
5.2 DTS Definition¶
In mhera.dtsi, the pcie0 and pcie1 node sections are as follows:
pcie0: pcie@1F356000 {
compatible = "sgs,dw-pcie-earlyparam"; /* [rc] "sgs,dw-pcie" [ep] "sgs,dw-pcie-ep" [bootargs] "sgs,dw-pcie-earlyparam" */
reg = <0x0 0x1f356000 0x1000>, /* 4K DBI */
<0x0 0x1f357000 0x200>, /* DBI2 */
<0x0 0x1f358000 0x1000>, /* atu */
<0x1 0x00000000 0x1000>, /* [only rc] 4K CFG */
<0x1 0x00000000 0x40000000>, /* [only ep] Configuration space */
<0x0 0x1f2c7800 0x200>, /* mac */
<0x0 0x1f2cd400 0x200>, /* mac2 */
<0x0 0x1f359000 0x1000>; /* dma */
reg-names = "dbi", "dbi2", "atu", "config", "addr_space", "mac", "mac2", "dma";
portid = <0>;
#address-cells = <3>;
#size-cells = <2>;
/* properties for RC */
device_type = "pci";
bus-range = <0x00 0xff>;
/* ranges: [flags] [pci addr] [cpu addr] [size] */
ranges = <0x81000000 0 0x00001000 0x1 0x00001000 0 0x0000f000 /* downstream I/O */
0x82000000 0 0x00010000 0x1 0x00010000 0 0x3fff0000>;/* non-prefetchable memory */
linux,pci-domain = <0>;
num-lanes = <2>;
max-link-speed = <2>;
interrupts = <GIC_SPI INT_IRQ_PCIE0_OUT IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE0_OUT IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE0_OUT IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE0_SUP_PHY_P0 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE0_SUP_PHY_P1 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi", "mac", "hdma", "sup_phy0", "sup_phy1";
#interrupt-cells = <1>;
dma_read_channel_number=<8>;
dma_write_channel_number=<8>;
clocks = <&CLK_pcie0>;
clk_source = <0>; /*0: internal, 1:internal_2, 2: external, 3: wire */
status = "okay";
};
pcie1: pcie@1F35a000 {
compatible = "sgs,dw-pcie-earlyparam"; /* [rc] "sgs,dw-pcie" [ep] "sgs,dw-pcie-ep" [bootargs] "sgs,dw-pcie-earlyparam" */
reg = <0x0 0x1f35a000 0x1000>, /* DBI */
<0x0 0x1f35b000 0x200>, /* DBI2 */
<0x0 0x1f35c000 0x1000>, /* atu */
<0x1 0x40000000 0x1000>, /* [only rc] 4K CFG */
<0x1 0x40000000 0x40000000>, /* [only ep] Configuration space */
<0x0 0x1f2c7a00 0x200>, /* mac */
<0x0 0x1f2cd600 0x200>, /* mac2 */
<0x0 0x1f35d000 0x1000>; /* dma */
reg-names = "dbi", "dbi2", "atu", "config", "addr_space", "mac", "mac2", "dma";
portid = <1>;
#address-cells = <3>;
#size-cells = <2>;
/* properties for RC */
device_type = "pci";
bus-range = <0x00 0xff>;
/* ranges: [flags] [pci addr] [cpu addr] [size] */
ranges = <0x81000000 0 0x00001000 0x1 0x40000000 0 0x00020000 /* downstream I/O */
0x82000000 0 0x00100000 0x1 0x40100000 0 0x3ff00000>; /* non-prefetchable memory */
linux,pci-domain = <1>;
num-lanes = <2>;
max-link-speed = <2>;
interrupts = <GIC_SPI INT_IRQ_PCIE1_OUT IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE1_OUT IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE1_OUT IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE1_SUP_PHY_P0 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI INT_IRQ_PCIE1_SUP_PHY_P1 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi", "mac", "hdma", "sup_phy0", "sup_phy1";
#interrupt-cells = <1>;
dma_read_channel_number=<8>;
dma_write_channel_number=<8>;
clocks = <&CLK_pcie1>;
clk_source = <0>; /*0: internal, 1:internal_2, 2: external, 3: wire */
status = "okay";
};
In the above sections, the address space of the PCIe controller includes DBI, DBI2, ATU, configuration space, MAC, MAC2, and DMA register space.
The description of the properties in the node is as follows:
| Property | Description |
Remarks |
|---|---|---|
| compatible | Used for driver matching | "sgs,dw-pcie" (RC), "sgs,dw-pcie-ep" (EP), "sgs,dw-pcie-earlyparam" |
| reg | Register address and size | Including DBI, DBI2, ATU, CFG, configuration space, MAC, MAC2, DMA |
| reg-names | Register region names | "dbi", "dbi2", "atu", "config", "addr_space", "mac", "mac2", "dma" |
| portid | Port ID | 0: pcie0, 1: pcie1 |
| #address-cells | Address cells | Do not modify |
| #size-cells | Size cells | Do not modify |
| device_type | Device type | Must be "pci" |
| bus-range | PCIe bus number range | Configure according to actual settings |
| ranges | Address mapping range | Configure according to actual settings |
| linux,pci-domain | PCIe domain number | Distinguish different PCIe controllers |
| num-lanes | Link width | 1, 2 |
| max-link-speed | Maximum link rate | 1=Gen1, 2=Gen2 |
| interrupts | Interrupt number | Including msi, mac, hdma, sup_phy0, sup_phy1 |
| interrupt-names | Interrupt names | "msi", "mac", "hdma", "sup_phy0", "sup_phy1" |
| dma_read_channel_number | DMA read channel count | Default 8 |
| dma_write_channel_number | DMA write channel count | Default 8 |
| clocks | Clock node | Do not modify |
| clk_source | Clock source selection | 0: internal, 1: internal_2, 2: external, 3: wire |
| status | Node enable | "okay": enable "disabled": disable |
5.3 Module Usage Introduction¶
The basic workflow for user-space applications is:
-
Scan for PCIe devices
-
Access PCIe device configuration space
-
Map PCIe device BAR space for read/write operations
lspci Tool Description:
The lspci command included in the system is a simplified version with relatively limited functionality. If you need the complete version of the lspci tool (with more features and detailed options), please download it from the pciutils official website:
- Official Website: https://pci-ids.ucw.cz/git/
- Download Path: git://git.kernel.org/pub/scm/utils/pciutils/pciutils.git
- Compilation Method:
make make install
The complete lspci tool provides more detailed device information parsing, more query options, and better compatibility.
Example: Using lspci tool to view PCIe device information
/ # lspci -vv
00:00.0 PCI bridge: SGS Technologies PCIe Controller (rev 01)
Control: I/O+ Mem+ BusMaster+
Status: Cap+ 66MHz- UDF- FastB2B- OrdErr-
LnkCap: Port #0, Speed 5GT/s, Width x2
LnkSta: Speed 5GT/s, Width x2
/ # lspci -s 00:01.0 -vv
00:01.0 Ethernet controller: Ethernet Controller X
Region 0: Memory at 0x40000000 (32-bit, prefetchable)
Region 2: Memory at 0x40100000 (32-bit, non-prefetchable)
5.4 Sample code¶
This demo provides a reference for accessing PCIe device configuration space and BAR space, and can be modified according to requirements.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#define PCI_CONFIG_SPACE_SIZE 256
#define PCI_BAR0_SIZE 0x10000
/* Read PCIe configuration space */
int pci_read_config(int fd, int offset, unsigned char *buf, int len)
{
if (lseek(fd, offset, SEEK_SET) == -1) {
perror("lseek");
return -1;
}
if (read(fd, buf, len) != len) {
perror("read config");
return -1;
}
return 0;
}
/* Write to PCIe configuration space */
int pci_write_config(int fd, int offset, unsigned char *buf, int len)
{
if (lseek(fd, offset, SEEK_SET) == -1) {
perror("lseek");
return -1;
}
if (write(fd, buf, len) != len) {
perror("write config");
return -1;
}
return 0;
}
/* Map BAR space and access */
void* pci_map_bar(int bar_fd, size_t size)
{
void *mapped_addr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED, bar_fd, 0);
if (mapped_addr == MAP_FAILED) {
perror("mmap");
return NULL;
}
return mapped_addr;
}
int main(int argc, char **argv)
{
int config_fd = -1;
int bar_fd = -1;
unsigned char config_buf[PCI_CONFIG_SPACE_SIZE];
void *bar_base = NULL;
char device_path[256];
unsigned int vendor_id, device_id;
/* Open PCIe device configuration space */
snprintf(device_path, sizeof(device_path),
"/sys/bus/pci/devices/0000:00:01.0/config");
config_fd = open(device_path, O_RDWR);
if (config_fd < 0) {
perror("Failed to open PCI device config");
return -1;
}
/* Read Vendor ID and Device ID */
pci_read_config(config_fd, 0x00, config_buf, 4);
vendor_id = config_buf[1] << 8 | config_buf[0];
device_id = config_buf[3] << 8 | config_buf[2];
printf("PCIe Device Information:\n");
printf(" Vendor ID: 0x%04x\n", vendor_id);
printf(" Device ID: 0x%04x\n", device_id);
/* Read Class Code */
pci_read_config(config_fd, 0x08, config_buf, 4);
printf(" Class Code: 0x%02x%02x%02x\n",
config_buf[2], config_buf[1], config_buf[0]);
/* Read BAR0 address */
pci_read_config(config_fd, 0x10, config_buf, 4);
unsigned int bar0 = config_buf[3] << 24 | config_buf[2] << 16 |
config_buf[1] << 8 | config_buf[0];
printf(" BAR0: 0x%08x\n", bar0);
/* Open BAR0 resource file for memory mapping */
snprintf(device_path, sizeof(device_path),
"/sys/bus/pci/devices/0000:00:01.0/resource0");
bar_fd = open(device_path, O_RDWR | O_SYNC);
if (bar_fd < 0) {
perror("Failed to open BAR0 resource");
goto out;
}
/* Map BAR space */
bar_base = pci_map_bar(bar_fd, PCI_BAR0_SIZE);
if (!bar_base) {
fprintf(stderr, "Failed to map BAR0\n");
goto out;
}
printf("\nAccessing BAR0 registers:\n");
printf(" BAR0 mapped at: %p\n", bar_base);
/* Read register at BAR0 offset 0x00 */
unsigned int reg_value = *(unsigned int*)(bar_base + 0x00);
printf(" Register at 0x00: 0x%08x\n", reg_value);
out:
if (bar_base && bar_base != MAP_FAILED) {
munmap(bar_base, PCI_BAR0_SIZE);
}
if (bar_fd >= 0) {
close(bar_fd);
}
if (config_fd >= 0) {
close(config_fd);
}
return 0;
}
6. FAQ¶
Q1: PCIe Link Training Failure
-
Reproduce the failure where PCIe link cannot be established normally, dmesg shows link training failure:
sgs-pcie 1f35a000.pcie: PCIe1: mode=RC, clk_source=internal, ssc_enable=0 sgs-pcie 1f35a000.pcie: PCIe1: lanes=2, mac=ffffffc008e25a00, mac2=ffffffc008e2d600, dbi=ffffffc008e35000 sgs-pcie 1f35a000.pcie: sgs_pcie_phy_init232 sgs-pcie 1f35a000.pcie: host bridge /soc/pcie@1F35a000 ranges: sgs-pcie 1f35a000.pcie: IO 0x0140000000..0x014001ffff -> 0x0000001000 sgs-pcie 1f35a000.pcie: MEM 0x0140100000..0x017fffffff -> 0x0000100000 sgs-pcie 1f35a000.pcie: iATU unroll: enabled sgs-pcie 1f35a000.pcie: iATU regions: 8 ob, 8 ib, align 4K, limit 4G sgs-pcie 1f35a000.pcie: Phy link never came up -
Root Cause Analysis
Common causes of PCIe link training failure include:
-
Hardware connection issues: differential signal line impedance mismatch, incorrect wire sequence, or poor contact;
-
Clock configuration issues: incorrect reference clock frequency or poor clock signal quality;
-
Device tree configuration issues: max-link-speed and num-lanes configuration do not match actual hardware.
-
-
Solutions
Check hardware connections and device tree configuration to ensure:
-
Use an oscilloscope or logic analyzer to check differential signal quality;
-
Check max-link-speed and num-lanes configuration in device tree;
-
Try reducing link rate or link width for testing.
-
Q2: PCIe Device Cannot Enumerate
-
PCIe device is not recognized by the system after startup, lspci command cannot see the device:
/ # lspci / # -
Root Cause Analysis
Possible reasons why PCIe device cannot enumerate:
-
PCIe controller driver is not loaded correctly;
-
Device tree configuration error, PCIe controller is not enabled;
-
PERST# signal of PCIe device is not reset correctly;
-
PCIe device power supply is not working properly.
You can check the initialization status of the PCIe controller through dmesg. Use the
dmesg | grep pcicommand to view initialization logs and error information of the PCIe controller. -
-
Solutions
-
Check whether the PCIe controller driver is loaded correctly;
-
Ensure the status property of the PCIe controller in device tree is "ok";
-
Check the timing of PERST# signal in hardware design to ensure it meets PCIe specification requirements;
-
Use a multimeter to check whether the power supply voltage of the PCIe device is normal.
-
Q3: PCIe Bandwidth Below Expected
-
PCIe link is established, but actual bandwidth is far below theoretical value:
/ # lspci -vv -s 00:01.0 | grep LnkSta LnkSta: Speed 2.5GT/s, Width x1
Although configured as Gen2 x2, it actually works at Gen1 x1.
-
Description
PCIe link rate and width will be automatically negotiated. The actual rate depends on:
-
The maximum rate supported by both devices;
-
Whether signal quality meets high-speed transmission requirements;
-
Whether errors are detected during link training.
-
-
Solutions
-
Check device tree configuration to confirm max-link-speed and num-lanes are set correctly;
-
Check hardware design to ensure impedance matching and routing quality of differential signal lines;
-
Check whether the peer device supports the configured rate and width;
-
Check dmesg logs to confirm error messages during link training.
-