Merge changes from topic "rd1ae-upstream" into integration

* changes:
  docs(rd1ae): add RD-1 AE documentation
  feat(rd1ae): enabling Trusted Board Boot(TBB) for RD-1 AE
  feat(rd1ae): introduce BL31 for RD-1 AE platform
  feat(rd1ae): add device tree files
  feat(rd1ae): introduce Arm RD-1 AE platform
  build(bl2): enable check for bl2 base overflow assert
  feat(arm): add support for loading CONFIG from BL2
diff --git a/changelog.yaml b/changelog.yaml
index d073a84..5224441 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -272,6 +272,13 @@
           - title: Corstone-1000
             scope: corstone-1000
 
+          - title: Automotive RD
+            scope: automotive_rd
+
+            subsections:
+              - title: RD-1 AE
+                scope: rd1ae
+
       - title: Aspeed
         scope: aspeed
 
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 8bb12ab..4d08a7f 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -594,6 +594,16 @@
 :|G|: `rupsin01`_
 :|F|: plat/arm/board/tc
 
+Arm Automotive RD platform port
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Diego Sueiro <diego.sueiro@arm.com>
+:|G|: `diego-sueiro`_
+:|M|: Peter Hoyes <peter.hoyes@arm.com>
+:|G|: `hoyes`_
+:|M|: Divin Raj <divin.raj@arm.com>
+:|G|: `divin-raj`_
+:|F|: plat/arm/board/automotive_rd
+
 Aspeed platform port
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Chia-Wei Wang <chiawei_wang@aspeedtech.com>
@@ -1041,12 +1051,15 @@
 .. _CJKay: https://github.com/cjkay
 .. _danh-arm: https://github.com/danh-arm
 .. _davidvincze: https://github.com/davidvincze
+.. _diego-sueiro: https://github.com/diego-sueiro
+.. _divin-raj: https://github.com/divin-raj
 .. _etienne-lms: https://github.com/etienne-lms
 .. _glneo: https://github.com/glneo
 .. _gprocopciucnxp: https://github.com/gprocopciucnxp
 .. _grandpaul: https://github.com/grandpaul
 .. _harrisonmutai-arm: https://github.com/harrisonmutai-arm
 .. _hilamirandakuzi1: https://github.com/hilamirandakuzi1
+.. _hoyes: https://github.com/hoyes
 .. _hzhuang1: https://github.com/hzhuang1
 .. _hugues-kambampiana-arm: https://github.com/hugueskamba
 .. _JackyBai: https://github.com/JackyBai
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index e1b3ef0..afbb157 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -16,6 +16,12 @@
    should match the frame used by the Non-Secure image (normally the Linux
    kernel). Default is true (access to the frame is allowed).
 
