Support for NXP's imx SoC common function
authorAnson Huang <Anson.Huang@nxp.com>
Tue, 5 Jun 2018 08:12:27 +0000 (16:12 +0800)
committerAnson Huang <Anson.Huang@nxp.com>
Tue, 19 Jun 2018 02:24:32 +0000 (10:24 +0800)
This patch adds support for NXP's imx SoC common
function support like topology, gic implementation.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
plat/imx/common/imx8_helpers.S [new file with mode: 0644]
plat/imx/common/imx8_topology.c [new file with mode: 0644]
plat/imx/common/include/plat_imx8.h [new file with mode: 0644]
plat/imx/common/include/plat_macros.S [new file with mode: 0644]
plat/imx/common/plat_imx8_gic.c [new file with mode: 0644]

diff --git a/plat/imx/common/imx8_helpers.S b/plat/imx/common/imx8_helpers.S
new file mode 100644 (file)
index 0000000..b89d346
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <cortex_a35.h>
+
+       .globl  plat_is_my_cpu_primary
+       .globl  plat_my_core_pos
+       .globl  plat_calc_core_pos
+       .globl  plat_reset_handler
+       .globl  plat_get_my_entrypoint
+       .globl  plat_secondary_cold_boot_setup
+       .globl  plat_crash_console_init
+       .globl  plat_crash_console_putc
+       .globl  platform_mem_init
+       .globl  imx_mailbox_init
+
+       /* --------------------------------------------------------------------
+        * Helper macro that reads the part number of the current CPU and jumps
+        * to the given label if it matches the CPU MIDR provided.
+        *
+        * Clobbers x0.
+        * --------------------------------------------------------------------
+        */
+       .macro  jump_if_cpu_midr _cpu_midr, _label
+
+       mrs     x0, midr_el1
+       ubfx    x0, x0, MIDR_PN_SHIFT, #12
+       cmp     w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+       b.eq    \_label
+
+       .endm
+
+       /* ----------------------------------------------
+        * The mailbox_base is used to distinguish warm/cold
+        * reset. The mailbox_base is in the data section, not
+        * in .bss, this allows function to start using this
+        * variable before the runtime memory is initialized.
+        * ----------------------------------------------
+        */
+       .section .data.mailbox_base
+       .align 3
+       mailbox_base: .quad 0x0
+
+       /* ----------------------------------------------
+        * unsigned int plat_is_my_cpu_primary(void);
+        * This function checks if this is the primary CPU
+        * ----------------------------------------------
+        */
+func plat_is_my_cpu_primary
+       mrs     x0, mpidr_el1
+       and     x0, x0, #(MPIDR_CPU_MASK)
+       cmp     x0, #PLAT_PRIMARY_CPU
+       cset    x0, eq
+       ret
+endfunc plat_is_my_cpu_primary
+
+       /* ----------------------------------------------
+        * unsigned int plat_my_core_pos(void)
+        * This Function uses the plat_calc_core_pos()
+        * to get the index of the calling CPU.
+        * ----------------------------------------------
+        */
+func plat_my_core_pos
+       mrs     x0, mpidr_el1
+       and     x1, x0, #MPIDR_CPU_MASK
+       and     x0, x0, #MPIDR_CLUSTER_MASK
+       add     x0, x1, x0, LSR #6
+       ret
+endfunc plat_my_core_pos
+
+       /*
+        * unsigned int plat_calc_core_pos(uint64_t mpidr)
+        * helper function to calculate the core position.
+        * With this function.
+        */
+func plat_calc_core_pos
+       and     x1, x0, #MPIDR_CPU_MASK
+       and     x0, x0, #MPIDR_CLUSTER_MASK
+       add     x0, x1, x0, LSR #6
+       ret
+endfunc plat_calc_core_pos
+
+       /* ---------------------------------------------
+        * function to get the entrypoint.
+        * ---------------------------------------------
+        */
+func plat_get_my_entrypoint
+       adrp    x1, mailbox_base
+       ldr     x0, [x1, :lo12:mailbox_base]
+       ret
+endfunc        plat_get_my_entrypoint
+
+func imx_mailbox_init
+       adrp    x1, mailbox_base
+       str     x0, [x1, :lo12:mailbox_base]
+       ret
+endfunc imx_mailbox_init
+
+func plat_secondary_cold_boot_setup
+       b       .
+endfunc plat_secondary_cold_boot_setup
+
+func plat_crash_console_init
+       ret
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+       ret
+endfunc plat_crash_console_putc
+
+func platform_mem_init
+       ret
+endfunc platform_mem_init
diff --git a/plat/imx/common/imx8_topology.c b/plat/imx/common/imx8_topology.c
new file mode 100644 (file)
index 0000000..bcb7d59
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <platform.h>
+
+const unsigned char imx_power_domain_tree_desc[] = {
+       PWR_DOMAIN_AT_MAX_LVL,
+       PLATFORM_CLUSTER_COUNT,
+       PLATFORM_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+       return imx_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+       unsigned int cluster_id, cpu_id;
+
+       mpidr &= MPIDR_AFFINITY_MASK;
+
+       if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+               return -1;
+
+       cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+       cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+       if (cluster_id > PLATFORM_CLUSTER_COUNT ||
+               cpu_id > PLATFORM_MAX_CPU_PER_CLUSTER)
+               return -1;
+
+       return (cpu_id + (cluster_id * 4));
+}
diff --git a/plat/imx/common/include/plat_imx8.h b/plat/imx/common/include/plat_imx8.h
new file mode 100644 (file)
index 0000000..27d4c37
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_IMX8_H__
+#define __PLAT_IMX8_H__
+
+#include <gicv3.h>
+
+unsigned int plat_calc_core_pos(uint64_t mpidr);
+void imx_mailbox_init(uintptr_t base_addr);
+void plat_gic_driver_init(void);
+void plat_gic_init(void);
+void plat_gic_cpuif_enable(void);
+void plat_gic_cpuif_disable(void);
+void plat_gic_pcpu_init(void);
+
+#endif /*__PLAT_IMX8_H__ */
diff --git a/plat/imx/common/include/plat_macros.S b/plat/imx/common/include/plat_macros.S
new file mode 100644 (file)
index 0000000..30cce0a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * the below macros print out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL3-1
+ */
+.macro plat_print_gic_regs
+       /* TODO */
+.endm
+
+/*
+ * the below macros print out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1
+ */
+.macro plat_print_interconnect_regs
+       /* TODO */
+.endm
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+      /* TODO */
+.endm
diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c
new file mode 100644 (file)
index 0000000..242e31b
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <gicv3.h>
+#include <plat_imx8.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <utils.h>
+
+/* the GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* array of Group1 secure interrupts to be configured by the gic driver */
+const unsigned int g1s_interrupt_array[] = { 6 };
+
+/* array of Group0 interrupts to be configured by the gic driver */
+const unsigned int g0_interrupt_array[] = { 7 };
+
+static unsigned int plat_imx_mpidr_to_core_pos(unsigned long mpidr)
+{
+       return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+const gicv3_driver_data_t arm_gic_data = {
+       .gicd_base = PLAT_GICD_BASE,
+       .gicr_base = PLAT_GICR_BASE,
+       .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
+       .g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
+       .g0_interrupt_array = g0_interrupt_array,
+       .g1s_interrupt_array = g1s_interrupt_array,
+       .rdistif_num = PLATFORM_CORE_COUNT,
+       .rdistif_base_addrs = rdistif_base_addrs,
+       .mpidr_to_core_pos = plat_imx_mpidr_to_core_pos,
+};
+
+void plat_gic_driver_init(void)
+{
+       /*
+        * the GICv3 driver is initialized in EL3 and does not need
+        * to be initialized again in S-EL1. This is because the S-EL1
+        * can use GIC system registers to manage interrupts and does
+        * not need GIC interface base addresses to be configured.
+        */
+#if IMAGE_BL31
+       gicv3_driver_init(&arm_gic_data);
+#endif
+}
+
+void plat_gic_init(void)
+{
+       gicv3_distif_init();
+       gicv3_rdistif_init(plat_my_core_pos());
+       gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_gic_cpuif_enable(void)
+{
+       gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_gic_cpuif_disable(void)
+{
+       gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void plat_gic_pcpu_init(void)
+{
+       gicv3_rdistif_init(plat_my_core_pos());
+}