pci: pci-uclass: Add support for Alternate-RoutingID capability

If ARI capability is found on device, use it to update next function
number in bus scan and also helps to skip unnecessary bdf scans.

Signed-off-by: Suneel Garapati <sgarapati@marvell.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 4635752..377806f 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -63,6 +63,15 @@
 	  if available on a PCI Physical Function device and probe for
 	  applicable drivers.
 
+config PCI_ARID
+        bool "Enable Alternate Routing-ID support for PCI"
+        depends on PCI || DM_PCI
+        default n
+        help
+          Say Y here if you want to enable Alternate Routing-ID capability
+          support on PCI devices. This helps to skip some devices in BDF
+          scan that are not present.
+
 config PCIE_ECAM_GENERIC
 	bool "Generic ECAM-based PCI host controller support"
 	default n
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 23135eb..fc60dfe 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -798,6 +798,7 @@
 	ulong header_type;
 	pci_dev_t bdf, end;
 	bool found_multi;
+	int ari_off;
 	int ret;
 
 	found_multi = false;
@@ -871,6 +872,31 @@
 		pplat->vendor = vendor;
 		pplat->device = device;
 		pplat->class = class;
+
+		if (IS_ENABLED(CONFIG_PCI_ARID)) {
+			ari_off = dm_pci_find_ext_capability(dev,
+							     PCI_EXT_CAP_ID_ARI);
+			if (ari_off) {
+				u16 ari_cap;
+
+				/*
+				 * Read Next Function number in ARI Cap
+				 * Register
+				 */
+				dm_pci_read_config16(dev, ari_off + 4,
+						     &ari_cap);
+				/*
+				 * Update next scan on this function number,
+				 * subtract 1 in BDF to satisfy loop increment.
+				 */
+				if (ari_cap & 0xff00) {
+					bdf = PCI_BDF(PCI_BUS(bdf),
+						      PCI_DEV(ari_cap),
+						      PCI_FUNC(ari_cap));
+					bdf = bdf - 0x100;
+				}
+			}
+		}
 	}
 
 	return 0;