]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
feat(msm8916): initial platform port
authorStephan Gerhold <stephan@gerhold.net>
Wed, 1 Dec 2021 19:01:11 +0000 (20:01 +0100)
committerStephan Gerhold <stephan@gerhold.net>
Thu, 3 Feb 2022 10:56:22 +0000 (11:56 +0100)
Introduce the bare mimimum base of the msm8916 BL31 port. This is
pretty much just a standard platform "skeleton" with CPU/memory
initialization and an UART driver. This allows booting into
e.g. U-Boot with working UART output.

Note that the plat/qti/msm8916 port is completely separate and does not
make use of anything in plat/qti/common at the moment. The main reason
for that is that plat/qti/common is heavily focused around having a
binary "qtiseclib" component, while the MSM8916 port is fully
open-source (and therefore somewhat limited to publicly documented
functionality).

In the future it might be possible to re-use some of the open-source
parts in plat/qti/common (e.g. spmi_arb.c or pm_ps_hold.c) but it's
not strictly required for the basic functionality supported so far.

Change-Id: I7b4375df0f947b3bd1e55b0b52b21edb6e6d175b
Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
plat/qti/msm8916/aarch64/msm8916_helpers.S [new file with mode: 0644]
plat/qti/msm8916/aarch64/uartdm_console.S [new file with mode: 0644]
plat/qti/msm8916/include/msm8916_mmap.h [new file with mode: 0644]
plat/qti/msm8916/include/plat_macros.S [new file with mode: 0644]
plat/qti/msm8916/include/platform_def.h [new file with mode: 0644]
plat/qti/msm8916/include/uartdm_console.h [new file with mode: 0644]
plat/qti/msm8916/msm8916_bl31_setup.c [new file with mode: 0644]
plat/qti/msm8916/msm8916_pm.c [new file with mode: 0644]
plat/qti/msm8916/msm8916_topology.c [new file with mode: 0644]
plat/qti/msm8916/platform.mk [new file with mode: 0644]

