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/common/fdt_wrappers.c b/common/fdt_wrappers.c
index b213ffa..8638351 100644
--- a/common/fdt_wrappers.c
+++ b/common/fdt_wrappers.c
@@ -277,7 +277,7 @@
 	return err;
 }
 
-static uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells)
+uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells)
 {
 	uint64_t reg = fdt32_to_cpu(prop[0]);
 
diff --git a/docs/components/rmm-el3-comms-spec.rst b/docs/components/rmm-el3-comms-spec.rst
index 79e1d2c..f1ca031 100644
--- a/docs/components/rmm-el3-comms-spec.rst
+++ b/docs/components/rmm-el3-comms-spec.rst
@@ -53,7 +53,7 @@
     consistency with the versioning schemes used in other parts of RMM.
 
 This document specifies the 0.4 version of Boot Interface ABI and RMM-EL3
-services specification and the 0.3 version of the Boot Manifest.
+services specification and the 0.4 version of the Boot Manifest.
 
 .. _rmm_el3_boot_interface:
 
@@ -182,12 +182,12 @@
 
 This Boot Manifest is versioned independently of the Boot Interface, to help
 evolve the former independent of the latter.
-The current version for the Boot Manifest is ``v0.3`` and the rules explained
+The current version for the Boot Manifest is ``v0.4`` and the rules explained
 in :ref:`rmm_el3_ifc_versioning` apply on this version as well.
 
-The Boot Manifest v0.3 has the following fields:
+The Boot Manifest v0.4 has the following fields:
 
-   - version : Version of the Manifest (v0.3)
+   - version : Version of the Manifest (v0.4)
    - plat_data : Pointer to the platform specific data and not specified by this
      document. These data are optional and can be NULL.
    - plat_dram : Structure encoding the NS DRAM information on the platform. This
@@ -720,61 +720,65 @@
 RMM-EL3 Boot Manifest structure
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The RMM-EL3 Boot Manifest v0.3 structure contains platform boot information passed
-from EL3 to RMM. The size of the Boot Manifest is 64 bytes.
+The RMM-EL3 Boot Manifest v0.4 structure contains platform boot information passed
+from EL3 to RMM. The size of the Boot Manifest is 112 bytes.
 
 The members of the RMM-EL3 Boot Manifest structure are shown in the following
 table:
 
-+--------------+--------+----------------+----------------------------------------+
-|   Name       | Offset |     Type       |               Description              |
-+==============+========+================+========================================+
-| version      |   0    |   uint32_t     | Boot Manifest version                  |
-+--------------+--------+----------------+----------------------------------------+
-| padding      |   4    |   uint32_t     | Reserved, set to 0                     |
-+--------------+--------+----------------+----------------------------------------+
-| plat_data    |   8    |   uintptr_t    | Pointer to Platform Data section       |
-+--------------+--------+----------------+----------------------------------------+
-| plat_dram    |   16   | ns_dram_info   | NS DRAM Layout Info structure          |
-+--------------+--------+----------------+----------------------------------------+
-| plat_console |   40   | console_list   | List of consoles available to RMM      |
-+--------------+--------+----------------+----------------------------------------+
++--------------------+--------+-------------------+----------------------------------------------+
+|   Name             | Offset |       Type        |            Description                       |
++====================+========+===================+==============================================+
+| version            |   0    |      uint32_t     | Boot Manifest version                        |
++--------------------+--------+-------------------+----------------------------------------------+
+| padding            |   4    |      uint32_t     | Reserved, set to 0                           |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_data          |   8    |     uintptr_t     | Pointer to Platform Data section             |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_dram          |   16   |    memory_info    | NS DRAM Layout Info structure                |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_console       |   40   |   console_list    | List of consoles available to RMM            |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_ncoh_region   |   64   |    memory_info    | Device non-coherent ranges Info structure    |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_coh_region    |   88   |    memory_info    | Device coherent ranges Info structure        |
++--------------------+--------+-------------------+----------------------------------------------+
 
-.. _ns_dram_info_struct:
+.. _memory_info_struct:
 
-NS DRAM Layout Info structure
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Memory Info structure
+~~~~~~~~~~~~~~~~~~~~~~
 
-NS DRAM Layout Info structure contains information about platform Non-secure
-DRAM layout. The members of this structure are shown in the table below:
+Memory Info structure contains information about platform memory layout.
+The members of this structure are shown in the table below:
 
 +-----------+--------+----------------+----------------------------------------+
 |   Name    | Offset |     Type       |               Description              |
 +===========+========+================+========================================+
-| num_banks |   0    |   uint64_t     | Number of NS DRAM banks                |
+| num_banks |   0    |   uint64_t     | Number of memory banks/device regions  |
 +-----------+--------+----------------+----------------------------------------+
-| banks     |   8    | ns_dram_bank * | Pointer to 'ns_dram_bank'[] array      |
+| banks     |   8    |  memory_bank * | Pointer to 'memory_bank'[] array       |
 +-----------+--------+----------------+----------------------------------------+
 | checksum  |   16   |   uint64_t     | Checksum                               |
 +-----------+--------+----------------+----------------------------------------+
 
 Checksum is calculated as two's complement sum of 'num_banks', 'banks' pointer
-and DRAM banks data array pointed by it.
+and memory banks data array pointed by it.
 
-.. _ns_dram_bank_struct:
+.. _memory_bank_struct:
 
-NS DRAM Bank structure
-~~~~~~~~~~~~~~~~~~~~~~
+Memory Bank/Device region structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-NS DRAM Bank structure contains information about each Non-secure DRAM bank:
+Memory Bank structure contains information about each memory bank/device region:
 
-+-----------+--------+----------------+----------------------------------------+
-|   Name    | Offset |     Type       |               Description              |
-+===========+========+================+========================================+
-|   base    |   0    |   uintptr_t    | Base address                           |
-+-----------+--------+----------------+----------------------------------------+
-|   size    |   8    |   uint64_t     | Size of bank in bytes                  |
-+-----------+--------+----------------+----------------------------------------+
++-----------+--------+----------------+--------------------------------------------+
+|   Name    | Offset |     Type       |                Description                 |
++===========+========+================+============================================+
+|   base    |   0    |   uintptr_t    | Base address                               |
++-----------+--------+----------------+--------------------------------------------+
+|   size    |   8    |   uint64_t     | Size of memory bank/device region in bytes |
++-----------+--------+----------------+--------------------------------------------+
 
 .. _console_list_struct:
 
@@ -784,15 +788,15 @@
 Console List structure contains information about the available consoles for RMM.
 The members of this structure are shown in the table below:
 
-+--------------+--------+----------------+----------------------------------------+
-|   Name       | Offset |     Type       |               Description              |
-+==============+========+================+========================================+
-| num_consoles |   0    |   uint64_t     | Number of consoles                     |
-+--------------+--------+----------------+----------------------------------------+
-| consoles     |   8    | console_info * | Pointer to 'console_info'[] array      |
-+--------------+--------+----------------+----------------------------------------+
-| checksum     |   16   |   uint64_t     | Checksum                               |
-+--------------+--------+----------------+----------------------------------------+
++--------------+--------+----------------+-------------------------------------+
+|   Name       | Offset |     Type       |               Description           |
++==============+========+================+=====================================+
+| num_consoles |   0    |   uint64_t     | Number of consoles                  |
++--------------+--------+----------------+-------------------------------------+
+| consoles     |   8    | console_info * | Pointer to 'console_info'[] array   |
++--------------+--------+----------------+-------------------------------------+
+| checksum     |   16   |   uint64_t     | Checksum                            |
++--------------+--------+----------------+-------------------------------------+
 
 Checksum is calculated as two's complement sum of 'num_consoles', 'consoles'
 pointer and the consoles array pointed by it.
@@ -804,28 +808,28 @@
 
 Console Info structure contains information about each Console available to RMM.
 
-+-----------+--------+---------------+----------------------------------------+
-|   Name    | Offset |     Type      |               Description              |
-+===========+========+===============+========================================+
-| base      |   0    |   uintptr_t   | Console Base address                   |
-+-----------+--------+---------------+----------------------------------------+
-| map_pages |   8    |   uint64_t    | Num of pages to map for console MMIO   |
-+-----------+--------+---------------+----------------------------------------+
-| name      |   16   |   char[]      | Name of console                        |
-+-----------+--------+---------------+----------------------------------------+
-| clk_in_hz |   24   |   uint64_t    | UART clock (in hz) for console         |
-+-----------+--------+---------------+----------------------------------------+
-| baud_rate |   32   |   uint64_t    | Baud rate                              |
-+-----------+--------+---------------+----------------------------------------+
-| flags     |   40   |   uint64_t    | Additional flags (RES0)                |
-+-----------+--------+---------------+----------------------------------------+
++-----------+--------+---------------+-----------------------------------------+
+|   Name    | Offset |     Type      |               Description               |
++===========+========+===============+=========================================+
+| base      |   0    |   uintptr_t   | Console Base address                    |
++-----------+--------+---------------+-----------------------------------------+
+| map_pages |   8    |   uint64_t    | Num of pages to map for console MMIO    |
++-----------+--------+---------------+-----------------------------------------+
+| name      |   16   |   char[8]     | Name of console                         |
++-----------+--------+---------------+-----------------------------------------+
+| clk_in_hz |   24   |   uint64_t    | UART clock (in Hz) for console          |
++-----------+--------+---------------+-----------------------------------------+
+| baud_rate |   32   |   uint64_t    | Baud rate                               |
++-----------+--------+---------------+-----------------------------------------+
+| flags     |   40   |   uint64_t    | Additional flags (RES0)                 |
++-----------+--------+---------------+-----------------------------------------+
 
 .. _el3_token_sign_request_struct:
 
 EL3 Token Sign Request structure
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-This structure represents a realm attestation toekn signing request.
+This structure represents a realm attestation token signing request.
 
 +-------------+--------+---------------+-----------------------------------------+
 |   Name      | Offset |     Type      |               Description               |
diff --git a/fdts/fvp-base-psci-common.dtsi b/fdts/fvp-base-psci-common.dtsi
index 583bba7..ff3a6ba 100644
--- a/fdts/fvp-base-psci-common.dtsi
+++ b/fdts/fvp-base-psci-common.dtsi
@@ -7,7 +7,7 @@
  *
  * RTSM_VE_AEMv8A.lisa
  *
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -249,4 +249,38 @@
 				<0 0 44 &gic 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
 				<0 0 46 &gic 0 GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
 	};