+-  ``ARM_FW_CONFIG_LOAD_ENABLE``: Boolean option to enable the loading of
+   FW_CONFIG device trees from the Firmware Image Package (FIP). When enabled,
+   BL2 calls the platform specific function `arm_bl2_el3_plat_config_load`.
+   This function is responsible for loading, parsing, and validating the
+   FW_CONFIG device trees from the FIP. The option depends on RESET_TO_BL2.
+
 -  ``ARM_DISABLE_TRUSTED_WDOG``: boolean option to disable the Trusted Watchdog.
    By default, Arm platforms use a watchdog to trigger a system reset in case
    an error is encountered during the boot process (for example, when an image
diff --git a/docs/plat/arm/automotive_rd/index.rst b/docs/plat/arm/automotive_rd/index.rst
new file mode 100644
index 0000000..d0db6ac
--- /dev/null
+++ b/docs/plat/arm/automotive_rd/index.rst
@@ -0,0 +1,50 @@
+RD-1 AE (Kronos) Platform
+=========================
+
+Some of the features of the RD-1 AE platform referenced in TF-A include:
+
+- Neoverse-V3AE, Arm9.2-A application processor (64-bit mode)
+- A GICv4-compatible GIC-720AE
+
+Further information on RD1-AE is available at `rd1ae`_
+
+Boot Sequence
+-------------
+
+BL2 –> BL31 –> BL33
+
+The boot process starts from RSE (Runtime Security Engine) that loads the BL2 image
+and signals the System Control Processor (SCP) to power up the Application Processor (AP).
+The AP then runs BL2, which loads the rest of the images, including the runtime firmware
+BL31, and proceeds to execute it. Finally, it passes control to the non-secure world
+BL33 (u-boot).
+
+BL2 performs the actions described in the `Trusted Board Boot (TBB)`_ document.
+
+Build Procedure (TF-A only)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-  Obtain `Arm toolchain`_ and set the CROSS_COMPILE environment variable to
+   point to the toolchain folder.
+
+-  Build TF-A:
+
+   .. code:: shell
+
+      make \
+      PLAT=rd1ae \
+      MBEDTLS_DIR=<mbedtls_dir> \
+      ARCH=aarch64 \
+      CREATE_KEYS=1 \
+      GENERATE_COT=1 \
+      TRUSTED_BOARD_BOOT=1 \
+      COT=tbbr \
+      ARM_ROTPK_LOCATION=devel_rsa \
+      ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
+      BL33=<path to u-boot binary> \
+
+*Copyright (c) 2024, Arm Limited. All rights reserved.*
+
+.. _Arm Toolchain: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads
+.. _rd1ae: https://developer.arm.com/Tools%20and%20Software/Arm%20Reference%20Design-1%20AE
+.. _Trusted Board Boot (TBB): https://trustedfirmware-a.readthedocs.io/en/latest/design/trusted-board-boot.html
diff --git a/docs/plat/arm/index.rst b/docs/plat/arm/index.rst
index 2f68522..35c0c59 100644
--- a/docs/plat/arm/index.rst
+++ b/docs/plat/arm/index.rst
@@ -14,6 +14,7 @@
    arm-build-options
    morello/index
    corstone1000/index
+   automotive_rd/index
 
 This chapter holds documentation related to Arm's development platforms,
 including both software models (FVPs) and hardware development boards
@@ -21,4 +22,4 @@
 
 --------------
 
-*Copyright (c) 2019-2021, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
diff --git a/fdts/rd1ae.dts b/fdts/rd1ae.dts
new file mode 100644
index 0000000..3060b5a
--- /dev/null
+++ b/fdts/rd1ae.dts
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	model = "RD-1 AE";
+	compatible = "arm,rd1ae", "arm,neoverse";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	chosen {
+		stdout-path = &soc_serial0;
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu1: cpu@10000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x10000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu2: cpu@20000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x20000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu3: cpu@30000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x30000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu4: cpu@40000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x40000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu5: cpu@50000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x50000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu6: cpu@60000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x60000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu7: cpu@70000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x70000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu8: cpu@80000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x80000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu9: cpu@90000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0x90000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu10: cpu@a0000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0xa0000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu11: cpu@b0000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0xb0000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu12: cpu@c0000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0xc0000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu13: cpu@d0000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0xd0000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu14: cpu@e0000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0xe0000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+		cpu15: cpu@f0000 {
+			device_type = "cpu";
+			compatible = "arm,neoverse-v3";
+			reg = <0x0 0xf0000>;
+			enable-method = "psci";
+			i-cache-size = <0x10000>;
+			i-cache-line-size = <0x40>;
+			i-cache-sets = <0x100>;
+			d-cache-size = <0x10000>;
+			d-cache-line-size = <0x40>;
+			d-cache-sets = <0x100>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		/*
+		 * 0x7fc0 0000 - 0x7fff ffff : BL32
+		 * 0x7fbf 0000 - 0x7fbf ffff : FFA_SHARED_MM_BUF
+		 */
+		reg = <0x00000000 0x80000000 0 0x7fbf0000>,
+			  <0x00000080 0x80000000 0 0x80000000>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	soc_clk24mhz: clk24mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "refclk24mhz";
+	};
+
+	soc_refclk1mhz: refclk1mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <1000000>;
+		clock-output-names = "refclk1mhz";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller@30000000 {
+			compatible = "arm,gic-v3";
+			reg = <0x0 0x30000000 0 0x10000>,	// GICD
+				  <0x0 0x301c0000 0 0x8000000>;	// GICR
+			#interrupt-cells = <3>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			interrupt-controller;
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+			its1: msi-controller@30040000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x30040000 0x0 0x40000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+			its2: msi-controller@30080000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x30080000 0x0 0x40000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+			its3: msi-controller@300c0000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x300c0000 0x0 0x40000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+			its4: msi-controller@30100000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x30100000 0x0 0x40000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+			its5: msi-controller@30140000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x30140000 0x0 0x40000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+			its6: msi-controller@30180000 {
+				compatible = "arm,gic-v3-its";
+				reg = <0x0 0x30180000 0x0 0x40000>;
+				msi-controller;
+				#msi-cells = <1>;
+			};
+		};
+
+		soc_serial0: serial@2a400000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0x2a400000 0x0 0x10000>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&soc_clk24mhz>, <&soc_clk24mhz>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		watchdog@2a440000 {
+			compatible = "arm,sbsa-gwdt";
+			reg = <0x0 0x2a440000 0 0x1000>,
+				  <0x0 0x2a450000 0 0x1000>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		rtc@c170000 {
+			compatible = "arm,pl031", "arm,primecell";
+			reg = <0x0 0x0c170000 0x0 0x10000>;
+			interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&soc_clk24mhz>;
+			clock-names = "apb_pclk";
+		};
+
+		virtio-net@c150000 {
+			compatible = "virtio,mmio";
+			reg = <0x0 0xc150000 0x0 0x200>;
+			interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		virtio-block@c130000 {
+			compatible = "virtio,mmio";
+			reg = <0x0 0xc130000 0x0 0x200>;
+			interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		virtio-rng@c140000 {
+			compatible = "virtio,mmio";
+			reg = <0x0 0xc140000 0x0 0x200>;
+			interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pci@4000000000 {
+			#address-cells = <0x03>;
+			#size-cells = <0x02>;
+			compatible = "pci-host-ecam-generic";
+			device_type = "pci";
+			bus-range = <0x00 0x11>;
+			reg = <0x40 0x00 0x00 0x04000000>;
+			ranges = <0x43000000 0x40 0x40000000 0x40 0x40000000 0x10 0x00000000
+				  0x02000000 0x00 0x60000000 0x00 0x60000000 0x00 0x08000000
+				  0x01000000 0x00 0x00 0x00 0x77800000 0x00 0x800000>;
+			msi-map = <0x00 &its1 0x40000 0x10000>;
+			iommu-map = <0x00 &smmu 0x40000 0x10000>;
+			dma-coherent;
+		};
+
+		smmu: iommu@280000000 {
+			compatible = "arm,smmu-v3";
+			reg = <0x2 0x80000000 0x0 0x100000>;
+			dma-coherent;
+			#iommu-cells = <1>;
+			interrupts = <1 210 1>,
+				     <1 211 1>,
+				     <1 212 1>,
+				     <1 213 1>;
+			interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
+			msi-parent = <&its1 0x10000>;
+		};
+
+		sysreg: sysreg@c010000 {
+			compatible = "arm,vexpress-sysreg";
+			reg = <0x0 0xc010000 0x0 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		fixed_3v3: v2m-3v3@c011000 {
+			compatible = "regulator-fixed";
+			reg = <0x0 0xc011000 0x0 0x1000>;
+			regulator-name = "3V3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		mmci@c050000 {
+			compatible = "arm,pl180", "arm,primecell";
+			reg = <0x0 0xc050000 0x0 0x1000>;
+			interrupts = <0 0x8B 0x4>,
+				     <0 0x8C 0x4>;
+			cd-gpios = <&sysreg 0 0>;
+			wp-gpios = <&sysreg 1 0>;
+			bus-width = <8>;
+			max-frequency = <12000000>;
+			vmmc-supply = <&fixed_3v3>;
+			clocks = <&soc_clk24mhz>, <&soc_clk24mhz>;
+			clock-names = "mclk", "apb_pclk";
+		};
+
+	};
+
+	psci {
+		compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+		method = "smc";
+		cpu_suspend = <0xc4000001>;
+		cpu_off = <0x84000002>;
+		cpu_on = <0x84000003>;
+	};
+
+};
diff --git a/fdts/tbbr_cot_descriptors.dtsi b/fdts/tbbr_cot_descriptors.dtsi
index b3c0ca7..253297f 100644
--- a/fdts/tbbr_cot_descriptors.dtsi
+++ b/fdts/tbbr_cot_descriptors.dtsi
@@ -195,6 +195,12 @@
 			hash = <&hw_config_hash>;
 		};
 
+		fw_config {
+			image-id = <FW_CONFIG_ID>;
+			parent = <&trusted_boot_fw_cert>;
+			hash = <&fw_config_hash>;
+		};
+
 		scp_bl2_image {
 			image-id = <SCP_BL2_IMAGE_ID>;
 			parent = <&scp_fw_content_cert>;
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 83a5cd2..c3756bf 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -262,6 +262,9 @@
 /* BL2 at EL3 functions */
 void arm_bl2_el3_early_platform_setup(void);
 void arm_bl2_el3_plat_arch_setup(void);
+#if ARM_FW_CONFIG_LOAD_ENABLE
+void arm_bl2_el3_plat_config_load(void);
+#endif /* ARM_FW_CONFIG_LOAD_ENABLE */
 
 /* BL2U utility functions */
 void arm_bl2u_early_platform_setup(struct meminfo *mem_layout,
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/fdts/rd1ae_fw_config.dts b/plat/arm/board/automotive_rd/platform/rd1ae/fdts/rd1ae_fw_config.dts
new file mode 100644
index 0000000..53cd3b0
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/fdts/rd1ae_fw_config.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "fconf,dyn_cfg-dtb_registry";
+
+		hw-config {
+			load-address = <0x0 0x83000000>;
+			max-size = <0x8000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+};
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/include/plat_macros.S b/plat/arm/board/automotive_rd/platform/rd1ae/include/plat_macros.S
new file mode 100644
index 0000000..8efe8ac
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/include/plat_macros.S
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+	.macro plat_crash_print_regs
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/include/platform_def.h b/plat/arm/board/automotive_rd/platform/rd1ae/include/platform_def.h
new file mode 100644
index 0000000..44c8ee3
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/include/platform_def.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+/* These are referenced by arm_def.h #included next, so #define first. */
+#define PLAT_ARM_TRUSTED_SRAM_BASE		UL(0x0)
+
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/css/common/css_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_CORE_COUNT			U(16)
+#define PLAT_ARM_CLUSTER_COUNT			U(16)
+#define PLAT_MAX_CPUS_PER_CLUSTER		U(1)
+#define PLAT_MAX_PE_PER_CPU			U(1)
+
+#define PLATFORM_STACK_SIZE			UL(0x1000)
+
+/* BL1 is not supported */
+#define PLAT_ARM_TRUSTED_ROM_BASE		UL(0x0)
+#define PLAT_ARM_TRUSTED_ROM_SIZE		UL(0x0)
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE		UL(0x00080000)
+
+/* USE_ROMLIB is not supported */
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE		U(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE		U(0)
+
+/* Defined based on actual binary sizes */
+#define PLAT_ARM_MAX_BL1_RW_SIZE		0x0
+#define PLAT_ARM_MAX_BL2_SIZE			0x20000
+#define PLAT_ARM_MAX_BL31_SIZE			0x70000
+
+#define PLAT_ARM_DRAM2_BASE			ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE			ULL(0x180000000)
+
+#define PLAT_CSS_MHU_BASE			UL(0x2A920000)
+#define PLAT_ARM_NSTIMER_FRAME_ID		U(0)
+
+#define SOC_CSS_SEC_UART_BASE			UL(0x2A410000)
+#define SOC_CSS_NSEC_UART_BASE			UL(0x2A400000)
+#define SOC_CSS_UART_SIZE			UL(0x10000)
+#define SOC_CSS_UART_CLK_IN_HZ			UL(7372800)
+#define PLAT_ARM_BOOT_UART_BASE			SOC_CSS_SEC_UART_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ		SOC_CSS_UART_CLK_IN_HZ
+#define PLAT_ARM_RUN_UART_BASE			SOC_CSS_SEC_UART_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ		SOC_CSS_UART_CLK_IN_HZ
+#define PLAT_ARM_CRASH_UART_BASE		SOC_CSS_SEC_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ		SOC_CSS_UART_CLK_IN_HZ
+
+/* Physical and virtual address space limits for MMU */
+#define PLAT_PHY_ADDR_SPACE_SIZE		(1ULL << 42)
+#define PLAT_VIRT_ADDR_SPACE_SIZE		(1ULL << 42)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE			UL(0x30000000)
+#define PLAT_ARM_GICR_BASE			UL(0x301C0000)
+#define PLAT_ARM_GICC_BASE			UL(0x2C000000)
+#define PLAT_ARM_G1S_IRQ_PROPS(grp)		CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp)		ARM_G0_IRQ_PROPS(grp)
+
+/* Virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME		UL(0xC0000000)
+
+/* Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE			UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT		UL(100)
+
+#define V2M_SYS_LED_SS_SHIFT			U(0)
+#define V2M_SYS_LED_EL_SHIFT			U(1)
+#define V2M_SYS_LED_EC_SHIFT			U(3)
+
+#define V2M_SYS_LED_SS_MASK			U(0x01)
+#define V2M_SYS_LED_EL_MASK			U(0x03)
+#define V2M_SYS_LED_EC_MASK			U(0x1f)
+
+#define V2M_SYSREGS_BASE			UL(0x0C010000)
+#define V2M_SYS_LED				U(0x8)
+
+#define PLAT_ARM_SCMI_CHANNEL_COUNT		U(1)
+#define CSS_SYSTEM_PWR_DMN_LVL			ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL				ARM_PWR_LVL1
+
+#define MAX_IO_DEVICES				U(3)
+#define MAX_IO_HANDLES				U(4)
+
+#ifdef IMAGE_BL2
+#define PLAT_ARM_MMAP_ENTRIES			U(5)
+#else
+#define PLAT_ARM_MMAP_ENTRIES			U(6)
+#endif
+#define MAX_XLAT_TABLES				U(6)
+
+#define V2M_FLASH0_BASE				UL(0x08000000)
+#define V2M_FLASH0_SIZE				UL(0x04000000)
+#define V2M_FLASH_BLOCK_SIZE			UL(0x00040000)	/* 256 KB */
+#define PLAT_ARM_FLASH_IMAGE_BASE		V2M_FLASH0_BASE
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE		(V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#define PLAT_FW_CONFIG_MAX_SIZE			(ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE)
+#define PLAT_FW_CONFIG_BASE			ARM_FW_CONFIG_BASE
+
+/* RD1AE-specific memory mappings */
+#define RD1AE_EXTERNAL_FLASH	MAP_REGION_FLAT(V2M_FLASH0_BASE, \
+						V2M_FLASH0_SIZE, \
+						MT_DEVICE | MT_RO | \
+						MT_SECURE)
+
+#define RD1AE_MAP_NS_DRAM1	MAP_REGION_FLAT(ARM_DRAM1_BASE,	\
+						ARM_DRAM1_SIZE,	\
+						MT_MEMORY | MT_RW | \
+						MT_NS)
+
+#define RD1AE_DEVICE_BASE	(0x20000000)
+#define RD1AE_DEVICE_SIZE	(0x20000000)
+#define RD1AE_MAP_DEVICE	MAP_REGION_FLAT(RD1AE_DEVICE_BASE, \
+						RD1AE_DEVICE_SIZE, \
+						MT_DEVICE | MT_RW | \
+						MT_SECURE)
+
+#define SOC_PLATFORM_PERIPH_BASE	UL(0x0E000000)
+#define SOC_PLATFORM_PERIPH_SIZE	UL(0x02000000)
+#define SOC_PLATFORM_PERIPH_MAP_DEVICE	MAP_REGION_FLAT(SOC_PLATFORM_PERIPH_BASE, \
+							SOC_PLATFORM_PERIPH_SIZE, \
+							MT_DEVICE | MT_RW | MT_SECURE)
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE_OFFSET	UL(0x00E70000)
+#define TFW_NVCTR_BASE_OFFSET		0x0000
+#define NTFW_CTR_BASE_OFFSET		0x0004
+#define SOC_TRUSTED_NVCTR_BASE		(SOC_PLATFORM_PERIPH_BASE + TRUSTED_NVCTR_BASE_OFFSET)
+#define TFW_NVCTR_BASE			(SOC_TRUSTED_NVCTR_BASE + TFW_NVCTR_BASE_OFFSET)
+#define TFW_NVCTR_SIZE			U(4)
+#define NTFW_CTR_BASE			(SOC_TRUSTED_NVCTR_BASE + NTFW_CTR_BASE_OFFSET)
+#define NTFW_CTR_SIZE			U(4)
+
+/*******************************************************************************
+ * Memprotect definitions
+ ******************************************************************************/
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR	(V2M_FLASH0_BASE + \
+					V2M_FLASH0_SIZE - \
+					V2M_FLASH_BLOCK_SIZE)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/include/rd1ae_helpers.S b/plat/arm/board/automotive_rd/platform/rd1ae/include/rd1ae_helpers.S
new file mode 100644
index 0000000..32260ef
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/include/rd1ae_helpers.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.globl	plat_arm_calc_core_pos
+
+	/* ---------------------------------------------------------------------
+	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+	 *
+	 * Function to calculate the core position on rd1ae.
+	 *
+	 * (ClusterId * PLAT_MAX_CPUS_PER_CLUSTER * PLAT_MAX_PE_PER_CPU) +
+	 * (CPUId * PLAT_MAX_PE_PER_CPU) +
+	 * ThreadId
+	 *
+	 * which can be simplified as:
+	 *
+	 * ((ClusterId * PLAT_MAX_CPUS_PER_CLUSTER + CPUId) * PLAT_MAX_PE_PER_CPU)
+	 * + ThreadId
+	 * ---------------------------------------------------------------------
+	 */
+func plat_arm_calc_core_pos
+	mov	x4, x0
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx    x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx    x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx    x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx    x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov     x4, #PLAT_ARM_CLUSTER_COUNT
+	madd    x2, x3, x4, x2
+	mov     x4, #PLAT_MAX_CPUS_PER_CLUSTER
+	madd    x1, x2, x4, x1
+	mov     x4, #PLAT_MAX_PE_PER_CPU
+	madd    x0, x1, x4, x0
+	ret
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
new file mode 100644
index 0000000..35cd8a1
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
@@ -0,0 +1,88 @@
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# RD1AE (Kronos) platform.
+$(info Platform ${PLAT} is (kronos) specific.)
+
+RD1AE_BASE		=	plat/arm/board/automotive_rd/platform/rd1ae
+
+PLAT_INCLUDES		+=	-I${RD1AE_BASE}/include/
+
+override ARM_FW_CONFIG_LOAD_ENABLE	:=	1
+override ARM_PLAT_MT			:=	1
+override ARM_RECOM_STATE_ID_ENC		:=	1
+override CSS_LOAD_SCP_IMAGES		:=	0
+override CTX_INCLUDE_AARCH32_REGS	:=	0
+override ENABLE_SVE_FOR_NS		:=	1
+override ENABLE_SVE_FOR_SWD		:=	1
+override NEED_BL1			:=	0
+override NEED_BL2U			:=	0
+override PSCI_EXTENDED_STATE_ID		:=	1
+
+ARM_ARCH_MAJOR				:=	9
+ARM_ARCH_MINOR				:=	2
+CSS_USE_SCMI_SDS_DRIVER			:=	1
+ENABLE_FEAT_AMU				:=	1
+ENABLE_FEAT_ECV				:=	1
+ENABLE_FEAT_FGT				:=	1
+ENABLE_FEAT_MTE2			:=	1
+ENABLE_MPAM_FOR_LOWER_ELS		:=	1
+GIC_ENABLE_V4_EXTN			:=	1
+GICV3_SUPPORT_GIC600			:=	1
+HW_ASSISTED_COHERENCY			:=	1
+PLAT_MHU_VERSION			:=	1
+RESET_TO_BL2				:=	1
+SVE_VECTOR_LEN				:=	128
+USE_COHERENT_MEM			:=	0
+
+RD1AE_CPU_SOURCES	:=	lib/cpus/aarch64/neoverse_v3.S
+
+include drivers/arm/gic/v3/gicv3.mk
+RD1AE_GIC_SOURCES	:=	${GICV3_SOURCES}	\
+				plat/common/plat_gicv3.c	\
+				plat/arm/common/arm_gicv3.c
+
+PLAT_BL_COMMON_SOURCES	+=	${RD1AE_BASE}/rd1ae_plat.c	\
+				${RD1AE_BASE}/include/rd1ae_helpers.S
+
+BL2_SOURCES	+=	${RD1AE_CPU_SOURCES}	\
+			${RD1AE_BASE}/rd1ae_err.c	\
+			${RD1AE_BASE}/rd1ae_bl2_mem_params_desc.c	\
+			lib/utils/mem_region.c	\
+			plat/arm/common/arm_nor_psci_mem_protect.c	\
+			drivers/arm/sbsa/sbsa.c
+
+BL31_SOURCES	+=	${RD1AE_CPU_SOURCES}	\
+			${RD1AE_GIC_SOURCES}	\
+			${RD1AE_BASE}/rd1ae_bl31_setup.c	\
+			${RD1AE_BASE}/rd1ae_topology.c	\
+			drivers/cfi/v2m/v2m_flash.c	\
+			lib/utils/mem_region.c	\
+			plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+BL2_SOURCES	+=	${RD1AE_BASE}/rd1ae_tbb.c
+endif
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES	+=	${RD1AE_BASE}/fdts/${PLAT}_fw_config.dts	\
+			fdts/${PLAT}.dts
+
+FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+HW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config,${HW_CONFIG}))
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+FIP_BL2_ARGS	:=	tb-fw
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
+endif
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_bl2_mem_params_desc.c b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_bl2_mem_params_desc.c
new file mode 100644
index 0000000..30cc90f
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_bl2_mem_params_desc.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	/* Fill BL31 related information */
+	{
+		.image_id = BL31_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+			VERSION_2, entry_point_info_t,
+			SECURE | EXECUTABLE | EP_FIRST_EXE),
+		.ep_info.pc = BL31_BASE,
+		.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+			DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+		.ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL,
+#endif
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+			VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+		.image_info.image_base = BL31_BASE,
+		.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+	/* Fill HW_CONFIG related information */
+	{
+		.image_id = HW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+			VERSION_2, entry_point_info_t,
+			NON_SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+			VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+	/* Fill BL33 related information */
+	{
+		.image_id = BL33_IMAGE_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+			VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+		.ep_info.pc = PLAT_ARM_NS_IMAGE_BASE,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+			VERSION_2, image_info_t, 0),
+		.image_info.image_base = PLAT_ARM_NS_IMAGE_BASE,
+		.image_info.image_max_size = ARM_DRAM1_BASE + ARM_DRAM1_SIZE
+			- PLAT_ARM_NS_IMAGE_BASE,
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_bl31_setup.c b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_bl31_setup.c
new file mode 100644
index 0000000..ce7bad7
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_bl31_setup.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+
+static scmi_channel_plat_info_t plat_rd_scmi_info[] = {
+	{
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + MHU_V3_SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhu_ring_doorbell,
+	},
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(unsigned int channel_id)
+{
+	return &plat_rd_scmi_info[channel_id];
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_err.c b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_err.c
new file mode 100644
index 0000000..6254473
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_err.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/sbsa.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rd1ae error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+	console_flush();
+
+	sbsa_wdog_refresh(SBSA_SECURE_WDOG_BASE);
+
+	while (1) {
+		wfi();
+	}
+}
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_plat.c b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_plat.c
new file mode 100644
index 0000000..e917330
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_plat.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/sbsa.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	RD1AE_MAP_DEVICE,
+	RD1AE_EXTERNAL_FLASH,
+	SOC_PLATFORM_PERIPH_MAP_DEVICE,
+#if IMAGE_BL2
+	RD1AE_MAP_NS_DRAM1,
+#endif
+	{0}
+};
+
+void plat_arm_secure_wdt_start(void)
+{
+	sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
+
+/*
+ * For rd1ae we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers
+ */
+void plat_arm_interconnect_init(void)
+{
+}
+
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
+
+/*
+ * TZC programming is currently not done.
+ */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_tbb.c b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_tbb.c
new file mode 100644
index 0000000..01fbcce
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_tbb.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	assert(heap_addr != NULL);
+	assert(heap_size != NULL);
+
+	return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm       OBJECT IDENTIFIER,
+ *     parameters      ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm AlgorithmIdentifier,
+ *     digest          OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_topology.c b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_topology.c
new file mode 100644
index 0000000..2533184
--- /dev/null
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/rd1ae_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ *
+ * This descriptor defines the layout of the power domain tree for the RD1AE
+ * platform, which consists of 16 clusters.
+ ******************************************************************************/
+const unsigned char rd1_ae_pd_tree_desc[] = {
+	(PLAT_ARM_CLUSTER_COUNT),
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return rd1_ae_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)),
+};
+
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+	return PLAT_MAX_CPUS_PER_CLUSTER;
+}
diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c
index 01e0db0..869830d 100644
--- a/plat/arm/common/arm_bl2_el3_setup.c
+++ b/plat/arm/common/arm_bl2_el3_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,8 @@
 
 #include <drivers/generic_delay_timer.h>
 #include <drivers/partition/partition.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
@@ -64,6 +66,43 @@
 	generic_delay_timer_init();
 }
 
