Merge changes from topic "add_s32g274ardb2_support" into integration

* changes:
  feat(s32g274a): enable BL31 stage
  feat(s32g274a): add S32G274ARDB2 board support
  feat(nxp-drivers): add Linflex driver
diff --git a/changelog.yaml b/changelog.yaml
index aebb792..ad9c9b5 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -504,6 +504,13 @@
                   - title: LS1088AQDS
                     scope: ls1088aqds
 
+          - title: S32G274A
+            scope: s32g274a
+
+            subsections:
+              - title: S32G274ARDB
+                scope: s32g274ardb
+
       - title: QEMU
         scope: qemu
 
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 7753334..1f68927 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -710,6 +710,15 @@
 :|F|: plat/nxp/soc-ls1088a/ls1088ardb
 :|F|: plat/nxp/soc-ls1088a/ls1088aqds
 
+NXP SoC Part S32G274A and its platform port
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
+:|G|: `gprocopciucnxp`_
+:|F|: docs/plat/s32g274a.rst
+:|F|: drivers/nxp/console/linflex_console.S
+:|F|: include/drivers/nxp/console/linflex.h
+:|F|: plat/nxp/s32
+
 QEMU platform port
 ^^^^^^^^^^^^^^^^^^
 :|M|: Jens Wiklander <jens.wiklander@linaro.org>
@@ -983,6 +992,7 @@
 .. _davidvincze: https://github.com/davidvincze
 .. _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
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 702726e..5c1ded0 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -29,6 +29,7 @@
    imx8m
    imx8ulp
    imx9
+   s32g274a
    npcm845x
    nxp/index
    poplar
diff --git a/docs/plat/s32g274a.rst b/docs/plat/s32g274a.rst
new file mode 100644
index 0000000..3aa858e
--- /dev/null
+++ b/docs/plat/s32g274a.rst
@@ -0,0 +1,99 @@
+NXP S32G274A
+============
+
+S32G2 is an NXP vehicle network processor combining ASIL D safety, hardware
+security, high-performance real-time and application processing and network
+acceleration. S32G2 supports the needs of new vehicle architectures:
+service-oriented gateways, domain controllers, zonal processors, safety
+processors and more. It is equipped with 4 Cortex-A53 cores operating at
+1.0GHz.
+
+The TF-A includes support for one single S32G2-based board called S32G274ARDB2.
+The S32G-VNP-RDB2 is a compact, highly optimized and integrated board
+engineering for vehicle service-oriented gateway (SoG), domain control
+applications, high-performance processing, safety and security applications.
+More details about this board can be found at `s32g274ardb2`_.
+
+Boot Flow
+---------
+
+::
+
+   BootROM -> BL2 (SRAM) -> BL31 (SRAM) -> BL33 (DDR - TODO)
+
+.. warning::
+   This boot flow is a preliminary version that will serve as a foundation for
+   upcoming S32G2 contributions. The execution will hang after the BL31 stage
+   due to U-Boot being deployed in SRAM instead of DDR. This issue will be
+   resolved with the addition of the DDR driver.
+
+Code Locations
+--------------
+
+- Downstream TF-A:
+  `link: <https://github.com/nxp-auto-linux/arm-trusted-firmware>`__
+
+- Downstream U-Boot:
+  `link <https://github.com/nxp-auto-linux/u-boot>`__
+
+- Downstream Linux:
+  `link <https://github.com/nxp-auto-linux/linux>`__
+
+How to build
+------------
+
+The port currently available on the S32G274ARDB2 platform is in its initial
+stage. This means that important drivers like DDR and storage are not yet
+available. Consequently, the boot process depends on BootROM to load all TF-A
+stages in SRAM. To create a bootable image, the script below should be used.
+This script makes use of the ``mkimage`` tool, which is part of the U-Boot drop
+for S32G274A SoCs.
+
+.. code:: bash
+
+        #!/bin/bash -xe
+        TF_A="${TF_A:-`pwd`}"
+        UBOOT="${UBOOT:-${TF_A}/../u-boot}"
+        DEBUG="${DEBUG:-1}"
+
+        FIP_BASE="0x34100000"
+
+        if [ "${DEBUG}" -eq "1" ]; then
+                BUILD="debug"
+        else
+                BUILD="release"
+        fi
+
+        BOOT_IMAGE="build/s32g274ardb2/${BUILD}/BOOT_IMAGE.bin"
+        BL2_BIN="build/s32g274ardb2/${BUILD}/bl2.bin"
+        FIP_BIN="build/s32g274ardb2/${BUILD}/fip.bin"
+
+        # Generate bl2, bl31 and fip image
+        make -C "${TF_A}" -j9 'PLAT=s32g274ardb2' \
+                BL33="${UBOOT}/u-boot-nodtb.bin" DEBUG="${DEBUG}" clean
+        make -C "${TF_A}" -j9 'PLAT=s32g274ardb2' \
+                BL33="${UBOOT}/u-boot-nodtb.bin" DEBUG="${DEBUG}" bl2
+        make -C "${TF_A}" -j9 'PLAT=s32g274ardb2' \
+                BL33="${UBOOT}/u-boot-nodtb.bin" DEBUG="${DEBUG}" fip
+
+        # Extract BL2 entry
+        BL2_START="0x$(poetry run memory -p s32g274ardb2 -b debug -f | \
+                                grep BL2 | awk -F'|' '{print $3}' | xargs)"
+        # BL2 bin file size in bytes
+        BL2_SIZE="$(stat -c "%s" "${BL2_BIN}")"
+
+        # Pack bl2.bin and fip.bin by ensuring that the FIP image will start at FIP_BASE
+        cp -vf "${BL2_BIN}" "${BOOT_IMAGE}"
+        dd if="${FIP_BIN}" of="${BOOT_IMAGE}" seek="$((FIP_BASE - BL2_START))" bs=1
+
+        # Build a bootable image by appending the IVT
+        "${UBOOT}/tools/mkimage" \
+                -a "${BL2_START}" \
+                -e "${BL2_START}" \
+                -T s32ccimage \
+                -n "${UBOOT}/u-boot-s32.cfgout" \
+                -d "${BOOT_IMAGE}" \
+                fip.s32
+
+.. _s32g2: https://www.nxp.com/products/processors-and-microcontrollers/s32-automotive-platform/s32g-vehicle-network-processors/s32g2-processors-for-vehicle-networking:S32G2
+.. _s32g274ardb2: https://www.nxp.com/design/design-center/designs/s32g2-vehicle-networking-reference-design:S32G-VNP-RDB2
diff --git a/drivers/nxp/console/console.mk b/drivers/nxp/console/console.mk
index 6174650..5f3c6e3 100644
--- a/drivers/nxp/console/console.mk
+++ b/drivers/nxp/console/console.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2021 NXP
+# Copyright 2021-2024 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -28,8 +28,13 @@
 CONSOLE_SOURCES		:=	drivers/arm/pl011/aarch64/pl011_console.S	\
 				${PLAT_DRIVERS_PATH}/console/console_pl011.c
 else