+
+#if (ENABLE_RME == 1)
+	pci: pci@40000000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		compatible = "pci-host-ecam-generic";
+		device_type = "pci";
+		reg = <0x0 0x40000000 0x0 0x10000000>;
+		ranges = <0x2000000 0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>,
+			 <0x2000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
+		interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &gic 0 0 GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &gic 0 0 GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &gic 0 0 GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+		msi-map = <0x0 &its 0x0 0x10000>;
+		iommu-map = <0x0 &smmu 0x0 0x10000>;
+		dma-coherent;
+	};
+
+	smmu: iommu@2b400000 {
+		compatible = "arm,smmu-v3";
+		reg = <0x0 0x2b400000 0x0 0x100000>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
+			     <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
+		dma-coherent;
+		#iommu-cells = <1>;
+		msi-parent = <&its 0x10000>;
+	};
+#endif /* ENABLE_RME */
 };
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index de08f1d..7f6af59 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -49,6 +49,8 @@
 
 int fdtw_find_or_add_subnode(void *fdt, int parentoffset, const char *name);
 
+uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells);
+
 static inline uint32_t fdt_blob_size(const void *dtb)
 {
 	const uint32_t *dtb_header = (const uint32_t *)dtb;
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 55b44b1..073c157 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -246,6 +246,9 @@
 /* Number of DRAM banks */
 #define ARM_DRAM_NUM_BANKS		2UL
 
+/* Number of PCIe memory regions */
+#define ARM_PCI_NUM_REGIONS		2UL
+
 #define ARM_IRQ_SEC_PHY_TIMER		29
 
 #define ARM_IRQ_SEC_SGI_0		8
diff --git a/include/services/rmm_core_manifest.h b/include/services/rmm_core_manifest.h
index 6b57267..2d6e71f 100644
--- a/include/services/rmm_core_manifest.h
+++ b/include/services/rmm_core_manifest.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,7 +14,7 @@
 #include <lib/cassert.h>
 
 #define RMMD_MANIFEST_VERSION_MAJOR		U(0)
-#define RMMD_MANIFEST_VERSION_MINOR		U(3)
+#define RMMD_MANIFEST_VERSION_MINOR		U(4)
 
 #define RMM_CONSOLE_MAX_NAME_LEN		U(8)
 
@@ -37,29 +37,29 @@
 #define RMMD_GET_MANIFEST_VERSION_MINOR(_version)		\
 	(_version & 0xFFFF)
 
-/* NS DRAM bank structure */
-struct ns_dram_bank {
+/* Memory bank/device region structure */
+struct memory_bank {
 	uintptr_t base;			/* Base address */
-	uint64_t size;			/* Size of bank */
+	uint64_t size;			/* Size of memory bank/device region */
 };
 
-CASSERT(offsetof(struct ns_dram_bank, base) == 0UL,
+CASSERT(offsetof(struct memory_bank, base) == 0UL,
 			rmm_manifest_base_unaligned);
-CASSERT(offsetof(struct ns_dram_bank, size) == 8UL,
+CASSERT(offsetof(struct memory_bank, size) == 8UL,
 			rmm_manifest_size_unaligned);
 
-/* NS DRAM layout info structure */
-struct ns_dram_info {
-	uint64_t num_banks;		/* Number of NS DRAM banks */
-	struct ns_dram_bank *banks;	/* Pointer to ns_dram_bank[] */
-	uint64_t checksum;		/* Checksum of ns_dram_info data */
+/* Memory/device region layout info structure */
+struct memory_info {
+	uint64_t num_banks;		/* Number of memory banks/device regions */
+	struct memory_bank *banks;	/* Pointer to memory_bank[] */
+	uint64_t checksum;		/* Checksum of memory_info data */
 };
 
-CASSERT(offsetof(struct ns_dram_info, num_banks) == 0UL,
+CASSERT(offsetof(struct memory_info, num_banks) == 0UL,
 			rmm_manifest_num_banks_unaligned);
-CASSERT(offsetof(struct ns_dram_info, banks) == 8UL,
+CASSERT(offsetof(struct memory_info, banks) == 8UL,
 			rmm_manifest_dram_data_unaligned);
-CASSERT(offsetof(struct ns_dram_info, checksum) == 16UL,
+CASSERT(offsetof(struct memory_info, checksum) == 16UL,
 			rmm_manifest_checksum_unaligned);
 
 /* Console info structure */
@@ -98,13 +98,18 @@
 CASSERT(offsetof(struct console_list, checksum) == 16UL,
 			rmm_manifest_console_list_checksum);
 
-/* Boot manifest core structure as per v0.3 */
+/* Boot manifest core structure as per v0.4 */
 struct rmm_manifest {
 	uint32_t version;			/* Manifest version */
 	uint32_t padding;			/* RES0 */
 	uintptr_t plat_data;			/* Manifest platform data */
-	struct ns_dram_info plat_dram;		/* Platform NS DRAM data (v0.2) */
-	struct console_list plat_console;	/* Platform console list (v0.3) */
+	/* Platform NS DRAM data (v0.2) */
+	struct memory_info plat_dram;
+	/* Platform console list (v0.3) */
+	struct console_list plat_console;
+	/* Platform device address ranges (v0.4) */
+	struct memory_info plat_ncoh_region;
+	struct memory_info plat_coh_region;
 };
 
 CASSERT(offsetof(struct rmm_manifest, version) == 0UL,
@@ -115,5 +120,9 @@
 			rmm_manifest_plat_dram_unaligned);
 CASSERT(offsetof(struct rmm_manifest, plat_console) == 40UL,
 			rmm_manifest_plat_console_unaligned);
+CASSERT(offsetof(struct rmm_manifest, plat_ncoh_region) == 64UL,
+			rmm_manifest_plat_ncoh_region_unaligned);
+CASSERT(offsetof(struct rmm_manifest, plat_coh_region) == 88UL,
+			rmm_manifest_plat_coh_region_unaligned);
 
 #endif /* RMM_CORE_MANIFEST_H */
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,21 +41,30 @@
 	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);
 int fconf_populate_topology(uintptr_t config);
 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;