Merge "feat(s32g274a): add ncore support" into integration
diff --git a/plat/nxp/s32/s32g274ardb2/include/s32cc-ncore.h b/plat/nxp/s32/s32g274ardb2/include/s32cc-ncore.h
new file mode 100644
index 0000000..0c0870f
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/s32cc-ncore.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019-2021, 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef S32G2_NCORE_H
+#define S32G2_NCORE_H
+
+#include <stdbool.h>
+
+#define NCORE_BASE_ADDR			UL(0x50400000)
+
+#define A53_CLUSTER0_CAIU		U(0)
+#define A53_CLUSTER1_CAIU		U(1)
+
+/**
+ * Directory Unit Registers
+ *
+ * The directory provides a point of serialization for establishing transaction
+ * ordering and sequences coherence operations and memory accesses.
+ */
+#define NCORE_DIRU(N)			(NCORE_BASE_ADDR + UL(0x80000) + ((N) * UL(0x1000)))
+
+/* DIRU Snoop Filtering Enable */
+#define NCORE_DIRUSFE(N)		(NCORE_DIRU(N) + UL(0x10))
+#define NCORE_DIRUSFE_SFEN(SF)		BIT_32(SF)
+
+/* DIRU Caching Agent Snoop Enable */
+#define NCORE_DIRUCASE(N)		(NCORE_DIRU(N) + UL(0x40))
+#define NCORE_DIRUCASE_CASNPEN(CAIU)	BIT_32(CAIU)
+
+/* DIRU Snoop Filter Maintenance Control */
+#define NCORE_DIRUSFMC(N)		(NCORE_DIRU(N) + UL(0x80))
+#define NCORE_DIRUSFMC_SFID(SF)		((SF) << 16U)
+#define NCORE_DIRUSFMC_SFMNTOP_ALL	U(0x0)
+
+/* DIRU Snoop Filter Maintenance Activity */
+#define NCORE_DIRUSFMA(N)		(NCORE_DIRU(N) + UL(0x84))
+#define NCORE_DIRUSFMA_MNTOPACTV	BIT_32(0)
+
+/**
+ * Coherent Agent Interface Unit Registers
+ *
+ * CAI provides a means for a fully-coherent agent to be connected to the Ncore.
+ * The CAI behaves as a fully-coherent slave.
+ */
+#define NCORE_CAIU(N)			(NCORE_BASE_ADDR + ((N) * UL(0x1000)))
+#define NCORE_CAIU0_BASE_ADDR		NCORE_BASE_ADDR
+
+/* CAIU Transaction Control */
+#define NCORE_CAIUTC_OFF		UL(0x0)
+#define NCORE_CAIUTC_ISOLEN_SHIFT	U(1)
+#define NCORE_CAIUTC_ISOLEN_MASK	BIT_32(NCORE_CAIUTC_ISOLEN_SHIFT)
+
+#define NCORE_CAIUTC(N)			(NCORE_CAIU(N) + NCORE_CAIUTC_OFF)
+
+/* CAIU Identification */
+#define NCORE_CAIUID(n)			(NCORE_CAIU(n) + UL(0xFFC))
+#define NCORE_CAIUID_TYPE		GENMASK_32(U(19), U(16))
+#define NCORE_CAIUID_TYPE_ACE_DVM	U(0x0)
+
+/**
+ * Coherent Subsystem Registers
+ */
+#define NCORE_CSR			(NCORE_BASE_ADDR + UL(0xFF000))
+
+/* Coherent Subsystem ACE DVM Snoop Enable */
+#define NCORE_CSADSE			(NCORE_CSR + UL(0x40))
+#define NCORE_CSADSE_DVMSNPEN(CAIU)	BIT_32(CAIU)
+
+/* Coherent Subsystem Identification */
+#define NCORE_CSID			(NCORE_CSR + UL(0xFFC))
+#define NCORE_CSID_NUMSFS_SHIFT		U(18)
+#define NCORE_CSID_NUMSFS_MASK		GENMASK_32(U(22), NCORE_CSID_NUMSFS_SHIFT)
+#define NCORE_CSID_NUMSFS(CSIDR)	(((CSIDR) & NCORE_CSID_NUMSFS_MASK) \
+					  >> NCORE_CSID_NUMSFS_SHIFT)
+
+/* Coherent Subsystem Unit Identification */
+#define NCORE_CSUID			(NCORE_CSR + UL(0xFF8))
+#define NCORE_CSUID_NUMCMIUS_SHIFT	U(24)
+#define NCORE_CSUID_NUMCMIUS_MASK	GENMASK_32(U(29), NCORE_CSUID_NUMCMIUS_SHIFT)
+#define NCORE_CSUID_NUMCMIUS(CSUIDR)	(((CSUIDR) & NCORE_CSUID_NUMCMIUS_MASK) \
+					 >> NCORE_CSUID_NUMCMIUS_SHIFT)
+#define NCORE_CSUID_NUMDIRUS_SHIFT	U(16)
+#define NCORE_CSUID_NUMDIRUS_MASK	GENMASK_32(U(21), NCORE_CSUID_NUMDIRUS_SHIFT)
+#define NCORE_CSUID_NUMDIRUS(CSUIDR)	(((CSUIDR) & NCORE_CSUID_NUMDIRUS_MASK) \
+					 >> NCORE_CSUID_NUMDIRUS_SHIFT)
+#define NCORE_CSUID_NUMNCBUS_SHIFT	U(8)
+#define NCORE_CSUID_NUMNCBUS_MASK	GENMASK_32(U(13), NCORE_CSUID_NUMNCBUS_SHIFT)
+#define NCORE_CSUID_NUMNCBUS(CSUIDR)	(((CSUIDR) & NCORE_CSUID_NUMNCBUS_MASK) \
+					 >> NCORE_CSUID_NUMNCBUS_SHIFT)
+
+#ifndef __ASSEMBLER__
+void ncore_caiu_online(uint32_t caiu);
+void ncore_caiu_offline(uint32_t caiu);
+void ncore_init(void);
+bool ncore_is_caiu_online(uint32_t caiu);
+void ncore_disable_caiu_isolation(uint32_t caiu);
+#endif /* __ASSEMBLER__ */
+
+#endif /* S32G2_NCORE_H */
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
index 705832c..4645f01 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
@@ -11,6 +11,7 @@
 #include <plat_console.h>
 #include <s32cc-clk-drv.h>
 #include <plat_io_storage.h>
