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

Message ID 20230812204455.479510-2-a-verma1@ti.com
State New
Headers
Series Advertise ARI related capabilities. |

Commit Message

Achal Verma Aug. 12, 2023, 8:44 p.m. UTC
  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@ti.com>
---
 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(+)
  

Patch

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)