fix(lib/pcie): import pcie enumeration helpers from rmm-acs

Import PCIe enumeration helpers from rmm-acs[1] at tag v1.0_REL0_12.24.

This patch adds the missing device enumeration logic added as part of
the initial commit.

This change is verified with FVP default PCI topology. The helper
pcie_init() might need some enhancements for other platforms with
different PCI topology.

[1] https://github.com/ARM-software/cca-rmm-acs

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I46724c458fe0071272fc7bca73d51e27181bb1b4
diff --git a/include/lib/pcie/pcie.h b/include/lib/pcie/pcie.h
index d7188a0..7dd165c 100644
--- a/include/lib/pcie/pcie.h
+++ b/include/lib/pcie/pcie.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -100,7 +100,7 @@
 #define CC_BASE_SHIFT	24
 
 void pcie_init(void);
-void pcie_create_info_table(void);
+
 pcie_device_bdf_table_t *pcie_get_bdf_table(void);
 uint32_t pcie_find_capability(uint32_t bdf, uint32_t cid_type, uint32_t cid,
 				uint32_t *cid_offset);
diff --git a/include/plat/common/plat_pcie_enum.h b/include/plat/common/plat_pcie_enum.h
new file mode 100644
index 0000000..667fe05
--- /dev/null
+++ b/include/plat/common/plat_pcie_enum.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2025, Arm Limited or its affiliates. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_PCIE_ENUM_H__
+#define __PLAT_PCIE_ENUM_H__
+
+#include <stdio.h>
+#include <stdint.h>
+
+/* Header Offset and Type */
+#define HEADER_OFFSET		0xC
+#define TYPE0_HEADER		0
+#define TYPE1_HEADER		1
+
+#define TYPE01_RIDR		0x8
+
+#define DEVICE_ID_OFFSET	16
+
+/* Initial BUS definitions */
+#define PRI_BUS			0
+#define SEC_BUS			1
+#define BUS_NUM_REG_OFFSET	0x18
+
+/* BAR offset */
+#define BAR0_OFFSET		0x10
+#define TYPE1_BAR_MAX_OFF	0x14
+#define TYPE0_BAR_MAX_OFF	0x24
+
+#define BAR_NON_PRE_MEM		0
+#define BAR_PRE_MEM		0x1
+
+#define MEM_BASE32_LIM_MASK	0xFFF00000
+#define MEM_BASE64_LIM_MASK	0xFFFFFFFFFFF00000
+#define NON_PRE_FET_OFFSET	0x20
+#define PRE_FET_OFFSET		0x24
+#define BAR_INCREMENT		0x100000
+
+#define PRI_BUS_CLEAR_MASK	0xFFFFFF00
+
+#define TYPE0_MAX_BARS		6
+#define TYPE1_MAX_BARS		2
+
+/* BAR register masks */
+#define BAR_MIT_MASK		0x1
+#define BAR_MDT_MASK		0x3
+#define BAR_MT_MASK		0x1
+#define BAR_BASE_MASK		0xfffffff
+
+/* BAR register shifts */
+#define BAR_MIT_SHIFT		0
+#define BAR_MDT_SHIFT		1
+#define BAR_MT_SHIFT		3
+#define BAR_BASE_SHIFT		4
+
+/* TYPE 0/1 Cmn Cfg reg offsets and mask*/
+#define TYPE01_CPR		0x34
+#define TYPE01_CPR_MASK		0xff
+#define COMMAND_REG_OFFSET	0x04
+#define REG_ACC_DATA		0x7
+
+#define BAR_MASK		0xFFFFFFF0
+
+#define PCIE_HEADER_TYPE(header_value)		((header_value >> 16) & 0x3)
+#define BUS_NUM_REG_CFG(sub_bus, sec_bus, pri_bus)	(sub_bus << 16 | sec_bus << 8 | bus)
+
+#define BAR_REG(bar_reg_value)		((bar_reg_value >> 2) & 0x1)
+#define BAR_MEM(bar_reg_value)		((bar_reg_value & 0xF) >> 3)
+#define REG_MASK_SHIFT(bar_value)	((bar_value & MEM_BASE32_LIM_MASK) >> 16)
+
+#endif /* __PLAT_PCIE_ENUM_H__ */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index e5032fa..077ccb3 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -208,6 +208,11 @@
  */
 const struct pcie_info_table *plat_pcie_get_info_table(void);
 
