We are using an i.MX6DL running kernel 5.10.235 and are seeing a PCIe Gen1 link-training issue. The logs indicate that link training never completes—the link continuously retrains. Debug0 register shows that link is not stable indicating that something is triggering a retrain.
Observed LTSSM transitions:
L0 → S_POLL_CONFIG → S_RCVRY_RCVRCFG → S_CFG_LINKWD_START → S_POLL_CONFIG
We also noticed that the LnkCap register value changes (every power cycle) even though both pci-imx6.c and pcie-designware.c explicitly configure the link for Gen1. What else could be modifying this register?
Examples:
Case 1: 0x1ffc07c = value 0x0011cc12
LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s/L1, Exit Latency L0s <1us, L1 <8us
LnkCtl2: Target Link Speed 2.5GT/s
Case 2: 0x1ffc07c = value 0x00100001
LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s/L1, Exit Latency L0s <1us, L1 unlimited
LnkCtl2: Target Link Speed 2.5GT/s
Additionally, disabling the scrambler appears to stabilize the link:
devmem2 0x1ffc710 w 0x00010122
Looking for info on:
1. What could trigger link retraining after initially reaching L0?
2. What other HW/SW part may modify LnkCap?
Attaching document for more details.
Hello,
1. Regarding what could trigger link retraining after reaching L0 state:
- Signal integrity issues on the PCIe lanes can cause link instability
- Power supply fluctuations or noise affecting the PCIe PHY
- Clock jitter or instability in the PCIe reference clock
- Hardware design issues related to PCIe trace impedance or length matching
- Software/driver bugs that may initiate unnecessary retraining
2. For the fluctuating LnkCap register values:
- The register can be modified by both hardware initialization sequences and software drivers
- In the i.MX6 PCIe implementation, both pci-imx6.c and pcie-designware.c attempt to configure link parameters
- Link capability negotiation occurs during training, and values may be adjusted based on what the endpoint device reports
Your observation that disabling the scrambler stabilizes the link (devmem2 0x1ffc710 w 0x00010122) suggests a potential signal integrity or clock issue. This is consistent with previous cases where PCIe link stability issues on i.MX6 platforms were resolved through hardware adjustments.
I recommend reviewing application note AN4784 "PCIe Certification Guide for i.MX 6Dual/6Quad and i.MX 6Solo/6DualLite" which contains detailed PCIe SERDES settings information specifically for the i.MX6DL platform. This document provides comprehensive PCIe certification guidance that can help resolve intermittent link training failures.
For your specific continuous retraining issue, consider:
- Verifying PCIe reference clock signal quality and jitter
- Checking trace length matching on your PCB design
- Confirming proper termination and impedance on PCIe lanes
- Examining power rail stability under load conditions
The LnkCap register modifications you're seeing could be related to hardware-level register access during initialization sequences, potentially influenced by variations in PHY calibration.
Regards
Adding some more details.
Based on the observations below, the Gen1 link is stable when the scrambler is disabled. Is there a way to force the host to train exclusively at Gen1, preventing it from attempting Gen2?
* LnkCap is 5GT/s
root# lspci -s 00:00.0 -vv |grep LnkCap
LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <1us, L1
root# devmem2 0x1ffc07c
/dev/mem opened.
Memory mapped at address 0xb6f5c000.
Read at address 0x01FFC07C (0xb6f5c07c): 0x0011CC12 <<< gen2
root# ltssm_debug.sh |grep curr
LTSSM current state | 0x7 | S_CFG_LINKWD_START
LTSSM current state | 0x11 | S_L0
LTSSM current state | 0x7 | S_CFG_LINKWD_START
LTSSM current state | 0xf | S_RCVRY_RCVRCFG
* Setting Lnkcap to gen1 but value is getting overwritten
root# devmem2 0x1ffc07c w 0x00100011
root# devmem2 0x1ffc07c
/dev/mem opened. Memory mapped at address 0xb6fb1000.
Read at address 0x01FFC07C (0xb6fb107c): 0x0011CC12
root# ltssm_debug.sh |grep curr
LTSSM current state | 0x7 | S_CFG_LINKWD_START
LTSSM current state | 0xf | S_RCVRY_RCVRCFG
LTSSM current state | 0x7 | S_CFG_LINKWD_START
* Disable scrambler
root# devmem2 0x1ffc710 w 0x00010122
root# devmem2 0x1ffc710
/dev/mem opened. Memory mapped at address 0xb6f66000.
Read at address 0x01FFC710 (0xb6f66710): 0x00010122
* LnkCap was set to Gen1 again, and the value remains stable.
root# devmem2 0x1ffc07c w 0x00100011
root# devmem2 0x1ffc07c
/dev/mem opened. Memory mapped at address 0xb6f0a000.
Read at address 0x01FFC07C (0xb6f0a07c): 0x00100011
* Gen1 changes reflected here
root# lspci -s 00:00.0 -vv |grep LnkCap
LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM not supported
root:~# ltssm_debug.sh |grep curr
LTSSM current state | 0x11 | S_L0
LTSSM current state | 0x11 | S_L0
Link stable.Thanks
Hello,
Thanks for providing the pointers.
However, if we are forcing the link speed to Gen1, in what scenarios can the hardware still advertise Link Capabilities as Gen2 and also enable ASPM-related options?
For example, we see:
LnkCap: Port #0, Speed 5GT/s, Width x1,
ASPM L0s L1, Exit Latency L0s <1us, L1 <8us
We also observe 5 GT/s and Autonomous Change TS1 in the training sequence.
We do not want the link to train at Gen2.
TS1/TS2 logs are attached.
Thanks