feat(s32g274a): enable BL31 stage
Add BL31 prerequisites for the S32G274ARDB2 board to allow single-core
cold boot without MMU and PSCI services.
Change-Id: I8a10fd62f3cc9430083758043ea82e3803f61060
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>
Signed-off-by: Bogdan Roman <bogdan-gabriel.roman@nxp.com>
Signed-off-by: Andra-Teodora Ilie <andra.ilie@nxp.com>
Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
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/platform_def.h b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
index 7e87fcb..bdfeee2 100644
--- a/plat/nxp/s32/s32g274ardb2/include/platform_def.h
+++ b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
@@ -18,10 +18,15 @@
/* 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)
@@ -39,6 +44,13 @@
#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)
@@ -51,4 +63,16 @@
#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_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_helpers.S b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
index a537665..193c884 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_helpers.S
+++ b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
@@ -15,6 +15,7 @@
.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
diff --git a/plat/nxp/s32/s32g274ardb2/platform.mk b/plat/nxp/s32/s32g274ardb2/platform.mk
index 9c04fbb..ee1507e 100644
--- a/plat/nxp/s32/s32g274ardb2/platform.mk
+++ b/plat/nxp/s32/s32g274ardb2/platform.mk
@@ -54,3 +54,12 @@
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;
+}