feat(rmm): add PCIe IO info to Boot manifest

- Add PCIe and SMMUv3 related information to DTS for
  configurations with ENABLE_RME=1.
- Add entries for PCIe IO memory regions to Boot manifest
- Update RMMD_MANIFEST_VERSION_MINOR from 3 to 4.
- Read PCIe related information from DTB and write it to
  Boot manifest.
- Rename structures that used to describe DRAM layout
  and now describe both DRAM and PCIe IO memory regions:
  - ns_dram_bank -> memory_bank
  - ns_dram_info -> memory_info.

Change-Id: Ib75d1af86076f724f5c330074e231f1c2ba8e21d
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index 43dc17b..662b8a4 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,7 +18,8 @@
 struct hw_topology_t soc_topology;
 struct uart_serial_config_t uart_serial_config;
 struct cpu_timer_t cpu_timer;
-struct ns_dram_layout dram_layout;
+struct dram_layout_t dram_layout;
+struct pci_props_t pci_props;
 
 /*
  * Each NS DRAM bank entry is 'reg' node property which is
@@ -27,6 +28,7 @@
 #define DRAM_ENTRY_SIZE		(4UL * sizeof(uint32_t))
 
 CASSERT(ARM_DRAM_NUM_BANKS == 2UL, ARM_DRAM_NUM_BANKS_mismatch);
+CASSERT(ARM_PCI_NUM_REGIONS == 2UL, ARM_PCI_NUM_REGIONS_mismatch);
 
 #define ILLEGAL_ADDR	ULL(~0)
 
@@ -352,8 +354,98 @@
 	return 0;
 }
 
+/*
+ * Each PCIe memory region entry is 'ranges' node property which is
+ * an arbitrary number of (child-bus-address, parent-bus-address, length)
+ * triplets. E.g. with
+ * #address-cells = <3>
+ * #size-cells = <2>
+ * parent's #address-cells = <2>
+ * each entry occupies 7 32-bit words.
+ */
+int fconf_populate_pci_props(uintptr_t config)
+{
+	int node, parent, len, err;
+	int parent_ac, ac, sc, entry_len;
+	const uint32_t *reg, *ranges;
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)config;
+
+	/* Find 'pci' node */
+	node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type",
+					     "pci", sizeof("pci"));
+	if (node < 0) {
+		WARN("FCONF: Unable to locate 'pci' node\n");
+		pci_props.ecam_base = 0UL;
+		pci_props.size = 0UL;
+		pci_props.num_ncoh_regions = 0UL;
+		/* Don't return error code if 'pci' node not found */
+		return 0;
+	}
+
+	reg = fdt_getprop(hw_config_dtb, node, "reg", &len);
+	if (reg == NULL) {
+		ERROR("FCONF failed to read 'reg' property\n");
+		return len;
+	}
+
+	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0,
+					 (uintptr_t *)&pci_props.ecam_base,
+					 (size_t *)&pci_props.size);
+	if (err < 0) {
+		ERROR("FCONF: Failed to read 'reg' property of 'pci' node\n");
+		return err;
+	}
+
+	parent = fdt_parent_offset(hw_config_dtb, node);
+	if (parent < 0) {
+		return -FDT_ERR_BADOFFSET;
+	}
+
+	parent_ac = fdt_address_cells(hw_config_dtb, parent);
+	ac = fdt_address_cells(hw_config_dtb, node);
+	sc = fdt_size_cells(hw_config_dtb, node);
+
+	entry_len = parent_ac + ac + sc;
+
+	ranges = fdt_getprop(hw_config_dtb, node, "ranges", &len);
+	if (ranges == NULL) {
+		ERROR("FCONF failed to read 'ranges' property\n");
+		return len;
+	}
+
+	/* 'ranges' length in 32-bit words */
+	len /= sizeof(uint32_t);
+	if ((len % entry_len) != 0) {
+		return -FDT_ERR_BADVALUE;
+	}
+
+	pci_props.num_ncoh_regions = (uint64_t)(len / entry_len);
+
+	if (pci_props.num_ncoh_regions > ARM_PCI_NUM_REGIONS) {
+		WARN("FCONF: 'ranges' reports more memory regions than supported\n");
+		pci_props.num_ncoh_regions = ARM_PCI_NUM_REGIONS;
+	}
+
+	for (unsigned int i = 0U; i < (unsigned int)pci_props.num_ncoh_regions; i++) {
+		unsigned int cell = i * entry_len + ac;
+
+		/* Read CPU address (parent-bus-address) space */
+		pci_props.ncoh_regions[i].base =
+			fdt_read_prop_cells(&ranges[cell], ac);
+
+		/* Read CPU address size */
+		pci_props.ncoh_regions[i].size =
+			fdt_read_prop_cells(&ranges[cell + parent_ac], sc);
+	}
+
+	return 0;
+}
+
 FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, dram_layout, fconf_populate_dram_layout);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, pci_props, fconf_populate_pci_props);
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index bdc2cac..19a340f 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -34,12 +34,11 @@
 #define FVP_GICV2		1
 #define FVP_GICV3		2
 