+#if ARM_FW_CONFIG_LOAD_ENABLE
+/*************************************************************************************
+ * FW CONFIG load function for BL2 when RESET_TO_BL2=1 && ARM_FW_CONFIG_LOAD_ENABLE=1
+ *************************************************************************************/
+void arm_bl2_el3_plat_config_load(void)
+{
+	int ret;
+	const struct dyn_cfg_dtb_info_t *fw_config_info;
+
+	/* Set global DTB info for fixed fw_config information */
+	set_config_info(PLAT_FW_CONFIG_BASE, ~0UL, PLAT_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID);
+
+	/* Fill the device tree information struct with the info from the config dtb */
+	ret = fconf_load_config(FW_CONFIG_ID);
+	if (ret < 0) {
+		ERROR("Loading of FW_CONFIG failed %d\n", ret);
+		plat_error_handler(ret);
+	}
+
+	/*
+	 * FW_CONFIG loaded successfully. Check the FW_CONFIG device tree parsing
+	 * is successful.
+	 */
+	fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+	if (fw_config_info == NULL) {
+		ret = -1;
+		ERROR("Invalid FW_CONFIG address\n");
+		plat_error_handler(ret);
+	}
+	ret = fconf_populate_dtb_registry(fw_config_info->config_addr);
+	if (ret < 0) {
+		ERROR("Parsing of FW_CONFIG failed %d\n", ret);
+		plat_error_handler(ret);
+	}
+}
+#endif /* ARM_FW_CONFIG_LOAD_ENABLE */
+
 /*******************************************************************************
  * Perform the very early platform specific architectural setup here. At the
  * moment this is only initializes the mmu in a quick and dirty way.
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index b5a7db1..90ee70c 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -42,7 +42,7 @@
 #if TRANSFER_LIST
 CASSERT(BL2_BASE >= PLAT_ARM_EL3_FW_HANDOFF_BASE + PLAT_ARM_FW_HANDOFF_SIZE,
 	assert_bl2_base_overflows);
-#else
+#elif !RESET_TO_BL2
 CASSERT(BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl2_base_overflows);
 #endif /* TRANSFER_LIST */
 