+ifeq ($(CONSOLE), LINFLEX)
+CONSOLE_SOURCES		:=	${PLAT_DRIVERS_PATH}/console/linflex_console.S
+else
 	$(error -> CONSOLE not set!)
 endif
+
+endif
 endif
 
 ifeq (${BL_COMM_CONSOLE_NEEDED},yes)
diff --git a/drivers/nxp/console/linflex_console.S b/drivers/nxp/console/linflex_console.S
new file mode 100644
index 0000000..abcbb59
--- /dev/null
+++ b/drivers/nxp/console/linflex_console.S
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/libc/errno.h>
+
+#include <asm_macros.S>
+#include <console_macros.S>
+#include <lib/utils_def.h>
+
+#define LDIV_MULTIPLIER		U(16)
+
+#define LINFLEX_LINCR1		(0x0)
+#define LINCR1_INIT		BIT_32(0)
+#define LINCR1_MME		BIT_32(4)
+
+#define LINFLEX_LINSR		(0x8)
+#define LINSR_LINS_INITMODE	(0x00001000)
+#define LINSR_LINS_MASK		(0x0000F000)
+
+#define LINFLEX_UARTCR		(0x10)
+#define UARTCR_ROSE		BIT_32(23)
+
+#define LINFLEX_UARTSR		(0x14)
+#define LINFLEX_LINIBRR		(0x28)
+#define LINFLEX_LINFBRR		(0x24)
+#define LINFLEX_BDRL		(0x38)
+#define LINFLEX_UARTPTO		(0x50)
+
+#define UARTCR_UART		BIT_32(0)
+#define UARTCR_WL0		BIT_32(1)
+#define UARTCR_PC0		BIT_32(3)
+#define UARTCR_TXEN		BIT_32(4)
+#define UARTCR_RXEN		BIT_32(5)
+#define UARTCR_PC1		BIT_32(6)
+#define UARTCR_TFBM		BIT_32(8)
+#define UARTCR_RFBM		BIT_32(9)
+#define UARTCR_OSR_SHIFT	U(24)
+#define UARTCR_OSR_WIDTH	U(4)
+
+#define UARTSR_DTF		BIT_32(1)
+
+/*
+ * "core" functions are low-level implementations that do not require
+ * writable memory and are thus safe to call in BL1 crash context.
+ */
+.globl console_linflex_core_init
+.globl console_linflex_core_putc
+
+.globl console_linflex_register
+.globl console_linflex_putc
+
+/**
+ * uint32_t get_ldiv_mult(uintptr_t baseaddr, uint32_t clock,
+ *                        uint32_t baud, console_t *console,);
+ *
+ * Clobber list : x0 - x6
+ * Out x4: LDIV multiplier
+ */
+func get_ldiv_mult
+	ldr	w4, [x0, LINFLEX_UARTCR]
+	mov	w5, w4
+
+	/* Prepare choices in w5 and w6 */
+	ubfx	x5, x5, #UARTCR_OSR_SHIFT, #UARTCR_OSR_WIDTH
+	mov	w6, #LDIV_MULTIPLIER
+
+	and	w4, w4, #UARTCR_ROSE
+	cmp	w4, #0x0
+	csel	w4, w5, w6, ne
+	ret
+endfunc get_ldiv_mult
+
+/*
+ * void linflex_set_brg(uintptr_t baseaddr, uint32_t clock
+ *                      uint32_t baud, console_t *console);
+ *
+ * Clobber list : x0 - x7, x13
+ */
+func linflex_set_brg
+	mov	x13, x30
+	bl	get_ldiv_mult
+	mov	x30, x13
+
+	/* (x4) dividr = baudrate * ldiv_mult */
+	mul	x4, x4, x2
+	/* (x5) divisr = clock rate */
+	mov	x5, x1
+	/* (x6) ibr = divisr / dividr */
+	udiv	x6, x5, x4
+	/* (x7) fbr = divisr % dividr */
+	msub	x7, x6, x4, x5
+	/* fbr *= 16 / dividr */
+	lsl	x7, x7, #4
+	udiv	x7, x7, x4
+	/* fbr &= 0xf */
+	and	w7, w7, #0xf
+	str	w6, [x0, LINFLEX_LINIBRR]
+	str	w7, [x0, LINFLEX_LINFBRR]
+	ret
+endfunc linflex_set_brg
+
+/**
+ * int console_linflex_core_init(uintptr_t baseaddr, uint32_t clock,
+ *                               uint32_t baud);
+ *
+ * In:  x0 - Linflex base address
+ *      x1 - clock frequency
+ *      x2 - baudrate
+ * Out: x0 - 1 on success, 0 on error
+ * Clobber list : x0 - x7, x13 - x14
+ */
+func console_linflex_core_init
+	/* Set master mode and init mode */
+	mov	w4, #(LINCR1_INIT)
+	str	w4, [x0, LINFLEX_LINCR1]
+	mov	w4, #(LINCR1_MME | LINCR1_INIT)
+	str	w4, [x0, LINFLEX_LINCR1]
+
+	/* wait for init mode entry */
+wait_init_entry:
+	ldr	w4, [x0, LINFLEX_LINSR]
+	and	w4, w4, #LINSR_LINS_MASK
+	cmp	w4, #LINSR_LINS_INITMODE
+	b.ne	wait_init_entry
+
+	/* Set UART bit */
+	mov	w4, #UARTCR_UART
+	str	w4, [x0, LINFLEX_UARTCR]
+
+	mov	x14, x30
+	bl	linflex_set_brg
+	mov	x30, x14
+
+	/* Set preset timeout register value. */
+	mov	w4, #0xf
+	str	w4, [x0, LINFLEX_UARTPTO]
+
+	/* 8-bit data, no parity, Tx/Rx enabled, UART mode */
+	mov	w4, #(UARTCR_PC1 | UARTCR_RXEN | UARTCR_TXEN | UARTCR_PC0 | \
+		      UARTCR_WL0 | UARTCR_UART | UARTCR_RFBM | UARTCR_TFBM)
+	str	w4, [x0, LINFLEX_UARTCR]
+
+	/* End init mode */
+	ldr	w4, [x0, LINFLEX_LINCR1]
+	bic	w4, w4, #LINCR1_INIT
+	str	w4, [x0, LINFLEX_LINCR1]
+	ret
+endfunc console_linflex_core_init
+
+/**
+ * int console_linflex_register(uintptr_t baseaddr, uint32_t clock,
+ *                              uint32_t clock, uint32_t baud);
+ *
+ * Function to initialize and register the console.
+ * The caller needs to pass an empty console_linflex_t
+ * structure in which *MUST* be allocated in
+ * persistent memory (e.g. a global or static local
+ * variable, *NOT* on the stack).
+ * In:  x0 - Linflex base address
+ *      x1 - clock frequency
+ *      x2 - baudrate
+ *      x3 - pointer to empty console_t structure
+ * Out: x0 - 1 on success, 0 on error
+ * Clobber list : x0 - x7, x13 - x15
+ */
+func console_linflex_register
+	mov	x15, x30
+	bl	console_linflex_core_init
+	mov	x30, x15
+
+	/* Populate the base address */
+	str	x0, [x3, #CONSOLE_T_BASE]
+
+	mov	x0, x3
+	finish_console_register linflex, putc=1, getc=0, flush=0
+endfunc console_linflex_register
+
+/**
+ * int console_linflex_core_putc(int c, uintptr_t baseaddr);
+
+ * Out: w0 - printed character on success, < 0 on error.
+ * Clobber list : x0 - x3
+ */
+func console_linflex_core_putc
+	cbz	x1, putc_error
+
+	cmp	w0, #'\n'
+	b.ne	print_char
+
+	/* Print '\r\n' for each '\n' */
+	mov	x0, #'\r'
+	mov	x14, x30
+	bl	console_linflex_core_putc
+	mov	x30, x14
+	mov	x0, #'\n'
+
+print_char:
+	ldr	w2, [x1, LINFLEX_UARTCR]
+	and	w2, w2, #UARTCR_TFBM
+	cmp	w2, #0x0
+	b.eq	buffer_mode
+
+fifo_mode:
+	/* UART is in FIFO mode */
+	ldr	w2, [x1, LINFLEX_UARTSR]
+	and	w2, w2, #UARTSR_DTF
+	cmp	w2, #0
+	b.ne	fifo_mode
+
+	strb	w0, [x1, LINFLEX_BDRL]
+	b	no_error
+
+buffer_mode:
+	strb	w0, [x1, LINFLEX_BDRL]
+
+buffer_loop:
+	ldr	w2, [x1, LINFLEX_UARTSR]
+	and	w3, w2, #UARTSR_DTF
+	cmp	w3, #0
+	b.eq	buffer_loop
+
+	/**
+	 * In Buffer Mode the DTFTFF bit of UARTSR register
+	 * has to be set in software
+	 */
+	mov	w2, #UARTSR_DTF
+	str	w2, [x1, LINFLEX_UARTSR]
+
+no_error:
+	mov	x0, #0
+	ret
+
+putc_error:
+	mov	x0, #-EINVAL
+	ret
+endfunc console_linflex_core_putc
+
+/**
+ * int console_linflex_putc(int c, console_t *console);
+ *
+ * Function to output a character over the console. It
+ * returns the character printed on success or -EINVAL on error.
+ * In : w0 - character to be printed
+ *      x1 - pointer to console_t struct
+ * Out: w0 - printed character on success, < 0 on error.
+ * Clobber list : x0 - x3, x15
+ */
+func console_linflex_putc
+	cbz	x1, putc_error
+	ldr	x1, [x1, #CONSOLE_T_BASE]
+
+	b	console_linflex_core_putc
+puct_error:
+	mov	x0, #-EINVAL
+	ret
+endfunc console_linflex_putc
diff --git a/include/drivers/nxp/console/linflex.h b/include/drivers/nxp/console/linflex.h
new file mode 100644
index 0000000..2b4e0d7
--- /dev/null
+++ b/include/drivers/nxp/console/linflex.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef LINFLEX_H
+#define LINFLEX_H
+
+#ifndef __ASSEMBLER__
+#include <drivers/console.h>
+
+int console_linflex_core_init(uintptr_t baseaddr, uint32_t clock,
+			      uint32_t baud);
+int console_linflex_register(uintptr_t baseaddr, uint32_t clock,
+			     uint32_t baud, console_t *console);
+#endif
+
+#endif /* LINFLEX_H */
diff --git a/plat/nxp/s32/s32g274ardb2/include/plat_console.h b/plat/nxp/s32/s32g274ardb2/include/plat_console.h
new file mode 100644
index 0000000..43c2bfd
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/plat_console.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_CONSOLE_H
+#define PLAT_CONSOLE_H
+
+void console_s32g2_register(void);
+
+#endif
diff --git a/plat/nxp/s32/s32g274ardb2/include/plat_helpers.h b/plat/nxp/s32/s32g274ardb2/include/plat_helpers.h
new file mode 100644
index 0000000..18582ec
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_HELPERS_H
+#define PLAT_HELPERS_H
+
+unsigned int s32g2_core_pos_by_mpidr(u_register_t mpidr);
+
+#endif /* PLAT_HELPERS_H */
diff --git a/plat/nxp/s32/s32g274ardb2/include/plat_io_storage.h b/plat/nxp/s32/s32g274ardb2/include/plat_io_storage.h
new file mode 100644
index 0000000..ea01300
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/plat_io_storage.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_IO_STORAGE_H
+#define PLAT_IO_STORAGE_H
+
+void plat_s32g2_io_setup(void);
+
+#endif
diff --git a/plat/nxp/s32/s32g274ardb2/include/plat_macros.S b/plat/nxp/s32/s32g274ardb2/include/plat_macros.S
new file mode 100644
index 0000000..8f0c472
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/plat_macros.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+.endm
+
+#endif /* PLAT_MACROS_S */
+
diff --git a/plat/nxp/s32/s32g274ardb2/include/platform_def.h b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
new file mode 100644
index 0000000..bdfeee2
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat/common/common_def.h>
+
+#define PLATFORM_STACK_SIZE		U(0x1000)
+
+/* Caches */
+#define CACHE_WRITEBACK_SHIFT		U(6)
+#define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* CPU Topology */
+#define PLATFORM_CORE_COUNT		U(4)
+#define PLATFORM_SYSTEM_COUNT		U(1)
+#define PLATFORM_CLUSTER_COUNT		U(2)
+#define PLATFORM_PRIMARY_CPU		U(0)
+#define PLATFORM_MPIDR_CPU_MASK_BITS	U(1)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(2)
+
+/* Power Domains */
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_SYSTEM_COUNT + \
+					 PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
+#define PLAT_MAX_OFF_STATE		U(2)
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_PWR_LVL_STATES		U(2)
+
+/* BL2 stage */
+#define BL2_BASE			UL(0x34078000)
+#define BL2_LIMIT			UL(0x34100000)
+
+/* BL31 stage */
+#define BL31_BASE			UL(0x34200000)
+#define BL31_LIMIT			UL(0x34300000)
+
+/* It is a dummy value for now, given the missing DDR */
+#define BL33_BASE			UL(0x34500000)
+#define BL33_LIMIT			UL(0x345FF000)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 36)
+/* We'll be doing a 1:1 mapping anyway */
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 36)
+
+#define MAX_MMAP_REGIONS		U(8)
+#define MAX_XLAT_TABLES			U(32)
+
+/* Console settings */
+#define UART_BASE			UL(0x401C8000)
+#define UART_BAUDRATE			U(115200)
+/* FIRC clock */
+#define UART_CLOCK_HZ			U(48000000)
+
+#define S32G_FIP_BASE			UL(0x34100000)
+#define S32G_FIP_SIZE			UL(0x100000)
+
+#define MAX_IO_HANDLES			U(2)
+#define MAX_IO_DEVICES			U(2)
+
+/* GIC settings */
+#define S32G_GIC_BASE			UL(0x50800000)
+#define PLAT_GICD_BASE			S32G_GIC_BASE
+#define PLAT_GICR_BASE			(S32G_GIC_BASE + UL(0x80000))
+
+/* Generic timer frequency; this goes directly into CNTFRQ_EL0.
+ * Its end-value is 5MHz; this is based on the assumption that
+ * GPR00[CA53_COUNTER_CLK_DIV_VAL] contains the reset value of 0x7, hence
+ * producing a divider value of 8, applied to the FXOSC frequency of 40MHz.
+ */
+#define COUNTER_FREQUENCY		U(5000000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
new file mode 100644
index 0000000..f265d95
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <plat_console.h>
+#include <plat_io_storage.h>
+
+#define SIUL2_PC09_MSCR		UL(0x4009C2E4)
+#define SIUL2_PC10_MSCR		UL(0x4009C2E8)
+#define SIUL2_PC10_LIN0_IMCR	UL(0x4009CA40)
+
+#define LIN0_TX_MSCR_CFG	U(0x00214001)
+#define LIN0_RX_MSCR_CFG	U(0x00094000)
+#define LIN0_RX_IMCR_CFG	U(0x00000002)
+
+struct bl_load_info *plat_get_bl_image_load_info(void)
+{
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+struct bl_params *plat_get_next_bl_params(void)
+{
+	return get_next_bl_params_from_mem_params_desc();
+}
+
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+static void linflex_config_pinctrl(void)
+{
+	/* set PC09 - MSCR[41] - for UART0 TXD */
+	mmio_write_32(SIUL2_PC09_MSCR, LIN0_TX_MSCR_CFG);
+	/* set PC10 - MSCR[42] - for UART0 RXD */
+	mmio_write_32(SIUL2_PC10_MSCR, LIN0_RX_MSCR_CFG);
+	/* set PC10 - MSCR[512]/IMCR[0] - for UART0 RXD */
+	mmio_write_32(SIUL2_PC10_LIN0_IMCR, LIN0_RX_IMCR_CFG);
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
+				  u_register_t arg2, u_register_t arg3)
+{
+	linflex_config_pinctrl();
+	console_s32g2_register();
+
+	plat_s32g2_io_setup();
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+}
+
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl2_image_desc.c b/plat/nxp/s32/s32g274ardb2/plat_bl2_image_desc.c
new file mode 100644
index 0000000..1fc7794
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl2_image_desc.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	{
+		.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.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS),
+		.ep_info.pc = BL31_BASE,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+				      image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+		.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+		.image_info.image_base = BL31_BASE,
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+	{
+		.image_id = BL33_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+				      entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+				      image_info_t, 0),
+		.image_info.image_max_size = BL33_LIMIT - BL33_BASE,
+		.image_info.image_base = BL33_BASE,
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl31_setup.c b/plat/nxp/s32/s32g274ardb2/plat_bl31_setup.c
new file mode 100644
index 0000000..03bf35c
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl31_setup.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/gicv3.h>
+#include <plat/common/platform.h>
+#include <plat_console.h>
+
+static entry_point_info_t bl33_image_ep_info;
+
+static unsigned int s32g2_mpidr_to_core_pos(unsigned long mpidr);
+
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+	unsigned long mode = MODE_EL1;
+	uint32_t spsr;
+
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+
+	return spsr;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	console_s32g2_register();
+
+	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+	bl33_image_ep_info.pc = BL33_BASE;
+	bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+void bl31_plat_arch_setup(void)
+{
+}
+
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	return &bl33_image_ep_info;
+}
+
+void bl31_platform_setup(void)
+{
+	static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+	static gicv3_driver_data_t plat_gic_data = {
+		.gicd_base = PLAT_GICD_BASE,
+		.gicr_base = PLAT_GICR_BASE,
+		.rdistif_num = PLATFORM_CORE_COUNT,
+		.rdistif_base_addrs = rdistif_base_addrs,
+		.mpidr_to_core_pos = s32g2_mpidr_to_core_pos,
+	};
+
+	unsigned int pos = plat_my_core_pos();
+
+	gicv3_driver_init(&plat_gic_data);
+	gicv3_distif_init();
+	gicv3_rdistif_init(pos);
+	gicv3_cpuif_enable(pos);
+}
+
+static unsigned int s32g2_mpidr_to_core_pos(unsigned long mpidr)
+{
+	int core;
+
+	core = plat_core_pos_by_mpidr(mpidr);
+	if (core < 0) {
+		return 0;
+	}
+
+	return (unsigned int)core;
+}
+
diff --git a/plat/nxp/s32/s32g274ardb2/plat_console.c b/plat/nxp/s32/s32g274ardb2/plat_console.c
new file mode 100644
index 0000000..27cae12
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/plat_console.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <linflex.h>
+#include <plat_console.h>
+#include <platform_def.h>
+
+void console_s32g2_register(void)
+{
+	static console_t s32g2_console;
+	int ret;
+
+	(void)memset(&s32g2_console, 0, sizeof(s32g2_console));
+
+	ret = console_linflex_register(UART_BASE, UART_CLOCK_HZ,
+				       UART_BAUDRATE, &s32g2_console);
+	if (ret == 0) {
+		panic();
+	}
+
+	console_set_scope(&s32g2_console,
+			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH |
+			  CONSOLE_FLAG_TRANSLATE_CRLF);
+}
diff --git a/plat/nxp/s32/s32g274ardb2/plat_helpers.S b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
new file mode 100644
index 0000000..193c884
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+
+#define S32G_NCORE_CAIU0_BASE_ADDR		UL(0x50400000)
+#define S32G_NCORE_CAIUTC_OFF			U(0x0)
+#define S32G_NCORE_CAIUTC_ISOLEN_SHIFT		U(1)
+
+.globl	plat_crash_console_flush
+.globl	plat_crash_console_init
+.globl	plat_crash_console_putc
+.globl	plat_is_my_cpu_primary
+.globl	plat_my_core_pos
+.globl	plat_reset_handler
+.globl	plat_secondary_cold_boot_setup
+.globl	platform_mem_init
+.globl	s32g2_core_pos_by_mpidr
+
+/* int plat_crash_console_init(void); */
+func plat_crash_console_init
+	mov_imm	x0, UART_BASE
+	mov_imm	x1, UART_CLOCK_HZ
+	mov_imm	x2, UART_BAUDRATE
+	b	console_linflex_core_init
+endfunc plat_crash_console_init
+
+/* int plat_crash_console_putc(int); */
+func plat_crash_console_putc
+	mov_imm	x1, UART_BASE
+	b	console_linflex_core_putc
+	ret
+endfunc plat_crash_console_putc
+
+/* void plat_crash_console_flush(void); */
+func plat_crash_console_flush
+	ret
+endfunc plat_crash_console_flush
+
+/**
+ * unsigned int s32g2_core_pos_by_mpidr(u_register_t mpidr);
+ *
+ * In: x0 -  MPIDR_EL1
+ * Out: x0
+ * Clobber list: x0, x1
+ */
+func s32g2_core_pos_by_mpidr
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	lsr	x0, x0, #MPIDR_AFF1_SHIFT
+	add	x0, x1, x0, lsl #PLATFORM_MPIDR_CPU_MASK_BITS
+	ret
+endfunc s32g2_core_pos_by_mpidr
+
+/**
+ * unsigned int plat_my_core_pos(void);
+ *
+ * Out: x0
+ * Clobber list: x0, x1, x8
+ */
+func plat_my_core_pos
+	mov	x8, x30
+	mrs x0, mpidr_el1
+	bl	s32g2_core_pos_by_mpidr
+	mov	x30, x8
+	ret
+endfunc plat_my_core_pos
+
+/**
+ * unsigned int plat_is_my_cpu_primary(void);
+ *
+ * Clobber list: x0, x1, x7, x8
+ */
+func plat_is_my_cpu_primary
+	mov	x7, x30
+	bl	plat_my_core_pos
+	cmp	x0, #PLATFORM_PRIMARY_CPU
+	cset	x0, eq
+	mov	x30, x7
+	ret
+endfunc plat_is_my_cpu_primary
+
+
+/**
+ * void plat_secondary_cold_boot_setup (void);
+ */
+func plat_secondary_cold_boot_setup
+	ret
+endfunc plat_secondary_cold_boot_setup
+
+/**
+ * void plat_reset_handler(void);
+ *
+ * Set the CAIUTC[IsolEn] bit for the primary A53 cluster.
+ * This is so cache invalidate operations from the early TF-A boot code
+ * won't cause Ncore to crash.
+ *
+ * Clobber list: x0, x1, x2
+ */
+func plat_reset_handler
+	mov	x0, #S32G_NCORE_CAIU0_BASE_ADDR
+	ldr	w1, [x0, #S32G_NCORE_CAIUTC_OFF]
+	movz	w2, #1
+	lsl	w2, w2, #S32G_NCORE_CAIUTC_ISOLEN_SHIFT
+	orr	w1, w1, w2
+	str	w1, [x0, #S32G_NCORE_CAIUTC_OFF]
+	ret
+endfunc plat_reset_handler
+
+/* void platform_mem_init(void); */
+func platform_mem_init
+	mov	x10, x30
+	mov	x0, #BL31_BASE
+	mov	x1, #(BL31_LIMIT & 0xFFFFU)
+	movk	x1, #(BL31_LIMIT >> 16), lsl #16
+	sub	x1, x1, x0
+	bl	zeromem
+	mov	x0, #BL33_BASE
+	mov	x1, #(BL33_LIMIT & 0xFFFFU)
+	movk	x1, #(BL33_LIMIT >> 16), lsl #16
+	sub	x1, x1, x0
+	bl	zeromem
+	mov	x30, x10
+	ret
+endfunc platform_mem_init
+
diff --git a/plat/nxp/s32/s32g274ardb2/plat_io_storage.c b/plat/nxp/s32/s32g274ardb2/plat_io_storage.c
new file mode 100644
index 0000000..db6bcc5
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/plat_io_storage.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <plat/common/platform.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <plat_io_storage.h>
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static int open_memmap(const uintptr_t spec);
+static int open_fip(const uintptr_t spec);
+
+static uintptr_t fip_dev_handle;
+
+static uintptr_t memmap_dev_handle;
+
+static int open_memmap(const uintptr_t spec)
+{
+	uintptr_t temp_handle = 0U;
+	int result;
+
+	result = io_dev_init(memmap_dev_handle, (uintptr_t)0);
+	if (result != 0) {
+		return result;
+	}
+
+	result = io_open(memmap_dev_handle, spec, &temp_handle);
+	if (result == 0) {
+		(void)io_close(temp_handle);
+	}
+
+	return result;
+}
+
+static int open_fip(const uintptr_t spec)
+{
+	uintptr_t temp_handle = 0U;
+	int result;
+
+	/* See if a Firmware Image Package is available */
+	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+	if (result != 0) {
+		return result;
+	}
+
+	result = io_open(fip_dev_handle, spec, &temp_handle);
+	if (result == 0) {
+		(void)io_close(temp_handle);
+	}
+
+	return result;
+}
+
+void plat_s32g2_io_setup(void)
+{
+	static const io_dev_connector_t *memmap_dev_con;
+	static const io_dev_connector_t *fip_dev_con;
+
+	int result __unused;
+
+	result = register_io_dev_memmap(&memmap_dev_con);
+	assert(result == 0);
+
+	result = io_dev_open(memmap_dev_con, (uintptr_t)0,
+			     &memmap_dev_handle);
+	assert(result == 0);
+
+	result = register_io_dev_fip(&fip_dev_con);
+	assert(result == 0);
+
+	result = io_dev_open(fip_dev_con, (uintptr_t)0,
+			     &fip_dev_handle);
+	assert(result == 0);
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	static const io_block_spec_t fip_block_spec = {
+		.offset = S32G_FIP_BASE,
+		.length = S32G_FIP_SIZE,
+	};
+
+	static const io_uuid_spec_t bl31_uuid_spec = {
+		.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+	};
+
+	static const io_uuid_spec_t bl33_uuid_spec = {
+		.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+	};
+
+	static const struct plat_io_policy policies[BL33_IMAGE_ID + 1] = {
+		[FIP_IMAGE_ID] = {
+			.dev_handle = &memmap_dev_handle,
+			.image_spec = (uintptr_t)&fip_block_spec,
+			.check = open_memmap,
+		},
+		[BL31_IMAGE_ID] = {
+			.dev_handle = &fip_dev_handle,
+			.image_spec = (uintptr_t)&bl31_uuid_spec,
+			.check = open_fip,
+		},
+		[BL33_IMAGE_ID] = {
+			.dev_handle = &fip_dev_handle,
+			.image_spec = (uintptr_t)&bl33_uuid_spec,
+			.check = open_fip,
+		},
+	};
+	const struct plat_io_policy *policy;
+	int result;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	result = policy->check(policy->image_spec);
+	assert(result == 0);
+
+	*image_spec = policy->image_spec;
+	*dev_handle = *policy->dev_handle;
+
+	return result;
+}
diff --git a/plat/nxp/s32/s32g274ardb2/platform.mk b/plat/nxp/s32/s32g274ardb2/platform.mk
new file mode 100644
index 0000000..ee1507e
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/platform.mk
@@ -0,0 +1,65 @@
+#
+# Copyright 2024 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_DRIVERS_PATH := drivers/nxp
+PLAT_COMMON_PATH  := plat/nxp/common
+PLAT_S32G274ARDB2 := plat/nxp/s32/s32g274ardb2
+
+CONSOLE           := LINFLEX
+
+include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
+
+PLAT_INCLUDES = \
+	-I${PLAT_S32G274ARDB2}/include
+
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 0
+
+ENABLE_SVE_FOR_NS := 0
+
+RESET_TO_BL2 := 1
+
+INIT_UNUSED_NS_EL2 := 1
+
+ERRATA_A53_855873 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_1530924 := 1
+ERRATA_SPECULATIVE_AT := 1
+
+# Selecting Drivers for SoC
+$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
+
+include ${PLAT_DRIVERS_PATH}/drivers.mk
+
+
+BL_COMMON_SOURCES += \
+	${PLAT_S32G274ARDB2}/plat_console.c \
+	${PLAT_S32G274ARDB2}/plat_helpers.S \
+
+BL2_SOURCES += \
+	${BL_COMMON_SOURCES} \
+	${PLAT_S32G274ARDB2}/plat_bl2_el3_setup.c \
+	${PLAT_S32G274ARDB2}/plat_bl2_image_desc.c \
+	${PLAT_S32G274ARDB2}/plat_io_storage.c \
+	common/desc_image_load.c \
+	drivers/io/io_fip.c \
+	drivers/io/io_memmap.c \
+	drivers/io/io_storage.c \
+	lib/cpus/aarch64/cortex_a53.S \
+
+BL31_SOURCES += \
+	${GICV3_SOURCES} \
+	${PLAT_S32G274ARDB2}/plat_bl31_setup.c \
+	${PLAT_S32G274ARDB2}/s32g2_psci.c \
+	${PLAT_S32G274ARDB2}/s32g2_soc.c \
+	${XLAT_TABLES_LIB_SRCS} \
+	lib/cpus/aarch64/cortex_a53.S \
+	plat/common/plat_gicv3.c \
+	plat/common/plat_psci_common.c \
diff --git a/plat/nxp/s32/s32g274ardb2/s32g2_psci.c b/plat/nxp/s32/s32g274ardb2/s32g2_psci.c
new file mode 100644
index 0000000..2d02d94
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/s32g2_psci.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	static const plat_psci_ops_t s32g2_psci_ops = {
+	};
+
+	*psci_ops = &s32g2_psci_ops;
+
+	return 0;
+}
+
diff --git a/plat/nxp/s32/s32g274ardb2/s32g2_soc.c b/plat/nxp/s32/s32g274ardb2/s32g2_soc.c
new file mode 100644
index 0000000..0001352
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/s32g2_soc.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+#include <plat_helpers.h>
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	static const unsigned char s32g_power_domain_tree_desc[] = {
+		PLATFORM_SYSTEM_COUNT,
+		PLATFORM_CLUSTER_COUNT,
+		PLATFORM_CORE_COUNT / U(2),
+		PLATFORM_CORE_COUNT / U(2),
+	};
+
+	return s32g_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id, core_id;
+	u_register_t mpidr_priv = mpidr;
+
+	mpidr_priv &= MPIDR_AFFINITY_MASK;
+
+	if ((mpidr_priv & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) {
+		return -1;
+	}
+
+	cluster_id = MPIDR_AFFLVL1_VAL(mpidr_priv);
+	cpu_id = MPIDR_AFFLVL0_VAL(mpidr_priv);
+
+	if ((cluster_id >= PLATFORM_CLUSTER_COUNT) ||
+	    (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)) {
+		return -1;
+	}
+
+	core_id = s32g2_core_pos_by_mpidr(mpidr_priv);
+	if (core_id >= PLATFORM_CORE_COUNT) {
+		return -1;
+	}
+
+	return (int)core_id;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}