-/* Defines for RMM Console*/
+/* Defines for RMM Console */
 #define FVP_RMM_CONSOLE_BASE		UL(0x1c0c0000)
 #define FVP_RMM_CONSOLE_BAUD		UL(115200)
 #define FVP_RMM_CONSOLE_CLK_IN_HZ	UL(14745600)
 #define FVP_RMM_CONSOLE_NAME		"pl011"
-
 #define FVP_RMM_CONSOLE_COUNT		UL(1)
 
 /*******************************************************************************
@@ -591,11 +590,78 @@
 
 	return sum;
 }
-
+/*
+ * Boot Manifest structure illustration, with two DRAM banks,
+ * a single console and one device memory with two PCIe device
+ * non-coherent address ranges.
+ *
+ * +--------------------------------------------------+
+ * | offset |        field       |      comment       |
+ * +--------+--------------------+--------------------+
+ * |   0    |       version      |     0x00000004     |
+ * +--------+--------------------+--------------------+
+ * |   4    |       padding      |     0x00000000     |
+ * +--------+--------------------+--------------------+
+ * |   8    |      plat_data     |       NULL         |
+ * +--------+--------------------+--------------------+
+ * |   16   |      num_banks     |                    |
+ * +--------+--------------------+                    |
+ * |   24   |       banks        |     plat_dram      +--+
+ * +--------+--------------------+                    |  |
+ * |   32   |      checksum      |                    |  |
+ * +--------+--------------------+--------------------+  |
+ * |   40   |    num_consoles    |                    |  |
+ * +--------+--------------------+                    |  |
+ * |   48   |      consoles      |    plat_console    +--|--+
+ * +--------+--------------------+                    |  |  |
+ * |   56   |      checksum      |                    |  |  |
+ * +--------+--------------------+--------------------+  |  |
+ * |   64   |      num_banks     |                    |  |  |
+ * +--------+--------------------+                    |  |  |
+ * |   72   |        banks       |  plat_ncoh_region  +--|--|--+
+ * +--------+--------------------+                    |  |  |  |
+ * |   80   |      checksum      |                    |  |  |  |
+ * +--------+--------------------+--------------------+  |  |  |
+ * |   88   |      num_banks     |                    |  |  |  |
+ * +--------+--------------------+                    |  |  |  |
+ * |   96   |       banks        |   plat_coh_region  |  |  |  |
+ * +--------+--------------------+                    |  |  |  |
+ * |   104  |      checksum      |                    |  |  |  |
+ * +--------+--------------------+--------------------+<-+  |  |
+ * |   112  |       base 0       |                    |     |  |
+ * +--------+--------------------+     mem_bank[0]    |     |  |
+ * |   120  |       size 0       |                    |     |  |
+ * +--------+--------------------+--------------------+     |  |
+ * |   128  |       base 1       |                    |     |  |
+ * +--------+--------------------+     mem_bank[1]    |     |  |
+ * |   136  |       size 1       |                    |     |  |
+ * +--------+--------------------+--------------------+<----+  |
+ * |   144  |       base         |                    |        |
+ * +--------+--------------------+                    |        |
+ * |   152  |      map_pages     |                    |        |
+ * +--------+--------------------+                    |        |
+ * |   160  |       name         |                    |        |
+ * +--------+--------------------+     consoles[0]    |        |
+ * |   168  |     clk_in_hz      |                    |        |
+ * +--------+--------------------+                    |        |
+ * |   176  |     baud_rate      |                    |        |
+ * +--------+--------------------+                    |        |
+ * |   184  |       flags        |                    |        |
+ * +--------+--------------------+--------------------+<-------+
+ * |   192  |       base 0       |                    |
+ * +--------+--------------------+   ncoh_region[0]   |
+ * |   200  |       size 0       |                    |
+ * +--------+--------------------+--------------------+
+ * |   208  |       base 1       |                    |
+ * +--------+--------------------+   ncoh_region[1]   |
+ * |   216  |       size 1       |                    |
+ * +--------+--------------------+--------------------+
+ */
 int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
 {
 	uint64_t checksum, num_banks, num_consoles;
-	struct ns_dram_bank *bank_ptr;
+	uint64_t num_ncoh_regions, num_coh_regions;
+	struct memory_bank *bank_ptr, *ncoh_region_ptr;
 	struct console_info *console_ptr;
 
 	assert(manifest != NULL);
@@ -607,71 +673,45 @@
 	/* Set number of consoles */
 	num_consoles = FVP_RMM_CONSOLE_COUNT;
 
+	/* Set number of device non-coherent address ranges based on DT */
+	num_ncoh_regions = FCONF_GET_PROPERTY(hw_config, pci_props, num_ncoh_regions);
+
 	manifest->version = RMMD_MANIFEST_VERSION;
 	manifest->padding = 0U; /* RES0 */
-	manifest->plat_data = (uintptr_t)NULL;
+	manifest->plat_data = 0UL;
 	manifest->plat_dram.num_banks = num_banks;
 	manifest->plat_console.num_consoles = num_consoles;
+	manifest->plat_ncoh_region.num_banks = num_ncoh_regions;
 
-	/*
-	 * Boot Manifest structure illustration, with two dram banks and
-	 * a single console.
-	 *
-	 * +----------------------------------------+
-	 * | offset |     field      |    comment   |
-	 * +--------+----------------+--------------+
-	 * |   0    |    version     |  0x00000003  |
-	 * +--------+----------------+--------------+
-	 * |   4    |    padding     |  0x00000000  |
-	 * +--------+----------------+--------------+
-	 * |   8    |   plat_data    |     NULL     |
-	 * +--------+----------------+--------------+
-	 * |   16   |   num_banks    |              |
-	 * +--------+----------------+              |
-	 * |   24   |     banks      |   plat_dram  |
-	 * +--------+----------------+              |
-	 * |   32   |    checksum    |              |
-	 * +--------+----------------+--------------+
-	 * |   40   |  num_consoles  |              |
-	 * +--------+----------------+              |
-	 * |   48   |    consoles    | plat_console |
-	 * +--------+----------------+              |
-	 * |   56   |    checksum    |              |
-	 * +--------+----------------+--------------+
-	 * |   64   |     base 0     |              |
-	 * +--------+----------------+    bank[0]   |
-	 * |   72   |     size 0     |              |
-	 * +--------+----------------+--------------+
-	 * |   80   |     base 1     |              |
-	 * +--------+----------------+    bank[1]   |
-	 * |   88   |     size 1     |              |
-	 * +--------+----------------+--------------+
-	 * |   96   |     base       |              |
-	 * +--------+----------------+              |
-	 * |   104  |   map_pages    |              |
-	 * +--------+----------------+              |
-	 * |   112  |     name       |              |
-	 * +--------+----------------+  consoles[0] |
-	 * |   120  |   clk_in_hz    |              |
-	 * +--------+----------------+              |
-	 * |   128  |   baud_rate    |              |
-	 * +--------+----------------+              |
-	 * |   136  |     flags      |              |
-	 * +--------+----------------+--------------+
-	 */
+	/* FVP does not support device coherent address ranges */
+	num_coh_regions = 0UL;
+	manifest->plat_coh_region.num_banks = num_coh_regions;
+	manifest->plat_coh_region.banks = NULL;
+	manifest->plat_coh_region.checksum = 0UL;
 
-	bank_ptr = (struct ns_dram_bank *)
-			(((uintptr_t)manifest) + sizeof(*manifest));
+	bank_ptr = (struct memory_bank *)
+			(((uintptr_t)manifest) + sizeof(struct rmm_manifest));
 	console_ptr = (struct console_info *)
-			((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr)));
-
+			((uintptr_t)bank_ptr + (num_banks *
+						sizeof(struct memory_bank)));
+	ncoh_region_ptr = (struct memory_bank *)
+			((uintptr_t)console_ptr + (num_consoles *
+						sizeof(struct console_info)));
 	manifest->plat_dram.banks = bank_ptr;
 	manifest->plat_console.consoles = console_ptr;