@@ -140,6 +140,9 @@
 
 	arm_transfer_list_dyn_cfg_init(secure_tl);
 #else
+#if ARM_FW_CONFIG_LOAD_ENABLE
+	arm_bl2_el3_plat_config_load();
+#endif /* ARM_FW_CONFIG_LOAD_ENABLE */
 	arm_bl2_dyn_cfg_init();
 #endif
 
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 7f0c9cb..2fd993c 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -164,6 +164,25 @@
 	ENABLE_PIE			:=	1
 endif
 
+# On Arm platform, disable ARM_FW_CONFIG_LOAD_ENABLE by default.
+ARM_FW_CONFIG_LOAD_ENABLE		:= 0
+$(eval $(call assert_boolean,ARM_FW_CONFIG_LOAD_ENABLE))
+$(eval $(call add_define,ARM_FW_CONFIG_LOAD_ENABLE))
+
+# In order to enable ARM_FW_CONFIG_LOAD_ENABLE for the Arm platform, the
+# platform should be reset to BL2 (RESET_TO_BL2=1), and FW_CONFIG must be
+# specified.
+ifeq (${ARM_FW_CONFIG_LOAD_ENABLE},1)
+    ifneq (${RESET_TO_BL2},1)
+        $(error RESET_TO_BL2 must be enabled when ARM_FW_CONFIG_LOAD_ENABLE \
+            is enabled)
+    endif
+    ifeq (${FW_CONFIG},)
+        $(error FW_CONFIG must be specified when ARM_FW_CONFIG_LOAD_ENABLE \
+            is enabled)
+    endif
+endif
+
 # Disable GPT parser support, use FIP image by default
 ARM_GPT_SUPPORT			:=	0
 $(eval $(call assert_boolean,ARM_GPT_SUPPORT))
@@ -275,7 +294,7 @@
 ifeq (${JUNO_AARCH32_EL3_RUNTIME},1)
 BL2_SOURCES		+=	plat/arm/common/aarch32/arm_bl2_mem_params_desc.c
 else
-ifneq (${PLAT}, corstone1000)
+ifeq ($(filter $(PLAT), corstone1000 rd1ae),)
 BL2_SOURCES		+=	plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c
 endif
 endif