+/* Retrieve platform PCIe bar config values */
+int plat_pcie_get_bar_config(uint64_t *bar64_val, uint64_t *rp_bar64_val,
+			     uint32_t *bar32np_val, uint32_t *bar32p_val,
+			     uint32_t *rp_bar32_val);
+
 /*
  * This function provides an address that is recognized as invalid for use
  * as an entry point in the CPU_ON and CPU_SUSPEND calls on this platform.
diff --git a/lib/pcie/pcie.c b/lib/pcie/pcie.c
index 8de2825..ea187a6 100644
--- a/lib/pcie/pcie.c
+++ b/lib/pcie/pcie.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,16 +14,35 @@
 #include <pcie_doe.h>
 #include <pcie_spec.h>
 #include <platform.h>
+#include <plat_pcie_enum.h>
 #include <tftf_lib.h>
 
 #define PCIE_DEBUG	VERBOSE
 
 const struct pcie_info_table *g_pcie_info_table;
-pcie_device_bdf_table_t *g_pcie_bdf_table;
+static pcie_device_bdf_table_t *g_pcie_bdf_table;
 
-pcie_device_bdf_table_t pcie_bdf_table[PCIE_DEVICE_BDF_TABLE_SZ];
+static pcie_device_bdf_table_t pcie_bdf_table[PCIE_DEVICE_BDF_TABLE_SZ];
 
-uintptr_t pcie_cfg_addr(uint32_t bdf)
+static uint32_t g_pcie_index;
+static uint32_t g_enumerate;
+
+/* 64-bit address initialisation */
+static uint64_t g_bar64_p_start;
+static uint64_t g_rp_bar64_value;
+static uint64_t g_bar64_p_max;
+static uint32_t g_64_bus, g_bar64_size;
+
+/* 32-bit address initialisation */
+static uint32_t g_bar32_np_start;
+static uint32_t g_bar32_p_start;
+static uint32_t g_rp_bar32_value;
+static uint32_t g_bar32_np_max;
+static uint32_t g_bar32_p_max;
+static uint32_t g_np_bar_size, g_p_bar_size;
+static uint32_t g_np_bus, g_p_bus;
+
+static uintptr_t pcie_cfg_addr(uint32_t bdf)
 {
 	uint32_t bus = PCIE_EXTRACT_BDF_BUS(bdf);
 	uint32_t dev = PCIE_EXTRACT_BDF_DEV(bdf);
@@ -102,7 +121,7 @@
  * @param   bdf - Function's Segment/Bus/Dev/Func in PCIE_CREATE_BDF format
  * @return  false If not a Host Bridge, true If it's a Host Bridge.
  */
-bool pcie_is_host_bridge(uint32_t bdf)
+static bool pcie_is_host_bridge(uint32_t bdf)
 {
 	uint32_t reg_value = pcie_read_cfg(bdf, TYPE01_RIDR);
 
@@ -168,7 +187,7 @@
  * @param  bdf
  * @return true if bdf is valid else false
  */
-bool pcie_check_device_valid(uint32_t bdf)
+static bool pcie_check_device_valid(uint32_t bdf)
 {
 	(void) bdf;
 	/*
@@ -185,7 +204,7 @@
  * @return Returns TRUE if the Function is on-chip peripheral, FALSE if it is
  *	   not an on-chip peripheral
  */
-bool pcie_is_onchip_peripheral(uint32_t bdf)
+static bool pcie_is_onchip_peripheral(uint32_t bdf)
 {
 	(void)bdf;
 	return false;
@@ -200,7 +219,7 @@
  *		   (1 << 0b1100) for iEP_EP, (1 << 0b1011) for iEP_RP,
  *		   (1 << PCIECR[7:4]) for any other device type.
  */
-uint32_t pcie_device_port_type(uint32_t bdf)
+static uint32_t pcie_device_port_type(uint32_t bdf)
 {
 	uint32_t pciecs_base, reg_value, dp_type;
 
@@ -236,7 +255,7 @@
  * @param  usrp_bdf  - Upstream Rootport bdf in PCIE_CREATE_BDF format
  * @return 0 for success, 1 for failure.
  */
-uint32_t pcie_get_rootport(uint32_t bdf, uint32_t *rp_bdf)
+static uint32_t pcie_get_rootport(uint32_t bdf, uint32_t *rp_bdf)
 {
 	uint32_t seg_num, sec_bus, sub_bus;
 	uint32_t reg_value, dp_type, index = 0;
@@ -334,7 +353,7 @@
  *
  * @return  None
  */
-void pcie_create_device_bdf_table(void)
+static void pcie_create_device_bdf_table(void)
 {
 	uint32_t seg_num, start_bus, end_bus;
 	uint32_t bus_index, dev_index, func_index, ecam_index;
@@ -404,7 +423,7 @@
  * @return TYPE0_HEADER for functions with Type 0 config space header,
  *         TYPE1_HEADER for functions with Type 1 config space header,
  */
-uint32_t pcie_function_header_type(uint32_t bdf)
+static uint32_t pcie_function_header_type(uint32_t bdf)
 {
 	/* Read four bytes of config space starting from cache line size register */
 	uint32_t reg_value = pcie_read_cfg(bdf, TYPE01_CLSR);
@@ -422,7 +441,7 @@
  * @param  bdf   - Segment/Bus/Dev/Func in PCIE_CREATE_BDF format
  * @return ECAM address if success, else NULL address
  */
-uintptr_t pcie_get_ecam_base(uint32_t bdf)
+static uintptr_t pcie_get_ecam_base(uint32_t bdf)
 {
 	uint8_t ecam_index = 0, sec_bus = 0, sub_bus;
 	uint16_t seg_num = (uint16_t)PCIE_EXTRACT_BDF_SEG(bdf);
@@ -466,7 +485,7 @@
  * @param   None
  * @return  None
  */
-void pcie_print_device_info(void)
+static void pcie_print_device_info(void)
 {
 	uint32_t bdf, dp_type;
 	uint32_t tbl_index = 0;
@@ -596,18 +615,11 @@
  * @param	void
  * @return	void
  */
-void pcie_create_info_table(void)
+static void pcie_create_info_table(void)
 {
 	unsigned int num_ecam;
 
 	INFO("Creating PCIe info table\n");
-
-	g_pcie_info_table = plat_pcie_get_info_table();
-	if (g_pcie_info_table == NULL) {
-		ERROR("PCIe info not returned by platform\n");
-		panic();
-	}
-
 	g_pcie_bdf_table = pcie_bdf_table;
 
 	num_ecam = g_pcie_info_table->num_entries;
@@ -620,12 +632,611 @@
 	pcie_print_device_info();
 }
 
+static void pal_pci_cfg_write(uint32_t bus, uint32_t dev, uint32_t func,
+			      uint32_t offset, uint32_t data)
+{
+	pcie_write_cfg(PCIE_CREATE_BDF(0, bus, dev, func), offset, data);
+}
+
+static void pal_pci_cfg_read(uint32_t bus, uint32_t dev, uint32_t func,
+			     uint32_t offset, uint32_t *value)
+{
+	*value = pcie_read_cfg(PCIE_CREATE_BDF(0, bus, dev, func), offset);
+}
+
+/*
+ * This API programs the Memory Base and Memeory limit register of the Bus,
+ * Device and Function of Type1 Header
+ */
+static void get_resource_base_32(uint32_t bus, uint32_t dev, uint32_t func,
+				 uint32_t bar32_p_base, uint32_t bar32_np_base,
+				 uint32_t bar32_p_limit, uint32_t bar32_np_limit)
+{
+	uint32_t mem_bar_np;
+	uint32_t mem_bar_p;
+
+	/* Update the 32 bit NP-BAR start address for the next iteration */
+	if (bar32_np_base != g_bar32_np_start) {
+		if ((g_bar32_np_start << 12) != 0) {
+			g_bar32_np_start = (g_bar32_np_start &
+					    MEM_BASE32_LIM_MASK) + BAR_INCREMENT;
+		}
+
+		if (bar32_np_limit == g_bar32_np_start) {
+			bar32_np_limit = bar32_np_limit - BAR_INCREMENT;
+		}
+
+		pal_pci_cfg_read(bus, dev, func, NON_PRE_FET_OFFSET,
+				 &mem_bar_np);
+		mem_bar_np = ((bar32_np_limit & MEM_BASE32_LIM_MASK) |
+			      mem_bar_np);
+		pal_pci_cfg_write(bus, dev, func, NON_PRE_FET_OFFSET,
+				  mem_bar_np);
+	}
+
+	/* Update the 32 bit P-BAR start address for the next iteration */
+	if (bar32_p_base != g_bar32_p_start) {
+		if ((g_bar32_p_start  << 12) != 0) {
+			g_bar32_p_start  = (g_bar32_p_start &
+					    MEM_BASE32_LIM_MASK) + BAR_INCREMENT;
+		}
+
+		if (bar32_p_limit == g_bar32_p_start) {
+			bar32_p_limit = bar32_p_limit - BAR_INCREMENT;
+		}
+
+		pal_pci_cfg_read(bus, dev, func, PRE_FET_OFFSET, &mem_bar_p);
+		mem_bar_p = ((bar32_p_limit & MEM_BASE32_LIM_MASK) | mem_bar_p);
+		pal_pci_cfg_write(bus, dev, func, PRE_FET_OFFSET, mem_bar_p);
+	}
+}
+
+/*
+ * This API programs the Memory Base and Memeory limit register of the Bus,
+ * Device and Function of Type1 Header
+ */
+static void get_resource_base_64(uint32_t bus, uint32_t dev, uint32_t func,
+				 uint64_t bar64_p_base, uint64_t g_bar64_p_max)
+{
+	uint32_t bar64_p_lower32_base = (uint32_t)bar64_p_base;
+	uint32_t bar64_p_upper32_base = (uint32_t)(bar64_p_base >> 32);
+	uint32_t bar64_p_lower32_limit = (uint32_t)g_bar64_p_max;
+	uint32_t bar64_p_upper32_limit = (uint32_t)(g_bar64_p_max >> 32);
+
+	/* Obtain the memory base and memory limit */
+	bar64_p_lower32_base = REG_MASK_SHIFT(bar64_p_lower32_base);
+	bar64_p_lower32_limit = REG_MASK_SHIFT(bar64_p_lower32_limit);
+	uint32_t mem_bar_p = ((bar64_p_lower32_limit << 16) |
+			      bar64_p_lower32_base);
+
+	/* Configure Memory base and Memory limit register */
+	if ((bar64_p_base != g_bar64_p_max) && (g_bar64_p_start <=
+						g_bar64_p_max)) {
+		if ((g_bar64_p_start  << 12) != 0) {
+			g_bar64_p_start = (g_bar64_p_start &
+					   MEM_BASE64_LIM_MASK) + BAR_INCREMENT;
+		}
+
+		if (bar64_p_lower32_limit == g_bar64_p_start) {
+			bar64_p_lower32_limit = bar64_p_lower32_limit -
+				BAR_INCREMENT;
+		}
+
+		g_bar64_p_start = (g_bar64_p_start & MEM_BASE64_LIM_MASK) +
+			BAR_INCREMENT;
+
+		pal_pci_cfg_write(bus, dev, func, PRE_FET_OFFSET, mem_bar_p);
+		pal_pci_cfg_write(bus, dev, func, PRE_FET_OFFSET + 4,
+				  bar64_p_upper32_base);
+		pal_pci_cfg_write(bus, dev, func, PRE_FET_OFFSET + 8,
+				  bar64_p_upper32_limit);
+	}
+}
+
+static void pcie_rp_program_bar(uint32_t bus, uint32_t dev, uint32_t func)
+{
+	uint64_t bar_size, bar_upper_bits;
+	uint32_t offset = BAR0_OFFSET;
+	uint32_t bar_reg_value, bar_lower_bits;
+
+	while (offset <= TYPE1_BAR_MAX_OFF) {
+		pal_pci_cfg_read(bus, dev, func, offset, &bar_reg_value);
+
+		if (BAR_REG(bar_reg_value) == BAR_64_BIT) {
+			/*
+			 * BAR supports 64-bit address therefore, write all 1's
+			 * to BARn and BARn+1 and identify the size requested
+			 */
+			pal_pci_cfg_write(bus, dev, func, offset, 0xFFFFFFF0);
+			pal_pci_cfg_write(bus, dev, func, offset + 4,
+					  0xFFFFFFFF);
+			pal_pci_cfg_read(bus, dev, func, offset,
+					 &bar_lower_bits);
+			bar_size = bar_lower_bits & BAR_MASK;
+
+			pal_pci_cfg_read(bus, dev, func, offset + 4,
+					 &bar_reg_value);
+			bar_upper_bits = bar_reg_value;
+			bar_size = bar_size | (bar_upper_bits << 32);
+
+			bar_size = ~bar_size + 1;
+
+			/*
+			 * If BAR size is 0, then BAR not implemented, move to
+			 * next BAR
+			 */
+			if (bar_size == 0) {
+				offset = offset + 8;
+				continue;
+			}
+
+			pal_pci_cfg_write(bus, dev, func, offset,
+					  (uint32_t)g_rp_bar64_value);
+			pal_pci_cfg_write(bus, dev, func, offset + 4,
+					  (uint32_t)(g_rp_bar64_value >> 32));
+			offset = offset + 8;
+		} else {
+			/*
+			 * BAR supports 32-bit address. Write all 1's to BARn
+			 * and identify the size requested
+			 */
+			pal_pci_cfg_write(bus, dev, func, offset, 0xFFFFFFF0);
+			pal_pci_cfg_read(bus, dev, func, offset,
+					 &bar_lower_bits);
+			bar_reg_value = bar_lower_bits & BAR_MASK;
+			bar_size = ~bar_reg_value + 1;
+
+			/*
+			 * If BAR size is 0, then BAR not implemented, move to
+			 * next BAR
+			 */
+			if (bar_size == 0) {
+				offset = offset + 4;
+				continue;
+			}
+
+			pal_pci_cfg_write(bus, dev, func, offset,
+					  g_rp_bar32_value);
+			g_rp_bar32_value = g_rp_bar32_value + (uint32_t)bar_size;
+			offset = offset + 4;
+		}
+	}
+}
+
+/*
+ * This API programs all the BAR register in PCIe config space pointed by Bus,
+ *  Device and Function for an End Point PCIe device
+ */
+static void pcie_program_bar_reg(uint32_t bus, uint32_t dev, uint32_t func)
+{
+	uint64_t bar_size, bar_upper_bits;
+	uint32_t bar_reg_value, bar_lower_bits;
+	uint32_t offset = BAR0_OFFSET;
+	uint32_t np_bar_size = 0;
+	uint32_t p_bar_size = 0, p_bar64_size = 0;
+
+	while (offset <= TYPE0_BAR_MAX_OFF) {
+		pal_pci_cfg_read(bus, dev, func, offset, &bar_reg_value);
+
+		if (BAR_MEM(bar_reg_value) == BAR_PRE_MEM) {
+			if (BAR_REG(bar_reg_value) == BAR_64_BIT) {
+				/*
+				 * BAR supports 64-bit address therefore,
+				 * write all 1's to BARn and BARn+1 and identify
+				 * the size requested
+				 */
+
+				pal_pci_cfg_write(bus, dev, func, offset,
+						  0xFFFFFFF0);
+				pal_pci_cfg_write(bus, dev, func, offset + 4,
+						  0xFFFFFFFF);
+				pal_pci_cfg_read(bus, dev, func, offset,
+						 &bar_lower_bits);
+				bar_size = bar_lower_bits & BAR_MASK;
+
+				pal_pci_cfg_read(bus, dev, func, offset + 4,
+						 &bar_reg_value);
+				bar_upper_bits = bar_reg_value;
+				bar_size = bar_size | (bar_upper_bits << 32);
+
+				bar_size = ~bar_size + 1;
+
+				/*
+				 * If BAR size is 0, then BAR not implemented,
+				 * move to next BAR
+				 */
+				if (bar_size == 0) {
+					offset = offset + 8;
+					continue;
+				}
+
+				/*
+				 * If p_bar64_size = 0 and bus number is same as
+				 * bus of previous bus number, then check if the
+				 * current PCIe Device BAR size is greater than
+				 * the previous BAR size, if yes then add current
+				 * BAR size to the updated start address else
+				 * add the previous BAR size to the updated
+				 * start address
+				 */
+				if ((p_bar64_size == 0) && ((g_64_bus == bus))) {
+					if (g_bar64_size < bar_size) {
+						g_bar64_p_start =
+							g_bar64_p_start +
+							bar_size;
+					} else {
+						g_bar64_p_start =
+							g_bar64_p_start +
+							g_bar64_size;
+					}
+				} else if ((g_bar64_size < bar_size) &&
+					   (p_bar64_size != 0)) {
+					g_bar64_p_start = g_bar64_p_start +
+						bar_size;
+				} else {
+					g_bar64_p_start = g_bar64_p_start +
+						p_bar64_size;
+				}
+
+				pal_pci_cfg_write(bus, dev, func, offset,
+						  (uint32_t)g_bar64_p_start);
+				pal_pci_cfg_write(bus, dev, func, offset + 4,
+						  (uint32_t)(g_bar64_p_start >>
+							     32));
+
+				p_bar64_size = (uint32_t)bar_size;
+				g_bar64_size = (uint32_t)bar_size;
+				g_64_bus = bus;
+				offset = offset + 8;
+			} else {
+				/*
+				 * BAR supports 32-bit address. Write all 1's
+				 * to BARn and identify the size requested
+				 */
+				pal_pci_cfg_write(bus, dev, func, offset,
+						  0xFFFFFFF0);
+				pal_pci_cfg_read(bus, dev, func, offset,
+						 &bar_lower_bits);
+				bar_reg_value = bar_lower_bits & BAR_MASK;
+				bar_size = ~bar_reg_value + 1;
+
+				/*
+				 * If BAR size is 0, then BAR not implemented,
+				 * move to next BAR
+				 */
+				if (bar_size == 0) {
+					offset = offset + 4;
+					continue;
+				}
+
+				/*
+				 * If p_bar_size = 0 and bus number is same as
+				 * bus of previous bus number, then check if the
+				 * current PCIe Device BAR size is greater than
+				 * the previous BAR size, if yes then add
+				 * current BAR size to the updated start
+				 * address else add the previous BAR size to the
+				 * updated start address
+				 */
+				if ((p_bar_size == 0) && ((g_p_bus == bus))) {
+					if (g_p_bar_size < bar_size) {
+						g_bar32_p_start =
+							g_bar32_p_start +
+							(uint32_t)bar_size;
+					} else {
+						g_bar32_p_start =
+							g_bar32_p_start +
+							g_p_bar_size;
+					}
+				} else if ((g_p_bar_size < bar_size) &&
+					   (p_bar_size != 0)) {
+					g_bar32_p_start = g_bar32_p_start +
+						(uint32_t)bar_size;
+				} else {
+					g_bar32_p_start = g_bar32_p_start +
+						p_bar_size;
+				}
+
+				pal_pci_cfg_write(bus, dev, func, offset,
+						  g_bar32_p_start);
+				p_bar_size = (uint32_t)bar_size;
+				g_p_bar_size = (uint32_t)bar_size;
+				g_p_bus = bus;
+
+				offset = offset + 4;
+			}
+		} else {
+			/*
+			 * BAR supports 32-bit address. Write all 1's to BARn
+			 * and identify the size requested
+			 */
+			pal_pci_cfg_write(bus, dev, func, offset, 0xFFFFFFF0);
+			pal_pci_cfg_read(bus, dev, func, offset,
+					 &bar_lower_bits);
+			bar_reg_value = bar_lower_bits & BAR_MASK;
+			bar_size = ~bar_reg_value + 1;
+
+			/*
+			 * If BAR size is 0, then BAR not implemented, move to
+			 * next BAR
+			 */
+			if (bar_size == 0) {
+				if (BAR_REG(bar_lower_bits) == BAR_64_BIT) {
+					offset = offset + 8;
+				}
+
+				if (BAR_REG(bar_lower_bits) == BAR_32_BIT) {
+					offset = offset + 4;
+				}
+
+				continue;
+			}
+
+			/*
+			 * If np_bar_size = 0 and bus number is same as bus of
+			 * previous bus number, then check if the current PCIe
+			 * Device BAR size is greater than the previous BAR
+			 * size, if yes then add current BAR size to the
+			 * updated start address else add the previous BAR size
+			 * to the updated start address
+			 */
+			if ((np_bar_size == 0) && ((g_np_bus == bus))) {
+				if (g_np_bar_size < bar_size) {
+					g_bar32_np_start = g_bar32_np_start +
+						(uint32_t)bar_size;
+				} else {
+					g_bar32_np_start = g_bar32_np_start +
+						g_np_bar_size;
+				}
+			} else if ((g_np_bar_size < bar_size) &&
+				   (np_bar_size != 0)) {
+				g_bar32_np_start = g_bar32_np_start +
+					(uint32_t)bar_size;
+			} else {
+				g_bar32_np_start = g_bar32_np_start +
+					np_bar_size;
+			}
+
+			pal_pci_cfg_write(bus, dev, func, offset,
+					  g_bar32_np_start);
+			np_bar_size = (uint32_t)bar_size;
+			g_np_bar_size = (uint32_t)bar_size;
+			g_np_bus = bus;
+
+			pal_pci_cfg_read(bus, dev, func, offset, &bar_reg_value);
+			if (BAR_REG(bar_reg_value) == BAR_64_BIT) {
+				pal_pci_cfg_write(bus, dev, func,
+						  offset + 4, 0);
+				offset = offset + 8;
+			}
+
+			if (BAR_REG(bar_reg_value) == BAR_32_BIT) {
+				offset = offset + 4;
+			}
+		}
+
+		g_bar32_p_max = g_bar32_p_start;
+		g_bar32_np_max = g_bar32_np_start;
+		g_bar64_p_max =  g_bar64_p_start;
+	}
+}
+
+/*
+ * This API performs the PCIe bus enumeration
+ *
+ * bus,sec_bus - Bus(8-bits), secondary bus (8-bits)
+ * sub_bus - Subordinate bus
+ */
+static uint32_t pcie_enumerate_device(uint32_t bus, uint32_t sec_bus)
+{
+	uint32_t vendor_id = 0;
+	uint32_t header_value;
+	uint32_t sub_bus = bus;
+	uint32_t dev;
+	uint32_t func;
+	uint32_t class_code;
+	uint32_t com_reg_value;
+	uint32_t bar32_p_limit;
+	uint32_t bar32_np_limit;
+	uint32_t bar32_p_base = g_bar32_p_start;
+	uint32_t bar32_np_base = g_bar32_np_start;
+	uint64_t bar64_p_base = g_bar64_p_start;
+
+	if (bus == ((g_pcie_info_table->block[g_pcie_index].end_bus_num) + 1)) {
+		return sub_bus;
+	}
+
+	for (dev = 0; dev < PCIE_MAX_DEV; dev++) {
+		for (func = 0; func < PCIE_MAX_FUNC; func++) {
+			pal_pci_cfg_read(bus, dev, func, 0, &vendor_id);
+
+			if ((vendor_id == 0x0) || (vendor_id == 0xFFFFFFFF)) {
+				continue;
+			}
+
+			/* Skip Hostbridge configuration */
+			pal_pci_cfg_read(bus, dev, func, TYPE01_RIDR,
+					 &class_code);
+
+			if ((((class_code >> CC_BASE_SHIFT) & CC_BASE_MASK) ==
+			     HB_BASE_CLASS) &&
+			    (((class_code >> CC_SUB_SHIFT) & CC_SUB_MASK)) ==
+			    HB_SUB_CLASS) {
+				continue;
+			}
+
+			pal_pci_cfg_read(bus, dev, func, HEADER_OFFSET,
+					 &header_value);
+			if (PCIE_HEADER_TYPE(header_value) == TYPE1_HEADER) {
+				/*
+				 * Enable memory access, Bus master enable and
+				 * I/O access
+				 */
+				pal_pci_cfg_read(bus, dev, func,
+						 COMMAND_REG_OFFSET,
+						 &com_reg_value);
+
+				pal_pci_cfg_write(bus, dev, func,
+						  COMMAND_REG_OFFSET,
+						  (com_reg_value |
+						   REG_ACC_DATA));
+
+				pal_pci_cfg_write(bus, dev, func,
+						  BUS_NUM_REG_OFFSET,
+						  BUS_NUM_REG_CFG(0xFF, sec_bus,
+								  bus));
+
+				pal_pci_cfg_write(bus, dev, func,
+						  NON_PRE_FET_OFFSET,
+						  ((g_bar32_np_start >> 16) &
+						   0xFFF0));
+
+				pal_pci_cfg_write(bus, dev, func,
+						  PRE_FET_OFFSET,
+						  ((g_bar32_p_start >> 16) &
+						   0xFFF0));
+
+				sub_bus = pcie_enumerate_device(sec_bus,
+								(sec_bus + 1));
+				pal_pci_cfg_write(bus, dev, func,
+						  BUS_NUM_REG_OFFSET,
+						  BUS_NUM_REG_CFG(sub_bus,
+								  sec_bus, bus));
+				sec_bus = sub_bus + 1;
+
+				/*
+				 * Obtain the start memory base address & the
+				 * final memory base address of 32 bit BAR
+				 */
+				bar32_p_limit = g_bar32_p_max;
+				bar32_np_limit = g_bar32_np_max;
+
+				get_resource_base_32(bus, dev, func,
+						     bar32_p_base,
+						     bar32_np_base,
+						     bar32_p_limit,
+						     bar32_np_limit);
+
+				/*
+				 * Obtain the start memory base address & the
+				 * final memory base address of 64 bit BAR
+				 */
+				get_resource_base_64(bus, dev, func,
+						     bar64_p_base,
+						     g_bar64_p_max);
+
+				/* Update the BAR values of Type 1 Devices */
+				pcie_rp_program_bar(bus, dev, func);
+
+				/* Update the base and limit values */
+				bar32_p_base = g_bar32_p_start;
+				bar32_np_base = g_bar32_np_start;
+				bar64_p_base = g_bar64_p_start;
+			}
+
+			if (PCIE_HEADER_TYPE(header_value) == TYPE0_HEADER) {
+				pcie_program_bar_reg(bus, dev, func);
+				sub_bus = sec_bus - 1;
+			}
+		}
+	}
+
+	return sub_bus;
+}
+
+/*
+ * This API clears the primary bus number configured in the Type1 Header.
+ * Note: This is done to make sure the hardware is compatible
+ * with Linux enumeration.
+ */
+static void pcie_clear_pri_bus(void)
+{
+	uint32_t bus;
+	uint32_t dev;
+	uint32_t func;
+	uint32_t bus_value;
+	uint32_t header_value;
+	uint32_t vendor_id;
+
+	for (bus = 0; bus <= g_pcie_info_table->block[g_pcie_index].end_bus_num;
+	     bus++) {
+		for (dev = 0; dev < PCIE_MAX_DEV; dev++) {
+			for (func = 0; func < PCIE_MAX_FUNC; func++) {
+				pal_pci_cfg_read(bus, dev, func, 0, &vendor_id);
+
+				if ((vendor_id == 0x0) ||
+				    (vendor_id == 0xFFFFFFFF)) {
+					continue;
+				}
+
+				pal_pci_cfg_read(bus, dev, func, HEADER_OFFSET,
+						 &header_value);
+				if (PCIE_HEADER_TYPE(header_value) ==
+				    TYPE1_HEADER) {
+					pal_pci_cfg_read(bus, dev, func,
+							 BUS_NUM_REG_OFFSET,
+							 &bus_value);
+
+					bus_value = bus_value &
+						PRI_BUS_CLEAR_MASK;
+
+					pal_pci_cfg_write(bus, dev, func,
+							  BUS_NUM_REG_OFFSET,
+							  bus_value);
+				}
+			}
+		}
+	}
+}
+
+static void pcie_enumerate_devices(void)
+{
+	uint32_t pri_bus, sec_bus;
+	int rc;
+
+	g_pcie_info_table = plat_pcie_get_info_table();
+	if (g_pcie_info_table == NULL) {
+		ERROR("PCIe info not returned by platform\n");
+		panic();
+	}
+
+	if (g_pcie_info_table->num_entries == 0) {
+		INFO("Skipping Enumeration\n");
+		return;
+	}
+
+	/* Get platform specific bar config parameters */
+	rc = plat_pcie_get_bar_config(&g_bar64_p_start, &g_rp_bar64_value,
+				      &g_bar32_np_start, &g_bar32_p_start,
+				      &g_rp_bar32_value);
+	if (rc != 0) {
+		ERROR("PCIe bar config parameters not returned by platform\n");
+		panic();
+	}
+
+	INFO("Starting Enumeration\n");
+	while (g_pcie_index < g_pcie_info_table->num_entries) {
+		pri_bus = g_pcie_info_table->block[g_pcie_index].start_bus_num;
+
+		sec_bus = pri_bus + 1;
+
+		pcie_enumerate_device(pri_bus, sec_bus);
+		pcie_clear_pri_bus();
+
+		g_pcie_index++;
+	}
+	g_enumerate = 0;
+	g_pcie_index = 0;
+}
+
 void pcie_init(void)
 {
 	static bool is_init;
 
 	/* Create PCIe table and enumeration */
 	if (!is_init) {
+		pcie_enumerate_devices();
+
 		pcie_create_info_table();
 		is_init = true;
 	}
diff --git a/plat/arm/fvp/fvp_pcie.c b/plat/arm/fvp/fvp_pcie.c
index 38bdf39..4bba516 100644
--- a/plat/arm/fvp/fvp_pcie.c
+++ b/plat/arm/fvp/fvp_pcie.c
@@ -27,6 +27,28 @@
 	return &fvp_pcie_cfg;
 }
 
+/* Retrieve platform PCIe bar config values */
+int plat_pcie_get_bar_config(uint64_t *bar64_val, uint64_t *rp_bar64_val,
+			     uint32_t *bar32np_val, uint32_t *bar32p_val,
+			     uint32_t *rp_bar32_val)
+{
+#ifdef __aarch64__
+	assert((bar64_val != NULL) && (rp_bar64_val != NULL) &&
+	       (bar32np_val != NULL) && (bar32p_val != NULL) &&
+	       (rp_bar32_val != NULL));
+
+	*bar64_val = PLATFORM_OVERRIDE_PCIE_BAR64_VALUE;
+	*rp_bar64_val = PLATFORM_OVERRIDE_RP_BAR64_VALUE;
+
+	*bar32np_val = PLATFORM_OVERRIDE_PCIE_BAR32NP_VALUE;
+	*bar32p_val = PLATFORM_OVERRIDE_PCIE_BAR32P_VALUE;
+	*rp_bar32_val = PLATOFRM_OVERRIDE_RP_BAR32_VALUE;
+
+	return 0;
+#endif
+	return -1;
+}
+
 /*
  * Retrieve platform PCIe memory region (Base Platform RevC only)
  */
diff --git a/plat/arm/fvp/include/platform_pcie.h b/plat/arm/fvp/include/platform_pcie.h
index 4b3a0e9..4a2817e 100644
--- a/plat/arm/fvp/include/platform_pcie.h
+++ b/plat/arm/fvp/include/platform_pcie.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,4 +19,11 @@
 #define PLATFORM_PCIE_START_BUS_NUM_0	0x0
 #define PLATFORM_PCIE_END_BUS_NUM_0	0xFF
 
+/* PCIe BAR config parameters*/
+#define PLATFORM_OVERRIDE_PCIE_BAR64_VALUE	0x4000100000
+#define PLATFORM_OVERRIDE_RP_BAR64_VALUE	0x4000000000
+#define PLATFORM_OVERRIDE_PCIE_BAR32NP_VALUE	0x50000000
+#define PLATFORM_OVERRIDE_PCIE_BAR32P_VALUE	0x50600000
+#define PLATOFRM_OVERRIDE_RP_BAR32_VALUE	0x50850000
+
 #endif	/* PLATFORM_PCIE_H */
diff --git a/plat/common/plat_common.c b/plat/common/plat_common.c
index c06ad13..f8524cf 100644
--- a/plat/common/plat_common.c
+++ b/plat/common/plat_common.c
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
  *
@@ -25,6 +26,7 @@
 #pragma weak tftf_plat_reset
 #pragma weak plat_get_prot_regions
 #pragma weak plat_pcie_get_info_table
+#pragma weak plat_pcie_get_bar_config
 #pragma weak plat_get_invalid_addr
 #pragma weak plat_get_dev_region
 
@@ -157,6 +159,13 @@
 	return NULL;
 }
 
+int plat_pcie_get_bar_config(uint64_t *bar64_val, uint64_t *rp_bar64_val,
+			     uint32_t *bar32np_val, uint32_t *bar32p_val,
+			     uint32_t *rp_bar32_val)
+{
+	return -1;
+}
+
 uintptr_t plat_get_invalid_addr(void)
 {
 	return (uintptr_t)0x0;