+	manifest->plat_ncoh_region.banks = ncoh_region_ptr;
 
 	/* Ensure the manifest is not larger than the shared buffer */
 	assert((sizeof(struct rmm_manifest) +
-		(sizeof(struct console_info) * manifest->plat_console.num_consoles) +
-		(sizeof(struct ns_dram_bank) * manifest->plat_dram.num_banks)) <= ARM_EL3_RMM_SHARED_SIZE);
+		(sizeof(struct memory_bank) *
+			manifest->plat_dram.num_banks) +
+		(sizeof(struct console_info) *
+			manifest->plat_console.num_consoles) +
+		(sizeof(struct memory_bank) *
+			manifest->plat_ncoh_region.num_banks) +
+		(sizeof(struct memory_bank) *
+			manifest->plat_coh_region.num_banks))
+		<= ARM_EL3_RMM_SHARED_SIZE);
 
 	/* Calculate checksum of plat_dram structure */
 	checksum = num_banks + (uint64_t)bank_ptr;
@@ -683,31 +723,56 @@
 	}
 
 	/* Update checksum */
-	checksum += checksum_calc((uint64_t *)bank_ptr, sizeof(struct ns_dram_bank) * num_banks);
+	checksum += checksum_calc((uint64_t *)bank_ptr, sizeof(struct memory_bank) * num_banks);
 
 	/* Checksum must be 0 */
 	manifest->plat_dram.checksum = ~checksum + 1UL;
 
