PCI: cadence: Add flags for disabling ASPM capability for broken Root Ports

Add flags for disabling the ASPM L0s/L1 capability for broken Root Ports
by clearing the corresponding bits in Link Capabilities Register through
the local management bus. This allows ASPM to be disabled on platforms
which don't support it.

Signed-off-by: Yao Zi <me@ziyao.cc>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Han Gao <gaohan@iscas.ac.cn>
Tested-by: Chen Wang <unicorn_wang@outlook.com> # Pioneerbox
Reviewed-by: Chen Wang <unicorn_wang@outlook.com>
Link: https://patch.msgid.link/20260405154154.46829-2-me@ziyao.cc
This commit is contained in:
Yao Zi
2026-04-05 15:41:53 +00:00
committed by Bjorn Helgaas
parent 6de23f81a5
commit 5ccc76a87f
2 changed files with 26 additions and 0 deletions

View File

@@ -147,6 +147,13 @@ 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);
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);
return 0;
}

View File

@@ -115,6 +115,8 @@ struct cdns_pcie {
* @quirk_detect_quiet_flag: LTSSM Detect Quiet min delay set as quirk
* @ecam_supported: Whether the ECAM is supported
* @no_inbound_map: Whether inbound mapping is supported
* @quirk_broken_aspm_l0s: Disable ASPM L0s support as quirk
* @quirk_broken_aspm_l1: Disable ASPM L1 support as quirk
*/
struct cdns_pcie_rc {
struct cdns_pcie pcie;
@@ -127,6 +129,8 @@ struct cdns_pcie_rc {
unsigned int quirk_detect_quiet_flag:1;
unsigned int ecam_supported:1;
unsigned int no_inbound_map:1;
unsigned int quirk_broken_aspm_l0s:1;
unsigned int quirk_broken_aspm_l1:1;
};
/**
@@ -344,6 +348,21 @@ static inline u16 cdns_pcie_rp_readw(struct cdns_pcie *pcie, u32 reg)
return cdns_pcie_read_sz(addr, 0x2);
}
static inline void cdns_pcie_rp_writel(struct cdns_pcie *pcie,
u32 reg, u32 value)
{
void __iomem *addr = pcie->reg_base + CDNS_PCIE_RP_BASE + reg;
cdns_pcie_write_sz(addr, 0x4, value);
}
static inline u32 cdns_pcie_rp_readl(struct cdns_pcie *pcie, u32 reg)
{
void __iomem *addr = pcie->reg_base + CDNS_PCIE_RP_BASE + reg;
return cdns_pcie_read_sz(addr, 0x4);
}
static inline void cdns_pcie_hpa_rp_writeb(struct cdns_pcie *pcie,
u32 reg, u8 value)
{