+#include <s32cc-ncore.h>
 
 #define SIUL2_PC09_MSCR		UL(0x4009C2E4)
 #define SIUL2_PC10_MSCR		UL(0x4009C2E8)
@@ -62,6 +63,14 @@
 	linflex_config_pinctrl();
 	console_s32g2_register();
 
+	/* Restore (clear) the CAIUTC[IsolEn] bit for the primary cluster, which
+	 * we have manually set during early BL2 boot.
+	 */
+	ncore_disable_caiu_isolation(A53_CLUSTER0_CAIU);
+
+	ncore_init();
+	ncore_caiu_online(A53_CLUSTER0_CAIU);
+
 	plat_s32g2_io_setup();
 }
 
diff --git a/plat/nxp/s32/s32g274ardb2/plat_helpers.S b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
index 10c0035..7121900 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_helpers.S
+++ b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
@@ -6,10 +6,7 @@
 
 #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)
+#include <s32cc-ncore.h>
 
 .globl	plat_crash_console_flush
 .globl	plat_crash_console_init
@@ -104,12 +101,12 @@
  * Clobber list: x0, x1, x2
  */
 func plat_reset_handler
-	mov	x0, #S32G_NCORE_CAIU0_BASE_ADDR
-	ldr	w1, [x0, #S32G_NCORE_CAIUTC_OFF]
+	mov	x0, #NCORE_CAIU0_BASE_ADDR
+	ldr	w1, [x0, #NCORE_CAIUTC_OFF]
 	movz	w2, #1
-	lsl	w2, w2, #S32G_NCORE_CAIUTC_ISOLEN_SHIFT
+	lsl	w2, w2, #NCORE_CAIUTC_ISOLEN_SHIFT
 	orr	w1, w1, w2
-	str	w1, [x0, #S32G_NCORE_CAIUTC_OFF]
+	str	w1, [x0, #NCORE_CAIUTC_OFF]
 	ret
 endfunc plat_reset_handler
 
diff --git a/plat/nxp/s32/s32g274ardb2/platform.mk b/plat/nxp/s32/s32g274ardb2/platform.mk
index 7dc287d..7d6e960 100644
--- a/plat/nxp/s32/s32g274ardb2/platform.mk
+++ b/plat/nxp/s32/s32g274ardb2/platform.mk
@@ -53,6 +53,7 @@
 	${PLAT_S32G274ARDB2}/plat_bl2_el3_setup.c \
 	${PLAT_S32G274ARDB2}/plat_bl2_image_desc.c \
 	${PLAT_S32G274ARDB2}/plat_io_storage.c \
+	${PLAT_S32G274ARDB2}/s32cc_ncore.c \
 	common/desc_image_load.c \
 	drivers/io/io_fip.c \
 	drivers/io/io_memmap.c \
diff --git a/plat/nxp/s32/s32g274ardb2/s32cc_ncore.c b/plat/nxp/s32/s32g274ardb2/s32cc_ncore.c
new file mode 100644
index 0000000..aa60ac4
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/s32cc_ncore.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2021, 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include <s32cc-ncore.h>
+
+static void ncore_diru_online(uint32_t diru)
+{
+	uint32_t numsfs, sf;
+
+	numsfs = NCORE_CSID_NUMSFS(mmio_read_32(NCORE_CSID)) + 1U;
+
+	/* Initialize all entries maintenance operation for each snoop filter */
+	for (sf = 0U; sf < numsfs; sf++) {
+		mmio_write_32(NCORE_DIRUSFMC(diru), NCORE_DIRUSFMC_SFID(sf) |
+			      NCORE_DIRUSFMC_SFMNTOP_ALL);
+
+		while ((mmio_read_32(NCORE_DIRUSFMA(diru)) & NCORE_DIRUSFMA_MNTOPACTV) != 0U) {
+		}
+
+		mmio_setbits_32(NCORE_DIRUSFE(diru), NCORE_DIRUSFE_SFEN(sf));
+	}
+}
+
+void ncore_disable_caiu_isolation(uint32_t caiu)
+{
+	/* Exit from low-power state */
+	mmio_clrbits_32(NCORE_CAIUTC(caiu), NCORE_CAIUTC_ISOLEN_MASK);
+}
+
+static void set_caiu(uint32_t caiu, bool on)
+{
+	uint32_t dirucase, csadser, caiuidr;
+	uint32_t numdirus, diru;
+
+	/* Enable or disable snoop messages to the CAI for each DIRU */
+	numdirus = NCORE_CSUID_NUMDIRUS(mmio_read_32(NCORE_CSUID));
+	for (diru = 0; diru < numdirus; diru++) {
+		dirucase = mmio_read_32(NCORE_DIRUCASE(diru));
+
+		if (on) {
+			dirucase |= NCORE_DIRUCASE_CASNPEN(caiu);
+		} else {
+			dirucase &= ~NCORE_DIRUCASE_CASNPEN(caiu);
+		}
+
+		mmio_write_32(NCORE_DIRUCASE(diru), dirucase);
+	}
+
+	/* Enable or disable DVM messages to the CAI */
+	caiuidr = mmio_read_32(NCORE_CAIUID(caiu));
+	if ((caiuidr & NCORE_CAIUID_TYPE) == NCORE_CAIUID_TYPE_ACE_DVM) {
+		csadser = mmio_read_32(NCORE_CSADSE);
+
+		if (on) {
+			csadser |= NCORE_CSADSE_DVMSNPEN(caiu);
+		} else {
+			csadser &= ~NCORE_CSADSE_DVMSNPEN(caiu);
+		}
+
+		mmio_write_32(NCORE_CSADSE, csadser);
+	}
+}
+
+void ncore_caiu_online(uint32_t caiu)
+{
+	set_caiu(caiu, true);
+}
+
+void ncore_caiu_offline(uint32_t caiu)
+{
+	set_caiu(caiu, false);
+}
+
+bool ncore_is_caiu_online(uint32_t caiu)
+{
+	uint32_t stat = mmio_read_32(NCORE_CSADSE);
+
+	return ((stat & NCORE_CSADSE_DVMSNPEN(caiu)) != 0U);
+}
+
+void ncore_init(void)
+{
+	uint32_t csuidr = mmio_read_32(NCORE_CSUID);
+	uint32_t numdirus, diru;
+
+	numdirus = NCORE_CSUID_NUMDIRUS(csuidr);
+	for (diru = 0U; diru < numdirus; diru++) {
+		/**
+		 * Transition the directory to an online state by ensuring that
+		 * all DIRUs within the interface are operational.
+		 */
+		ncore_diru_online(diru);
+	}
+}