[PATCH 1/2] PCI: cadence: Advertise ARI Forwarding Supported

From: Achal Verma
Date: Sat Aug 12 2023 - 16:45:26 EST


J7 PCIe Root Complex has ARI Forwarding Support (advertised by
PCI_EXP_DEVCAP2_ARI bit) which means support for forwarding of TLPs
addressed to functions with function number greater than 7 but for some
PCIe instances on J7, PCI_EXP_DEVCAP2_ARI bit is cleared which prevents
accessing functions with function number > 7.

Setting the PCI_EXP_DEVCAP2_ARI explicitly, resolves the issue.

Signed-off-by: Achal Verma <a-verma1@xxxxxx>
---
drivers/pci/controller/cadence/pci-j721e.c | 4 ++++
drivers/pci/controller/cadence/pcie-cadence-host.c | 7 +++++++
drivers/pci/controller/cadence/pcie-cadence.h | 12 ++++++++++++
3 files changed, 23 insertions(+)

diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
index 2c3b3af59271..7e94eb94f29c 100644
--- a/drivers/pci/controller/cadence/pci-j721e.c
+++ b/drivers/pci/controller/cadence/pci-j721e.c
@@ -73,6 +73,7 @@ struct j721e_pcie_data {
unsigned int quirk_disable_flr:1;
u32 linkdown_irq_regfield;
unsigned int byte_access_allowed:1;
+ unsigned int set_afs_bit:1;
};

static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
@@ -292,6 +293,7 @@ static const struct j721e_pcie_data j721e_pcie_rc_data = {
.quirk_retrain_flag = true,
.byte_access_allowed = false,
.linkdown_irq_regfield = LINK_DOWN,
+ .set_afs_bit = true,
};

static const struct j721e_pcie_data j721e_pcie_ep_data = {
@@ -304,6 +306,7 @@ static const struct j721e_pcie_data j7200_pcie_rc_data = {
.quirk_detect_quiet_flag = true,
.linkdown_irq_regfield = J7200_LINK_DOWN,
.byte_access_allowed = true,
+ .set_afs_bit = true,
};

static const struct j721e_pcie_data j7200_pcie_ep_data = {
@@ -393,6 +396,7 @@ static int j721e_pcie_probe(struct platform_device *pdev)
rc = pci_host_bridge_priv(bridge);
rc->quirk_retrain_flag = data->quirk_retrain_flag;
rc->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
+ rc->set_afs_bit = data->set_afs_bit;

cdns_pcie = &rc->pcie;
cdns_pcie->dev = dev;
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
index 5b14f7ee3c79..fc696d94f7a2 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
@@ -507,6 +507,7 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
struct cdns_pcie *pcie;
struct resource *res;
int ret;
+ u32 pcie_cap2;

bridge = pci_host_bridge_from_priv(rc);
if (!bridge)
@@ -536,6 +537,12 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
if (rc->quirk_detect_quiet_flag)
cdns_pcie_detect_quiet_min_delay_set(&rc->pcie);

+ if (rc->set_afs_bit) {
+ pcie_cap2 = cdns_pcie_rp_readl(pcie, CDNS_PCIE_RP_CAP_OFFSET + PCI_EXP_DEVCAP2);
+ pcie_cap2 |= PCI_EXP_DEVCAP2_ARI;
+ cdns_pcie_rp_writel(pcie, CDNS_PCIE_RP_CAP_OFFSET + PCI_EXP_DEVCAP2, pcie_cap2);
+ }
+
cdns_pcie_host_enable_ptm_response(pcie);

ret = cdns_pcie_start_link(pcie);
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
index 190786e47df9..7a5d05f3febc 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
@@ -329,6 +329,7 @@ struct cdns_pcie_rc {
bool avail_ib_bar[CDNS_PCIE_RP_MAX_IB];
unsigned int quirk_retrain_flag:1;
unsigned int quirk_detect_quiet_flag:1;
+ unsigned int set_afs_bit:1;
};

/**
@@ -457,6 +458,17 @@ 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)
+{
+ writel(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
+}
+
+static inline u32 cdns_pcie_rp_readl(struct cdns_pcie *pcie, u32 reg)
+{
+ return readl(pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
+}
+
/* Endpoint Function register access */
static inline void cdns_pcie_ep_fn_writeb(struct cdns_pcie *pcie, u8 fn,
u32 reg, u8 value)
--
2.25.1