[PATCH v2 3/3] PCI: cadence: Use dynamic PCIe capability offset in host driver
From: Hans Zhang
Date: Sat May 09 2026 - 09:08:33 EST
The Cadence PCIe controller may place the PCI Express Capability
structure at different offsets depending on SoC integration. The
hardcoded CDNS_PCIE_RP_CAP_OFFSET (0xC0) is not universally valid.
Replace all uses of the fixed offset with the dynamically cached
pcie->pcie_cap obtained via cdns_pcie_get_pcie_cap(). This affects:
- Root Port training completion check
- Link retraining
- Root Port initialization (ASPM quirks)
Also remove the now-unused CDNS_PCIE_RP_CAP_OFFSET definition from
pcie-cadence-lga-regs.h.
This change ensures correct operation across different Cadence IP
generations (LGA and HPA) and SoC designs.
Signed-off-by: Hans Zhang <18255117159@xxxxxxx>
---
drivers/pci/controller/cadence/pcie-cadence-ep.c | 5 +++--
drivers/pci/controller/cadence/pcie-cadence-host-common.c | 4 ++--
drivers/pci/controller/cadence/pcie-cadence-host-hpa.c | 2 ++
drivers/pci/controller/cadence/pcie-cadence-host.c | 6 ++++--
drivers/pci/controller/cadence/pcie-cadence-lga-regs.h | 1 -
5 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 38a0157b60dc..eeee954f7dc7 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -571,9 +571,8 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
int max_epfs = sizeof(epc->function_num_map) * 8;
int ret, epf, last_fn;
u32 reg, value;
- u8 cap;
+ u8 cap = pcie->pcie_cap;
- cap = cdns_pcie_find_capability(pcie, PCI_CAP_ID_EXP);
/*
* BIT(0) is hardwired to 1, hence function 0 is always enabled
* and can't be disabled anyway.
@@ -690,6 +689,8 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
}
pcie->mem_res = res;
+ cdns_pcie_get_pcie_cap(pcie);
+
ep->max_regions = CDNS_PCIE_MAX_OB;
of_property_read_u32(np, "cdns,max-outbound-regions", &ep->max_regions);
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host-common.c b/drivers/pci/controller/cadence/pcie-cadence-host-common.c
index 2b0211870f02..26b248231558 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host-common.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host-common.c
@@ -26,7 +26,7 @@ EXPORT_SYMBOL_GPL(bar_max_size);
int cdns_pcie_host_training_complete(struct cdns_pcie *pcie)
{
- u32 pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET;
+ u32 pcie_cap_off = pcie->pcie_cap;
unsigned long end_jiffies;
u16 lnk_stat;
@@ -68,7 +68,7 @@ EXPORT_SYMBOL_GPL(cdns_pcie_host_wait_for_link);
int cdns_pcie_retrain(struct cdns_pcie *pcie,
cdns_pcie_linkup_func pcie_link_up)
{
- u32 lnk_cap_sls, pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET;
+ u32 lnk_cap_sls, pcie_cap_off = pcie->pcie_cap;
u16 lnk_stat, lnk_ctl;
int ret = 0;
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
index 8bf7cc106413..512e243df737 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host-hpa.c
@@ -355,6 +355,8 @@ int cdns_pcie_hpa_host_setup(struct cdns_pcie_rc *rc)
rc->cfg_res = res;
}
+ cdns_pcie_get_pcie_cap(pcie);
+
/* Put EROM Bar aperture to 0 */
cdns_pcie_hpa_writel(pcie, REG_BANK_IP_CFG_CTRL_REG, CDNS_PCIE_EROM, 0x0);
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index 873d496c440f..6f6d80840114 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -147,12 +147,12 @@ static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0);
cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
- value = cdns_pcie_rp_readl(pcie, CDNS_PCIE_RP_CAP_OFFSET + PCI_EXP_LNKCAP);
+ value = cdns_pcie_rp_readl(pcie, pcie->pcie_cap + PCI_EXP_LNKCAP);
if (rc->quirk_broken_aspm_l0s)
value &= ~PCI_EXP_LNKCAP_ASPM_L0S;
if (rc->quirk_broken_aspm_l1)
value &= ~PCI_EXP_LNKCAP_ASPM_L1;
- cdns_pcie_rp_writel(pcie, CDNS_PCIE_RP_CAP_OFFSET + PCI_EXP_LNKCAP, value);
+ cdns_pcie_rp_writel(pcie, pcie->pcie_cap + PCI_EXP_LNKCAP, value);
return 0;
}
@@ -410,6 +410,8 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
return PTR_ERR(rc->cfg_base);
rc->cfg_res = res;
+ cdns_pcie_get_pcie_cap(pcie);
+
ret = cdns_pcie_host_link_setup(rc);
if (ret)
return ret;
diff --git a/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h b/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h
index 857b2140c5d2..7b92812ed120 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h
+++ b/drivers/pci/controller/cadence/pcie-cadence-lga-regs.h
@@ -133,7 +133,6 @@
/* Root Port Registers (PCI configuration space for the root port function) */
#define CDNS_PCIE_RP_BASE 0x00200000
-#define CDNS_PCIE_RP_CAP_OFFSET 0xC0
/* Address Translation Registers */
#define CDNS_PCIE_AT_BASE 0x00400000
--
2.34.1