-	/* Calculate the checksum of the plat_consoles structure */
+	/* Calculate the checksum of plat_consoles structure */
 	checksum = num_consoles + (uint64_t)console_ptr;
 
 	/* Zero out the console info struct */
-	(void)memset((void *)console_ptr, '\0', sizeof(struct console_info) * num_consoles);
+	(void)memset((void *)console_ptr, '\0',
+			sizeof(struct console_info) * num_consoles);
 
 	console_ptr[0].base = FVP_RMM_CONSOLE_BASE;
 	console_ptr[0].map_pages = 1UL;
 	console_ptr[0].clk_in_hz = FVP_RMM_CONSOLE_CLK_IN_HZ;
 	console_ptr[0].baud_rate = FVP_RMM_CONSOLE_BAUD;
 
-	(void)strlcpy(console_ptr[0].name, FVP_RMM_CONSOLE_NAME, RMM_CONSOLE_MAX_NAME_LEN - 1UL);
+	(void)strlcpy(console_ptr[0].name, FVP_RMM_CONSOLE_NAME,
+						RMM_CONSOLE_MAX_NAME_LEN - 1UL);
 
 	/* Update checksum */
 	checksum += checksum_calc((uint64_t *)console_ptr,
 					sizeof(struct console_info) * num_consoles);
-
 	/* Checksum must be 0 */
 	manifest->plat_console.checksum = ~checksum + 1UL;
 