diff --git a/plat/qti/msm8916/aarch64/msm8916_helpers.S b/plat/qti/msm8916/aarch64/msm8916_helpers.S
new file mode 100644 (file)
index 0000000..dad9968
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+#include <msm8916_mmap.h>
+
+#define APCS_TCM_START_ADDR    0x10
+#define APCS_TCM_REDIRECT_EN_0 BIT_32(0)
+
+       .globl  plat_crash_console_init
+       .globl  plat_crash_console_putc
+       .globl  plat_crash_console_flush
+       .globl  plat_panic_handler
+       .globl  plat_my_core_pos
+       .globl  plat_get_my_entrypoint
+       .globl  plat_reset_handler
+       .globl  platform_mem_init
+       .globl  msm8916_entry_point
+
+       /* -------------------------------------------------
+        * int plat_crash_console_init(void)
+        * Initialize the crash console.
+        * Out: x0 - 1 on success, 0 on error
+        * Clobber list : x0 - x4
+        * -------------------------------------------------
+        */
+func plat_crash_console_init
+       mov     x1, #BLSP_UART2_BASE
+
+       /*
+        * If the non-secure world has been actively using the UART there might
+        * be still some characters left to be sent in the FIFO. In that case,
+        * resetting the transmitter too early might cause all output to become
+        * corrupted. To avoid that, try to flush (wait until FIFO empty) first.
+        */
+       mov     x4, lr
+       bl      console_uartdm_core_flush
+       mov     lr, x4
+
+       mov     x0, #1
+       b       console_uartdm_core_init
+endfunc plat_crash_console_init
+
+       /* -------------------------------------------------
+        * int plat_crash_console_putc(int c)
+        * Print a character on the crash console.
+        * In : w0 - character to be printed
+        * Out: w0 - printed character on success
+        * Clobber list : x1, x2
+        * -------------------------------------------------
+        */
+func plat_crash_console_putc
+       mov     x1, #BLSP_UART2_BASE
+       b       console_uartdm_core_putc
+endfunc plat_crash_console_putc
+
+       /* -------------------------------------------------
+        * void plat_crash_console_flush(void)
+        * Force a write of all buffered data that has not
+        * been output.
+        * Clobber list : x1, x2
+        * -------------------------------------------------
+        */
+func plat_crash_console_flush
+       mov     x1, #BLSP_UART2_BASE
+       b       console_uartdm_core_flush
+endfunc plat_crash_console_flush
+
+       /* -------------------------------------------------
+        * void plat_panic_handler(void) __dead
+        * Called when an unrecoverable error occurs.
+        * -------------------------------------------------
+        */
+func plat_panic_handler
+       /* Try to shutdown/reset */
+       mov_imm x0, MPM_PS_HOLD
+       str     wzr, [x0]
+1:     b       1b
+endfunc plat_panic_handler
+
+       /* -------------------------------------------------
+        * unsigned int plat_my_core_pos(void)
+        * Out: x0 - index of the calling CPU
+        * -------------------------------------------------
+        */
+func plat_my_core_pos
+       /* There is just a single cluster so this is very simple */
+       mrs     x0, mpidr_el1
+       and     x0, x0, #MPIDR_CPU_MASK
+       ret
+endfunc plat_my_core_pos
+
+       /* -------------------------------------------------
+        * uintptr_t plat_get_my_entrypoint(void)
+        * Distinguish cold and warm boot and return warm boot
+        * entry address if available.
+        * Out: x0 - warm boot entry point or 0 on cold boot
+        * -------------------------------------------------
+        */
+func plat_get_my_entrypoint
+       ldr     x0, msm8916_entry_point
+       ret
+endfunc plat_get_my_entrypoint
+
+       /* -------------------------------------------------
+        * void plat_reset_handler(void)
+        * Perform additional initialization after reset.
+        * Clobber list : x0 - x18, x30
+        * -------------------------------------------------
+        */
+func plat_reset_handler
+       /*
+        * Check if the CPU is running at the correct address.
+        * During cold boot the CPU enters here at the wrong address
+        * using the "boot remapper". (It remaps the BL31_BASE to
+        * the CPU reset address 0x0).
+        */
+       mov     x0, #BL31_BASE
+       adr     x1, bl31_entrypoint
+       cmp     x0, x1
+       b.ne    _remapped_cold_boot
+       /* Already running at correct address, just return directly */
+       ret
+
+_remapped_cold_boot:
+       /*
+        * The previous boot stage seems to use the L2 cache as TCM.
+        * Disable the TCM redirect before enabling caches to avoid
+        * strange crashes.
+        */
+       mov     x2, #APCS_CFG
+       ldr     w3, [x2, #APCS_TCM_START_ADDR]
+       and     w3, w3, #~APCS_TCM_REDIRECT_EN_0
+       str     w3, [x2, #APCS_TCM_START_ADDR]
+
+       /* Enter BL31 again at the real address */
+       br      x0
+endfunc plat_reset_handler
+
+       /* -------------------------------------------------
+        * void platform_mem_init(void)
+        * Performs additional memory initialization early
+        * in the boot process.
+        * -------------------------------------------------
+        */
+func platform_mem_init
+       /* Nothing to do here, all memory is already initialized */
+       ret
+endfunc platform_mem_init
+
+       .data
+       .align  3
+
+       /* -------------------------------------------------
+        * Warm boot entry point for CPU. Set by PSCI code.
+        * -------------------------------------------------
+        */
+msm8916_entry_point:
+       .quad   0
diff --git a/plat/qti/msm8916/aarch64/uartdm_console.S b/plat/qti/msm8916/aarch64/uartdm_console.S
new file mode 100644 (file)
index 0000000..c69c193
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * Based on aarch64/skeleton_console.S:
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <console_macros.S>
+
+/* UART DM registers */
+#define UART_DM_DMEN           0x03c           /* DMA / data packing */
+#define UART_DM_SR             0x0a4           /* status register */
+#define UART_DM_CR             0x0a8           /* command register */
+#define UART_DM_TF             0x100           /* transmit FIFO */
+
+#define UART_DM_DMEN_TX_SC     BIT_32(4)       /* TX single character mode */
+
+#define UART_DM_SR_TXRDY_BIT   2               /* TX FIFO has space */
+#define UART_DM_SR_TXEMT_BIT   3               /* TX FIFO is empty */
+
+#define UART_DM_CR_RESET_RX    (U(0x01) << 4)  /* reset receiver */
+#define UART_DM_CR_RESET_TX    (U(0x02) << 4)  /* reset transmitter */
+#define UART_DM_CR_TX_ENABLE   BIT_32(2)       /* enable transmitter */
+
+       .globl  console_uartdm_register
+       .globl  console_uartdm_core_init
+       .globl  console_uartdm_putc
+       .globl  console_uartdm_core_putc
+       .globl  console_uartdm_flush
+       .globl  console_uartdm_core_flush
+
+       /* -----------------------------------------------------------
+        * int console_uartdm_register(console_t *console,
+        *      uintptr_t base_addr)
+        * Function to initialize and register the console. The caller
+        * needs to pass an empty console_t structure in which *MUST*
+        * be allocated in persistent memory (e.g. a global or static
+        * local variable, *NOT* on the stack).
+        * In : x0 - pointer to empty console_t structure
+        *      x1 - base address
+        * Out: x0 - 1 on success, 0 on error
+        * Clobber list : x0 - x7
+        * -----------------------------------------------------------
+        */
+func console_uartdm_register
+       str     x1, [x0, #CONSOLE_T_BASE]
+       mov     x7, lr
+       bl      console_uartdm_core_init
+       mov     lr, x7
+
+       /* Register the new console */
+       finish_console_register uartdm putc=1, flush=1
+endfunc console_uartdm_register
+
+       /* -----------------------------------------------------------
+        * void console_uartdm_core_init(unused, uintptr_t base_addr)
+        * Function to initialize the console.
+        * In : x0 - unused
+        *      x1 - base address
+        * Out: void
+        * Clobber list : x1, x2, x3
+        * -----------------------------------------------------------
+        */
+func console_uartdm_core_init
+       /* Reset receiver */
+       mov     w3, #UART_DM_CR_RESET_RX
+       str     w3, [x1, #UART_DM_CR]
+
+       /* Reset transmitter */
+       mov     w3, #UART_DM_CR_RESET_TX
+       str     w3, [x1, #UART_DM_CR]
+
+       /*
+        * Disable BAM/DMA modes but enable single-character mode for TX.
+        * The single character mode allows simplifying the putc implementation
+        * since characters can be written directly to the FIFO instead of
+        * having to initiate a new transfer and waiting for its completion.
+        */
+       mov     w3, #UART_DM_DMEN_TX_SC
+       str     w3, [x1, #UART_DM_DMEN]
+
+       /* Enable transmitter */
+       mov     w3, #UART_DM_CR_TX_ENABLE
+       str     w3, [x1, #UART_DM_CR]
+
+       ret
+endfunc console_uartdm_core_init
+
+       /* -----------------------------------------------------------
+        * int console_uartdm_putc(int c, console_t *console)
+        * Function to output a character over the console.
+        * In : w0 - character to be printed
+        *      x1 - pointer to console_t struct
+        * Out: w0 - printed character on success, < 0 on error.
+        * Clobber list : x0, x1, x2
+        * -----------------------------------------------------------
+        */
+func console_uartdm_putc
+       ldr     x1, [x1, #CONSOLE_T_BASE]
+       b       console_uartdm_core_putc
+endfunc console_uartdm_putc
+
+       /* -----------------------------------------------------------
+        * int console_uartdm_core_putc(int c, uintptr_t base_addr)
+        * Function to output a character over the console.
+        * In : w0 - character to be printed
+        *      x1 - base address
+        * Out: w0 - printed character on success, < 0 on error.
+        * Clobber list : x2
+        * -----------------------------------------------------------
+        */
+func console_uartdm_core_putc
+1:     /* Loop until TX FIFO has space */
+       ldr     w2, [x1, #UART_DM_SR]
+       tbz     w2, #UART_DM_SR_TXRDY_BIT, 1b
+
+       /* Write character to FIFO */
+       str     w0, [x1, #UART_DM_TF]
+       ret
+endfunc console_uartdm_core_putc
+
+       /* -----------------------------------------------------------
+        * void console_uartdm_flush(console_t *console)
+        * Function to force a write of all buffered data
+        * that has not been output.
+        * In : x0 - pointer to console_t struct
+        * Out: void
+        * Clobber list : x0, x1, x2, x3, x4, x5
+        * -----------------------------------------------------------
+        */
+func console_uartdm_flush
+       ldr     x1, [x0, #CONSOLE_T_BASE]
+       b       console_uartdm_core_flush
+endfunc console_uartdm_flush
+
+       /* -----------------------------------------------------------
+        * void console_uartdm_core_flush(unused, uintptr_t base_addr)
+        * Function to force a write of all buffered data
+        * that has not been output.
+        * In : x0 - unused
+        *      x1 - base address
+        * Out: void
+        * Clobber list : x2
+        * -----------------------------------------------------------
+        */
+func console_uartdm_core_flush
+1:     /* Loop until TX FIFO is empty */
+       ldr     w2, [x1, #UART_DM_SR]
+       tbz     w2, #UART_DM_SR_TXEMT_BIT, 1b
+       ret
+endfunc console_uartdm_core_flush
diff --git a/plat/qti/msm8916/include/msm8916_mmap.h b/plat/qti/msm8916/include/msm8916_mmap.h
new file mode 100644 (file)
index 0000000..1696b84
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MSM8916_MMAP_H
+#define MSM8916_MMAP_H
+
+#define PCNOC_BASE             0x00000000
+#define PCNOC_SIZE             0x8000000       /* 128 MiB */
+#define APCS_BASE              0x0b000000
+#define APCS_SIZE              0x800000        /* 8 MiB */
+
+#define MPM_BASE               (PCNOC_BASE + 0x04a0000)
+#define MPM_PS_HOLD            (MPM_BASE + 0xb000)
+
+#define TLMM_BASE              (PCNOC_BASE + 0x1000000)
+#define TLMM_GPIO_CFG(n)       (TLMM_BASE + ((n) * 0x1000))
+
+#define GCC_BASE               (PCNOC_BASE + 0x1800000)
+
+#define BLSP_UART1_BASE                (PCNOC_BASE + 0x78af000)
+#define BLSP_UART2_BASE                (PCNOC_BASE + 0x78b0000)
+
+#define APCS_QGIC2_BASE                (APCS_BASE + 0x00000)
+#define APCS_QGIC2_GICD                (APCS_QGIC2_BASE + 0x0000)
+#define APCS_QGIC2_GICC                (APCS_QGIC2_BASE + 0x2000)
+#define APCS_BANKED_ACS                (APCS_BASE + 0x08000)
+#define APCS_BANKED_SAW2       (APCS_BASE + 0x09000)
+#define APCS_CFG               (APCS_BASE + 0x10000)
+#define APCS_GLB               (APCS_BASE + 0x11000)
+#define APCS_L2_SAW2           (APCS_BASE + 0x12000)
+#define APCS_QTMR              (APCS_BASE + 0x20000)
+#define APCS_ALIAS_ACS(cpu)    (APCS_BASE + 0x88000 + ((cpu) * 0x10000))
+#define APCS_ALIAS_SAW2(cpu)   (APCS_BASE + 0x89000 + ((cpu) * 0x10000))
+
+#endif /* MSM8916_MMAP_H */
diff --git a/plat/qti/msm8916/include/plat_macros.S b/plat/qti/msm8916/include/plat_macros.S
new file mode 100644 (file)
index 0000000..552add2
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+
+#include <msm8916_mmap.h>
+
+       /* ---------------------------------------------
+        * The below required platform porting macro
+        * prints out relevant GIC registers whenever
+        * an unhandled exception is taken in BL31.
+        * Clobbers: x0 - x10, x16, x17, sp
+        * ---------------------------------------------
+        */
+       .macro plat_crash_print_regs
+       mov_imm x16, APCS_QGIC2_GICD
+       mov_imm x17, APCS_QGIC2_GICC
+       arm_print_gic_regs
+       .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/qti/msm8916/include/platform_def.h b/plat/qti/msm8916/include/platform_def.h
new file mode 100644 (file)
index 0000000..4ad26dd
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat/common/common_def.h>
+
+/*
+ * There is at least 1 MiB available for BL31. However, at the moment the
+ * "msm8916_entry_point" variable in the data section is read through the
+ * 64 KiB region of the "boot remapper" after reset. For simplicity, limit
+ * the end of the data section (BL31_PROGBITS_LIMIT) to 64 KiB for now and
+ * the overall limit to 128 KiB. This could be increased if needed by placing
+ * the "msm8916_entry_point" variable explicitly in the first 64 KiB of BL31.
+ */
+#define BL31_LIMIT                     (BL31_BASE + 0x20000)   /* 128 KiB */
+#define BL31_PROGBITS_LIMIT            (BL31_BASE + 0x10000)   /* 64 KiB */
+
+#define CACHE_WRITEBACK_GRANULE                U(64)
+#define PLATFORM_STACK_SIZE            U(0x1000)
+
+/* CPU topology: single cluster with 4 cores */
+#define PLATFORM_CLUSTER_COUNT         U(1)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER  U(4)
+#define PLATFORM_CORE_COUNT            (PLATFORM_CLUSTER_COUNT * \
+                                        PLATFORM_MAX_CPUS_PER_CLUSTER)
+
+/* Power management */
+#define PLATFORM_SYSTEM_COUNT          U(1)
+#define PLAT_NUM_PWR_DOMAINS           (PLATFORM_SYSTEM_COUNT + \
+                                        PLATFORM_CLUSTER_COUNT + \
+                                        PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL               MPIDR_AFFLVL2
+#define PLAT_MAX_RET_STATE             U(2)
+#define PLAT_MAX_OFF_STATE             U(3)
+
+/* Translation tables */
+#define MAX_MMAP_REGIONS               8
+#define MAX_XLAT_TABLES                        4
+
+#define PLAT_PHY_ADDR_SPACE_SIZE       (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE      (ULL(1) << 32)
+
+/* Timer frequency */
+#define PLAT_SYSCNT_FREQ               19200000
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/msm8916/include/uartdm_console.h b/plat/qti/msm8916/include/uartdm_console.h
new file mode 100644 (file)
index 0000000..0f09ba8
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UARTDM_CONSOLE_H
+#define UARTDM_CONSOLE_H
+
+int console_uartdm_register(console_t *console, uintptr_t base_addr);
+
+#endif /* UARTDM_CONSOLE_H */
diff --git a/plat/qti/msm8916/msm8916_bl31_setup.c b/plat/qti/msm8916/msm8916_bl31_setup.c
new file mode 100644 (file)
index 0000000..a27549e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <msm8916_mmap.h>
+#include <platform_def.h>
+#include <uartdm_console.h>
+
+static const mmap_region_t msm8916_mmap[] = {
+       MAP_REGION_FLAT(PCNOC_BASE, PCNOC_SIZE,
+                       MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
+       MAP_REGION_FLAT(APCS_BASE, APCS_SIZE,
+                       MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
+       {},
+};
+
+static struct {
+       entry_point_info_t bl32;
+       entry_point_info_t bl33;
+} image_ep_info = {
+       /* BL32 entry point */
+       SET_STATIC_PARAM_HEAD(bl32, PARAM_EP, VERSION_1,
+                             entry_point_info_t, SECURE),
+       .bl32.pc = BL32_BASE,
+
+       /* BL33 entry point */
+       SET_STATIC_PARAM_HEAD(bl33, PARAM_EP, VERSION_1,
+                             entry_point_info_t, NON_SECURE),
+       .bl33.pc = PRELOADED_BL33_BASE,
+       .bl33.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS),
+};
+
+static console_t console;
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+       return PLAT_SYSCNT_FREQ;
+}
+
+#define CLK_ENABLE                     BIT_32(0)
+#define CLK_OFF                                BIT_32(31)
+
+#define GPIO_BLSP_UART2_TX             4
+#define GPIO_BLSP_UART2_RX             5
+#define GPIO_CFG_FUNC_BLSP_UART2       (U(0x2) << 2)
+#define GPIO_CFG_DRV_STRENGTH_16MA     (U(0x7) << 6)
+
+#define GCC_BLSP1_AHB_CBCR             (GCC_BASE + 0x01008)
+#define GCC_BLSP1_UART2_APPS_CBCR      (GCC_BASE + 0x0302c)
+#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x45004)
+#define BLSP1_AHB_CLK_ENA              BIT_32(10)
+
+/*
+ * The previous boot stage seems to disable most of the UART setup before exit
+ * so it must be enabled here again before the UART console can be used.
+ */
+static void msm8916_enable_blsp_uart2(void)
+{
+       /* Route GPIOs to BLSP UART2 */
+       mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_TX),
+                     GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA);
+       mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_RX),
+                     GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA);
+
+       /* Enable AHB clock */
+       mmio_setbits_32(GCC_APCS_CLOCK_BRANCH_ENA_VOTE, BLSP1_AHB_CLK_ENA);
+       while (mmio_read_32(GCC_BLSP1_AHB_CBCR) & CLK_OFF)
+               ;
+
+       /* Enable BLSP UART2 clock */
+       mmio_setbits_32(GCC_BLSP1_UART2_APPS_CBCR, CLK_ENABLE);
+       while (mmio_read_32(GCC_BLSP1_UART2_APPS_CBCR) & CLK_OFF)
+               ;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+                               u_register_t arg2, u_register_t arg3)
+{
+       /* Initialize the debug console as early as possible */
+       msm8916_enable_blsp_uart2();
+       console_uartdm_register(&console, BLSP_UART2_BASE);
+}
+
+void bl31_plat_arch_setup(void)
+{
+       mmap_add_region(BL31_BASE, BL31_BASE, BL31_END - BL31_BASE,
+                       MT_RW_DATA | MT_SECURE);
+       mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+                       BL_CODE_END - BL_CODE_BASE,
+                       MT_CODE | MT_SECURE);
+       mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+                       BL_RO_DATA_END - BL_RO_DATA_BASE,
+                       MT_RO_DATA | MT_SECURE);
+       mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+                       BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+                       MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER);
+
+       mmap_add(msm8916_mmap);
+       init_xlat_tables();
+       enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+       generic_delay_timer_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+       switch (type) {
+       case SECURE:
+               return &image_ep_info.bl32;
+       case NON_SECURE:
+               return &image_ep_info.bl33;
+       default:
+               assert(sec_state_is_valid(type));
+               return NULL;
+       }
+}
diff --git a/plat/qti/msm8916/msm8916_pm.c b/plat/qti/msm8916/msm8916_pm.c
new file mode 100644 (file)
index 0000000..c9a40f5
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <msm8916_mmap.h>
+
+static void __dead2 msm8916_system_reset(void)
+{
+       mmio_write_32(MPM_PS_HOLD, 0);
+       mdelay(1000);
+
+       ERROR("PSCI: System reset failed\n");
+       panic();
+}
+
+static const plat_psci_ops_t msm8916_psci_ops = {
+       .system_off                     = msm8916_system_reset,
+       .system_reset                   = msm8916_system_reset,
+};
+
+/* Defined and used in msm8916_helpers.S */
+extern uintptr_t msm8916_entry_point;
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+                       const plat_psci_ops_t **psci_ops)
+{
+       msm8916_entry_point = sec_entrypoint;
+       *psci_ops = &msm8916_psci_ops;
+       return 0;
+}
diff --git a/plat/qti/msm8916/msm8916_topology.c b/plat/qti/msm8916/msm8916_topology.c
new file mode 100644 (file)
index 0000000..4d0ed8f
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+static const unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = {
+       PLATFORM_SYSTEM_COUNT,
+       PLATFORM_CLUSTER_COUNT,
+       PLATFORM_MAX_CPUS_PER_CLUSTER,
+};
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+       unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+       if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+           MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
+           MPIDR_AFFLVL1_VAL(mpidr) > 0 ||
+           core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+               return -1;
+       }
+
+       return core;
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+       return plat_power_domain_tree_desc;
+}
diff --git a/plat/qti/msm8916/platform.mk b/plat/qti/msm8916/platform.mk
new file mode 100644 (file)
index 0000000..2d199e0
--- /dev/null
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include drivers/arm/gic/v2/gicv2.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS}
+
+PLAT_INCLUDES  :=      -Iinclude/plat/arm/common/${ARCH}               \
+                       -Iplat/qti/msm8916/include
+
+BL31_SOURCES   +=      ${GICV2_SOURCES}                                \
+                       drivers/delay_timer/delay_timer.c               \
+                       drivers/delay_timer/generic_delay_timer.c       \
+                       lib/cpus/${ARCH}/cortex_a53.S                   \
+                       plat/common/plat_gicv2.c                        \
+                       plat/common/plat_psci_common.c                  \
+                       plat/qti/msm8916/msm8916_bl31_setup.c           \
+                       plat/qti/msm8916/msm8916_pm.c                   \
+                       plat/qti/msm8916/msm8916_topology.c             \
+                       plat/qti/msm8916/${ARCH}/msm8916_helpers.S      \
+                       plat/qti/msm8916/${ARCH}/uartdm_console.S
+
+# Only BL31 is supported at the moment and is entered on a single CPU
+RESET_TO_BL31                  := 1
+COLD_BOOT_SINGLE_CPU           := 1
+
+# Build config flags
+# ------------------
+BL31_BASE                      ?= 0x86500000
+BL32_BASE                      ?= 0x86000000
+PRELOADED_BL33_BASE            ?= 0x8f600000
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA       := 1
+
+# Single cluster
+WARMBOOT_ENABLE_DCACHE_EARLY   := 1
+
+# Disable features unsupported in ARMv8.0
+ENABLE_AMU                     := 0
+ENABLE_SPE_FOR_LOWER_ELS       := 0
+ENABLE_SVE_FOR_NS              := 0
+
+# MSM8916 uses ARM Cortex-A53 r0p0 so likely all the errata apply
+ERRATA_A53_819472              := 1
+ERRATA_A53_824069              := 1
+ERRATA_A53_826319              := 1
+ERRATA_A53_827319              := 1
+ERRATA_A53_835769              := 1
+ERRATA_A53_836870              := 1
+ERRATA_A53_843419              := 1
+ERRATA_A53_855873              := 0    # Workaround works only for >= r0p3
+ERRATA_A53_1530924             := 1
+
+$(eval $(call add_define,BL31_BASE))
+$(eval $(call add_define,BL32_BASE))