+	/*
+	 * Calculate the checksum of device non-coherent address ranges
+	 * info structure
+	 */
+	checksum = num_ncoh_regions + (uint64_t)ncoh_region_ptr;
+
+	/* Zero out the PCIe region info struct */
+	(void)memset((void *)ncoh_region_ptr, 0,
+			sizeof(struct memory_bank) * num_ncoh_regions);
+
+	for (unsigned long i = 0UL; i < num_ncoh_regions; i++) {
+		ncoh_region_ptr[i].base =
+			FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].base);
+		ncoh_region_ptr[i].size =
+			FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].size);
+	}
+
+	/* Update checksum */
+	checksum += checksum_calc((uint64_t *)ncoh_region_ptr,
+			sizeof(struct memory_bank) * num_ncoh_regions);
+
+	/* Checksum must be 0 */
+	manifest->plat_ncoh_region.checksum = ~checksum + 1UL;
+
 	return 0;
 }
 #endif	/* ENABLE_RME */
diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
index b7a1247..351f13d 100644
--- a/plat/arm/board/fvp/include/fconf_hw_config_getter.h
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,6 +18,7 @@
 #define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop
 #define hw_config__cpu_timer_getter(prop) cpu_timer.prop
 #define hw_config__dram_layout_getter(prop) dram_layout.prop
+#define hw_config__pci_props_getter(prop) pci_props.prop
 
 struct gicv3_config_t {
 	uint64_t gicd_base;
@@ -40,9 +41,16 @@
 	uint32_t clock_freq;
 };
 
-struct ns_dram_layout {
+struct dram_layout_t {
 	uint64_t num_banks;
-	struct ns_dram_bank dram_bank[ARM_DRAM_NUM_BANKS];
+	struct memory_bank dram_bank[ARM_DRAM_NUM_BANKS];
+};
+
+struct pci_props_t {
+	uint64_t ecam_base;
+	uint64_t size;
+	uint64_t num_ncoh_regions;
+	struct memory_bank ncoh_regions[ARM_PCI_NUM_REGIONS];
 };
 
 int fconf_populate_gicv3_config(uintptr_t config);
@@ -50,11 +58,13 @@
 int fconf_populate_uart_config(uintptr_t config);
 int fconf_populate_cpu_timer(uintptr_t config);
 int fconf_populate_dram_layout(uintptr_t config);
+int fconf_populate_pci_props(uintptr_t config);
 
 extern struct gicv3_config_t gicv3_config;
 extern struct hw_topology_t soc_topology;
 extern struct uart_serial_config_t uart_serial_config;
 extern struct cpu_timer_t cpu_timer;
-extern struct ns_dram_layout dram_layout;
+extern struct dram_layout_t dram_layout;
+extern struct pci_props_t pci_props;
 
 #endif /* FCONF_HW_CONFIG_GETTER_H */
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
index 3ef9681..2402c05 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
@@ -64,7 +64,7 @@
 int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
 {
 	uint64_t checksum, num_banks, num_consoles;
-	struct ns_dram_bank *bank_ptr;
+	struct memory_bank *bank_ptr;
 	struct console_info *console_ptr;
 
 	assert(manifest != NULL);
@@ -129,7 +129,7 @@
 	 * +--------+----------------+--------------+
 	 */
 
-	bank_ptr = (struct ns_dram_bank *)
+	bank_ptr = (struct memory_bank *)
 			(((uintptr_t)manifest) + sizeof(*manifest));
 	console_ptr = (struct console_info *)
 			((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr)));
@@ -141,7 +141,7 @@
 	assert((sizeof(struct rmm_manifest) +
 		(sizeof(struct console_info) *
 		manifest->plat_console.num_consoles) +
-		(sizeof(struct ns_dram_bank) * manifest->plat_dram.num_banks))
+		(sizeof(struct memory_bank) * manifest->plat_dram.num_banks))
 		<= ARM_EL3_RMM_SHARED_SIZE);
 
 	/* Calculate checksum of plat_dram structure */
@@ -156,7 +156,7 @@
 
 	/* Update checksum */
 	checksum += checksum_calc((uint64_t *)bank_ptr,
-		sizeof(struct ns_dram_bank) * num_banks);
+		sizeof(struct memory_bank) * num_banks);
 
 	/* Checksum must be 0 */
 	manifest->plat_dram.checksum = ~checksum + 1UL;