Merge changes from topic "msm8916-spmin" into integration
* changes:
docs(msm8916): document new build options
feat(msm8916): allow selecting which UART to use
feat(msm8916): add SP_MIN port for AArch32
refactor(msm8916): detect cold boot in plat_get_my_entrypoint
feat(msm8916): add Test Secure Payload (TSP) port
build(msm8916): place bl32 directly after bl31
refactor(msm8916): separate common platform setup code
diff --git a/docs/plat/qti-msm8916.rst b/docs/plat/qti-msm8916.rst
index 09a79b7..d7c3642 100644
--- a/docs/plat/qti-msm8916.rst
+++ b/docs/plat/qti-msm8916.rst
@@ -7,7 +7,7 @@
is the `DragonBoard 410c`_ single-board computer, but the SoC is also used in
various mid-range smartphones/tablets.
-The TF-A/BL31 port for MSM8916 provides a minimal, community-maintained
+The TF-A port for MSM8916 provides a minimal, community-maintained
EL3 firmware. It is primarily based on information from the public
`Snapdragon 410E Technical Reference Manual`_ combined with a lot of
trial and error to actually make it work.
@@ -20,8 +20,7 @@
Functionality
-------------
-
-The BL31 port is much more minimal compared to the original firmware and
+The TF-A port is much more minimal compared to the original firmware and
therefore expects the non-secure world (e.g. Linux) to manage more hardware,
such as the SMMUs and all remote processors (RPM, WCNSS, Venus, Modem).
Everything except modem is currently functional with a slightly modified version
@@ -41,28 +40,74 @@
Boot Flow
---------
-BL31 replaces the original ``tz`` firmware in the boot flow::
+BL31 (AArch64) or BL32/SP_MIN (AArch32) replaces the original ``tz`` firmware
+in the boot flow::
Boot ROM (PBL) -> SBL -> BL31 (EL3) -> U-Boot (EL2) -> Linux (EL2)
-By default, BL31 enters the non-secure world in EL2 AArch64 state at address
-``0x8f600000``. The original hypervisor firmware (``hyp``) is not used, you can
-use KVM or another hypervisor. The entry address is fixed in the BL31 binary
-but can be changed using the ``PRELOADED_BL33_BASE`` make file parameter.
+After initialization the normal world starts at a fixed entry address in EL2/HYP
+mode, configured using ``PRELOADED_BL33_BASE``. At runtime, it is expected that
+the normal world bootloader was already loaded into RAM by a previous firmware
+component (usually SBL) and that it is capable of running in EL2/HYP mode.
-Using an AArch64 bootloader (such as `U-Boot for DragonBoard 410c`_) is
-recommended. AArch32 bootloaders (such as the original Little Kernel bootloader
-from Qualcomm) are not directly supported, although it is possible to use an EL2
-shim loader to temporarily switch to AArch32 state.
+`U-Boot for DragonBoard 410c`_ is recommended if possible. The original Little
+Kernel-based bootloader from Qualcomm does not support EL2/HYP, but can be
+booted using an additional shim loader such as `tfalkstub`_.
+
+Build
+-----
+It is possible to build for either AArch64 or AArch32. AArch64 is the preferred
+build option.
+
+AArch64 (BL31)
+^^^^^^^^^^^^^^
+Setup the cross compiler for AArch64 and build BL31 for ``msm8916``::
+
+ $ make CROSS_COMPILE=aarch64-none-elf- PLAT=msm8916
+
+The BL31 ELF image is generated in ``build/msm8916/release/bl31/bl31.elf``.
+
+AArch32 (BL32/SP_MIN)
+^^^^^^^^^^^^^^^^^^^^^
+Setup the cross compiler for AArch32 and build BL32 with SP_MIN for ``msm8916``::
+
+ $ make CROSS_COMPILE=arm-none-eabi- PLAT=msm8916 ARCH=aarch32 AARCH32_SP=sp_min
+
+The BL32 ELF image is generated in ``build/msm8916/release/bl32/bl32.elf``.
+
+Build Options
+-------------
+Some options can be changed at build time by adding them to the make command line:
+
+ * ``QTI_UART_NUM``: Number of UART controller to use for debug output and crash
+ reports. This must be the same UART as used by earlier boot firmware since
+ the UART controller does not get fully initialized at the moment. Defaults to
+ the usual debug UART used for the platform (see ``platform.mk``).
+ * ``QTI_RUNTIME_UART``: By default (``0``) the UART is only used for the boot
+ process and critical crashes. If set to ``1`` it is also used for runtime
+ messages. Note that this option can only be used if the UART is reserved in
+ the normal world and the necessary clocks remain enabled.
+
+The memory region used for the different firmware components is not fixed and
+can be changed on the make command line. The default values match the addresses
+used by the original firmware (see ``platform.mk``):
+
+ * ``PRELOADED_BL33_BASE``: The entry address for the normal world. Usually
+ refers to the first bootloader (e.g. U-Boot).
+ * ``BL31_BASE``: Base address for the BL31 firmware component. Must point to
+ a 64K-aligned memory region with at least 128 KiB space that is permanently
+ reserved in the normal world.
+ * ``BL32_BASE``: Base address for the BL32 firmware component.
+
+ * **AArch32:** BL32 is used in place of BL31, so the option is equivalent to
+ ``BL31_BASE``.
+ * **AArch64:** Secure-EL1 Payload. Defaults to using 128 KiB of space
+ directly after BL31. For testing only, the port is primarily intended as
+ a minimal PSCI implementation without a separate secure world.
Installation
------------
-First, setup the cross compiler for AArch64 and build TF-A for ``msm8916``::
-
- $ make CROSS_COMPILE=aarch64-linux-gnu- PLAT=msm8916
-
-The BL31 ELF image is generated in ``build/msm8916/release/bl31/bl31.elf``.
-This image must be "signed" before flashing it, even if the board has secure
+The ELF image must be "signed" before flashing it, even if the board has secure
boot disabled. In this case the signature does not provide any security,
but it provides the firmware with required metadata.
@@ -75,6 +120,10 @@
Then install the resulting ``build/msm8916/release/bl31/bl31-test-signed.mbn``
to the ``tz`` partition on the device. BL31 should be running after a reboot.
+.. note::
+ On AArch32 the ELF image is called ``bl32.elf``.
+ The installation procedure is identical.
+
.. warning::
Do not flash incorrectly signed firmware on devices that have secure
boot enabled! Make sure that you have a way to recover the board in case
@@ -82,8 +131,11 @@
Boot Trace
----------
-BL31 prints some lines on the debug console UART2, which will usually look like
-this (with ``DEBUG=1``, otherwise only the ``NOTICE`` lines are shown)::
+
+AArch64 (BL31)
+^^^^^^^^^^^^^^
+BL31 prints some lines on the debug console, which will usually look like this
+(with ``DEBUG=1``, otherwise only the ``NOTICE`` lines are shown)::
...
S - DDR Frequency, 400 MHz
@@ -109,8 +161,34 @@
Qualcomm-DragonBoard 410C
...
+AArch32 (BL32/SP_MIN)
+^^^^^^^^^^^^^^^^^^^^^
+BL32/SP_MIN prints some lines on the debug console, which will usually look like
+this (with ``DEBUG=1``, otherwise only the ``NOTICE`` lines are shown)::
+
+ ...
+ S - DDR Frequency, 400 MHz
+ NOTICE: SP_MIN: v2.8(debug):v2.8
+ NOTICE: SP_MIN: Built : 23:03:31, Mar 31 2023
+ INFO: SP_MIN: Platform setup start
+ INFO: ARM GICv2 driver initialized
+ INFO: SP_MIN: Platform setup done
+ INFO: SP_MIN: Initializing runtime services
+ INFO: BL32: cortex_a53: CPU workaround for 819472 was applied
+ INFO: BL32: cortex_a53: CPU workaround for 824069 was applied
+ INFO: BL32: cortex_a53: CPU workaround for 826319 was applied
+ INFO: BL32: cortex_a53: CPU workaround for 827319 was applied
+ INFO: BL32: cortex_a53: CPU workaround for disable_non_temporal_hint was applied
+ INFO: SP_MIN: Preparing exit to normal world
+ INFO: Entry point address = 0x86400000
+ INFO: SPSR = 0x1da
+ Android Bootloader - UART_DM Initialized!!!
+ [0] welcome to lk
+ ...
+
.. _Qualcomm Snapdragon 410: https://www.qualcomm.com/products/snapdragon-processors-410
.. _DragonBoard 410c: https://www.96boards.org/product/dragonboard410c/
.. _Snapdragon 410E Technical Reference Manual: https://developer.qualcomm.com/download/sd410/snapdragon-410e-technical-reference-manual.pdf
.. _U-Boot for DragonBoard 410c: https://u-boot.readthedocs.io/en/latest/board/qualcomm/dragonboard410c.html
.. _qtestsign: https://github.com/msm8916-mainline/qtestsign
+.. _tfalkstub: https://github.com/msm8916-mainline/tfalkstub
diff --git a/plat/qti/msm8916/aarch32/msm8916_helpers.S b/plat/qti/msm8916/aarch32/msm8916_helpers.S
new file mode 100644
index 0000000..ea39663
--- /dev/null
+++ b/plat/qti/msm8916/aarch32/msm8916_helpers.S
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2021-2023, 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: r0 - 1 on success, 0 on error
+ * Clobber list : r0 - r4
+ * -------------------------------------------------
+ */
+func plat_crash_console_init
+ ldr r1, =BLSP_UART_BASE
+ mov r0, #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 : r0 - character to be printed
+ * Out: r0 - printed character on success
+ * Clobber list : r1, r2
+ * -------------------------------------------------
+ */
+func plat_crash_console_putc
+ ldr r1, =BLSP_UART_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 : r1, r2
+ * -------------------------------------------------
+ */
+func plat_crash_console_flush
+ ldr r1, =BLSP_UART_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 */
+ ldr r0, =MPM_PS_HOLD
+ mov r1, #0
+ str r1, [r0]
+1: b 1b
+endfunc plat_panic_handler
+
+ /* -------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * Out: r0 - index of the calling CPU
+ * -------------------------------------------------
+ */
+func plat_my_core_pos
+ /* There is just a single cluster so this is very simple */
+ ldcopr r0, MPIDR
+ and r0, r0, #MPIDR_CPU_MASK
+ bx lr
+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: r0 - warm boot entry point or 0 on cold boot
+ * -------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ ldr r0, =msm8916_entry_point
+ ldr r0, [r0]
+ cmp r0, #0
+ bxne lr
+
+ /*
+ * Cold boot: Disable TCM redirect to L2 cache as early as
+ * possible to avoid crashes when making use of the cache.
+ */
+ ldr r1, =APCS_CFG
+ ldr r2, [r1, #APCS_TCM_START_ADDR]
+ and r2, r2, #~APCS_TCM_REDIRECT_EN_0
+ str r2, [r1, #APCS_TCM_START_ADDR]
+ bx lr
+endfunc plat_get_my_entrypoint
+
+ /* -------------------------------------------------
+ * 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 */
+ bx lr
+endfunc platform_mem_init
+
+ .data
+ .align 3
+
+ /* -------------------------------------------------
+ * Warm boot entry point for CPU. Set by PSCI code.
+ * -------------------------------------------------
+ */
+msm8916_entry_point:
+ .word 0
diff --git a/plat/qti/msm8916/aarch32/uartdm_console.S b/plat/qti/msm8916/aarch32/uartdm_console.S
new file mode 100644
index 0000000..a19776a
--- /dev/null
+++ b/plat/qti/msm8916/aarch32/uartdm_console.S
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * Based on aarch32/skeleton_console.S:
+ * Copyright (c) 2016-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_32(2) /* TX FIFO has space */
+#define UART_DM_SR_TXEMT BIT_32(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 : r0 - pointer to empty console_t structure
+ * r1 - base address
+ * Out: r0 - 1 on success, 0 on error
+ * Clobber list : r0 - r7
+ * -----------------------------------------------------------
+ */
+func console_uartdm_register
+ str r1, [r0, #CONSOLE_T_BASE]
+ mov r7, lr
+ bl console_uartdm_core_init
+ mov lr, r7
+
+ /* 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 : r0 - unused
+ * r1 - base address
+ * Out: void
+ * Clobber list : r1, r2, r3
+ * -----------------------------------------------------------
+ */
+func console_uartdm_core_init
+ /*
+ * Try to flush remaining characters from the TX FIFO before resetting
+ * the transmitter. Unfortunately there is no good way to check if
+ * the transmitter is actually enabled (and will finish eventually),
+ * so use a timeout to avoid looping forever.
+ */
+ mov r2, #65536
+1:
+ ldr r3, [r1, #UART_DM_SR]
+ tst r3, #UART_DM_SR_TXEMT
+ bne 2f
+ subs r2, r2, #1
+ bne 1b
+ /* Timeout */
+
+2: /* Reset receiver */
+ mov r3, #UART_DM_CR_RESET_RX
+ str r3, [r1, #UART_DM_CR]
+
+ /* Reset transmitter */
+ mov r3, #UART_DM_CR_RESET_TX
+ str r3, [r1, #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 r3, #UART_DM_DMEN_TX_SC
+ str r3, [r1, #UART_DM_DMEN]
+
+ /* Enable transmitter */
+ mov r3, #UART_DM_CR_TX_ENABLE
+ str r3, [r1, #UART_DM_CR]
+
+ bx lr
+endfunc console_uartdm_core_init
+
+ /* -----------------------------------------------------------
+ * int console_uartdm_putc(int c, console_t *console)
+ * Function to output a character over the console.
+ * In : r0 - character to be printed
+ * r1 - pointer to console_t struct
+ * Out: r0 - printed character on success, < 0 on error.
+ * Clobber list : r0, r1, r2
+ * -----------------------------------------------------------
+ */
+func console_uartdm_putc
+ ldr r1, [r1, #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 : r0 - character to be printed
+ * r1 - base address
+ * Out: r0 - printed character on success, < 0 on error.
+ * Clobber list : r2
+ * -----------------------------------------------------------
+ */
+func console_uartdm_core_putc
+ cmp r0, #'\n'
+ bne 2f
+
+1: /* Loop until TX FIFO has space */
+ ldr r2, [r1, #UART_DM_SR]
+ tst r2, #UART_DM_SR_TXRDY
+ beq 1b
+
+ /* Prepend '\r' to '\n' */
+ mov r2, #'\r'
+ str r2, [r1, #UART_DM_TF]
+
+2: /* Loop until TX FIFO has space */
+ ldr r2, [r1, #UART_DM_SR]
+ tst r2, #UART_DM_SR_TXRDY
+ beq 2b
+
+ /* Write character to FIFO */
+ str r0, [r1, #UART_DM_TF]
+ bx lr
+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 : r0 - pointer to console_t struct
+ * Out: void
+ * Clobber list : r0, r1, r2, r3, r4, r5
+ * -----------------------------------------------------------
+ */
+func console_uartdm_flush
+ ldr r1, [r0, #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 : r0 - unused
+ * r1 - base address
+ * Out: void
+ * Clobber list : r2
+ * -----------------------------------------------------------
+ */
+func console_uartdm_core_flush
+1: /* Loop until TX FIFO is empty */
+ ldr r2, [r1, #UART_DM_SR]
+ tst r2, #UART_DM_SR_TXEMT
+ beq 1b
+ bx lr
+endfunc console_uartdm_core_flush
diff --git a/plat/qti/msm8916/aarch64/msm8916_helpers.S b/plat/qti/msm8916/aarch64/msm8916_helpers.S
index 528c5a4..bccc5e5 100644
--- a/plat/qti/msm8916/aarch64/msm8916_helpers.S
+++ b/plat/qti/msm8916/aarch64/msm8916_helpers.S
@@ -30,7 +30,7 @@
* -------------------------------------------------
*/
func plat_crash_console_init
- mov x1, #BLSP_UART2_BASE
+ mov_imm x1, BLSP_UART_BASE
mov x0, #1
b console_uartdm_core_init
endfunc plat_crash_console_init
@@ -44,7 +44,7 @@
* -------------------------------------------------
*/
func plat_crash_console_putc
- mov x1, #BLSP_UART2_BASE
+ mov_imm x1, BLSP_UART_BASE
b console_uartdm_core_putc
endfunc plat_crash_console_putc
@@ -56,7 +56,7 @@
* -------------------------------------------------
*/
func plat_crash_console_flush
- mov x1, #BLSP_UART2_BASE
+ mov_imm x1, BLSP_UART_BASE
b console_uartdm_core_flush
endfunc plat_crash_console_flush
@@ -93,45 +93,44 @@
*/
func plat_get_my_entrypoint
ldr x0, msm8916_entry_point
+ cbz x0, 1f
+ ret
+1:
+ /*
+ * Cold boot: Disable TCM redirect to L2 cache as early as
+ * possible to avoid crashes when making use of the cache.
+ */
+ mov_imm x1, APCS_CFG
+ ldr w2, [x1, #APCS_TCM_START_ADDR]
+ and w2, w2, #~APCS_TCM_REDIRECT_EN_0
+ str w2, [x1, #APCS_TCM_START_ADDR]
+
+ /*
+ * After reset the CPU always starts executing at the fixed reset
+ * address (0x0), which does not match the link address of BL31.
+ * The "boot remapper" redirects all memory accesses to the real
+ * physical address in DRAM.
+ *
+ * For warm boots, this is already handled by loading the real
+ * entry point address above.
+ *
+ * For cold boots, check if the CPU is using the boot remapper,
+ * i.e. if bl31_entrypoint appears to be at the reset address (0x0).
+ */
+ adr x1, bl31_entrypoint
+ cbnz x1, 2f
+
+ /*
+ * Add the real BL31_BASE offset to the return address in the link
+ * register so the CPU will continue at the real address after return.
+ */
+ mov_imm x1, BL31_BASE
+ add lr, lr, x1
+2:
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.
diff --git a/plat/qti/msm8916/include/msm8916_mmap.h b/plat/qti/msm8916/include/msm8916_mmap.h
index d201536..35e3b86 100644
--- a/plat/qti/msm8916/include/msm8916_mmap.h
+++ b/plat/qti/msm8916/include/msm8916_mmap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,8 +23,9 @@
#define APPS_SMMU_BASE (PCNOC_BASE + 0x1e00000)
#define APPS_SMMU_QCOM (APPS_SMMU_BASE + 0xf0000)
-#define BLSP_UART1_BASE (PCNOC_BASE + 0x78af000)
-#define BLSP_UART2_BASE (PCNOC_BASE + 0x78b0000)
+#define BLSP1_BASE (PCNOC_BASE + 0x7880000)
+#define BLSP1_UART_BASE(n) (BLSP1_BASE + 0x2f000 + (((n) - 1) * 0x1000))
+#define BLSP_UART_BASE BLSP1_UART_BASE(QTI_UART_NUM)
#define APCS_QGIC2_BASE (APCS_BASE + 0x00000)
#define APCS_QGIC2_GICD (APCS_QGIC2_BASE + 0x0000)
diff --git a/plat/qti/msm8916/include/platform_def.h b/plat/qti/msm8916/include/platform_def.h
index 6d5ff2b..f6ba1cc 100644
--- a/plat/qti/msm8916/include/platform_def.h
+++ b/plat/qti/msm8916/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,7 @@
#include <plat/common/common_def.h>
+#ifdef __aarch64__
/*
* 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
@@ -18,6 +19,8 @@
*/
#define BL31_LIMIT (BL31_BASE + SZ_128K)
#define BL31_PROGBITS_LIMIT (BL31_BASE + SZ_64K)
+#endif
+#define BL32_LIMIT (BL32_BASE + SZ_128K)
#define CACHE_WRITEBACK_GRANULE U(64)
#define PLATFORM_STACK_SIZE SZ_4K
@@ -44,8 +47,9 @@
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
-/* Timer frequency */
+/* Timer */
#define PLAT_SYSCNT_FREQ 19200000
+#define IRQ_SEC_PHY_TIMER (16 + 2) /* PPI #2 */
/*
* The Qualcomm QGIC2 implementation seems to have PIDR0-4 and PIDR4-7
@@ -54,4 +58,9 @@
*/
#define GICD_PIDR2_GICV2 U(0xFD8)
+/* TSP */
+#define TSP_IRQ_SEC_PHY_TIMER IRQ_SEC_PHY_TIMER
+#define TSP_SEC_MEM_BASE BL32_BASE
+#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE)
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/msm8916/msm8916_bl31_setup.c b/plat/qti/msm8916/msm8916_bl31_setup.c
index 8cba5c5..449be7f 100644
--- a/plat/qti/msm8916/msm8916_bl31_setup.c
+++ b/plat/qti/msm8916/msm8916_bl31_setup.c
@@ -8,25 +8,10 @@
#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_gicv2.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),
- {},
-};
+#include "msm8916_config.h"
+#include "msm8916_setup.h"
static struct {
entry_point_info_t bl32;
@@ -44,160 +29,23 @@
.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);
+ msm8916_early_platform_setup();
}
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();
+ msm8916_plat_arch_setup(BL31_BASE, BL31_END - BL31_BASE);
enable_mmu_el3(0);
}
-static void msm8916_configure_timer(void)
-{
- /* Set timer frequency */
- mmio_write_32(APCS_QTMR + CNTCTLBASE_CNTFRQ, plat_get_syscnt_freq2());
-
- /* Make all timer frames available to non-secure world */
- mmio_write_32(APCS_QTMR + CNTNSAR, GENMASK_32(7, 0));
-}
-
-/*
- * The APCS register regions always start with a SECURE register that should
- * be cleared to 0 to only allow secure access. Since BL31 handles most of
- * the CPU power management, most of them can be cleared to secure access only.
- */
-#define APCS_GLB_SECURE_STS_NS BIT_32(0)
-#define APCS_GLB_SECURE_PWR_NS BIT_32(1)
-#define APCS_BOOT_START_ADDR_SEC (APCS_CFG + 0x04)
-#define REMAP_EN BIT_32(0)
-#define APCS_AA64NAA32_REG (APCS_CFG + 0x0c)
-
-static void msm8916_configure_cpu_pm(void)
-{
- unsigned int cpu;
-
- /* Disallow non-secure access to boot remapper / TCM registers */
- mmio_write_32(APCS_CFG, 0);
-
- /*
- * Disallow non-secure access to power management registers.
- * However, allow STS and PWR since those also seem to control access
- * to CPU frequency related registers (e.g. APCS_CMD_RCGR). If these
- * bits are not set, CPU frequency control fails in the non-secure world.
- */
- mmio_write_32(APCS_GLB, APCS_GLB_SECURE_STS_NS | APCS_GLB_SECURE_PWR_NS);
-
- /* Disallow non-secure access to L2 SAW2 */
- mmio_write_32(APCS_L2_SAW2, 0);
-
- /* Disallow non-secure access to CPU ACS and SAW2 */
- for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
- mmio_write_32(APCS_ALIAS_ACS(cpu), 0);
- mmio_write_32(APCS_ALIAS_SAW2(cpu), 0);
- }
-
- /* Make sure all further warm boots end up in BL31 and aarch64 state */
- CASSERT((BL31_BASE & 0xffff) == 0, assert_bl31_base_64k_aligned);
- mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL31_BASE | REMAP_EN);
- mmio_write_32(APCS_AA64NAA32_REG, 1);
-}
-
-/*
- * MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU,
- * which allows routing context bank interrupts to one of 3 interrupt numbers
- * ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number
- * by default to avoid special setup on the non-secure side.
- */
-#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038)
-#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c)
-#define SMMU_CFG_CLK_ENA BIT_32(12)
-#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000)
-#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff)
-
-static void msm8916_configure_smmu(void)
-{
- /* Enable SMMU configuration clock to enable register access */
- mmio_setbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
- while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF)
- ;
-
- /* Route all context bank interrupts to non-secure interrupt */
- mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL);
-
- /* Disable configuration clock again */
- mmio_clrbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
-}
-
void bl31_platform_setup(void)
{
INFO("BL31: Platform setup start\n");
- generic_delay_timer_init();
- msm8916_configure_timer();
- msm8916_gicv2_init();
- msm8916_configure_cpu_pm();
- msm8916_configure_smmu();
+ msm8916_platform_setup();
+ msm8916_configure();
INFO("BL31: Platform setup done\n");
}
diff --git a/plat/qti/msm8916/msm8916_config.c b/plat/qti/msm8916/msm8916_config.c
new file mode 100644
index 0000000..350ed5c
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_config.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <lib/mmio.h>
+
+#include "msm8916_config.h"
+#include "msm8916_gicv2.h"
+#include <msm8916_mmap.h>
+#include <platform_def.h>
+
+static void msm8916_configure_timer(void)
+{
+ /* Set timer frequency */
+ mmio_write_32(APCS_QTMR + CNTCTLBASE_CNTFRQ, PLAT_SYSCNT_FREQ);
+
+ /* Make all timer frames available to non-secure world */
+ mmio_write_32(APCS_QTMR + CNTNSAR, GENMASK_32(7, 0));
+}
+
+/*
+ * The APCS register regions always start with a SECURE register that should
+ * be cleared to 0 to only allow secure access. Since BL31 handles most of
+ * the CPU power management, most of them can be cleared to secure access only.
+ */
+#define APCS_GLB_SECURE_STS_NS BIT_32(0)
+#define APCS_GLB_SECURE_PWR_NS BIT_32(1)
+#define APCS_BOOT_START_ADDR_SEC (APCS_CFG + 0x04)
+#define REMAP_EN BIT_32(0)
+#define APCS_AA64NAA32_REG (APCS_CFG + 0x0c)
+
+static void msm8916_configure_cpu_pm(void)
+{
+ unsigned int cpu;
+
+ /* Disallow non-secure access to boot remapper / TCM registers */
+ mmio_write_32(APCS_CFG, 0);
+
+ /*
+ * Disallow non-secure access to power management registers.
+ * However, allow STS and PWR since those also seem to control access
+ * to CPU frequency related registers (e.g. APCS_CMD_RCGR). If these
+ * bits are not set, CPU frequency control fails in the non-secure world.
+ */
+ mmio_write_32(APCS_GLB, APCS_GLB_SECURE_STS_NS | APCS_GLB_SECURE_PWR_NS);
+
+ /* Disallow non-secure access to L2 SAW2 */
+ mmio_write_32(APCS_L2_SAW2, 0);
+
+ /* Disallow non-secure access to CPU ACS and SAW2 */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ mmio_write_32(APCS_ALIAS_ACS(cpu), 0);
+ mmio_write_32(APCS_ALIAS_SAW2(cpu), 0);
+ }
+
+#ifdef __aarch64__
+ /* Make sure all further warm boots end up in BL31 and aarch64 state */
+ CASSERT((BL31_BASE & 0xffff) == 0, assert_bl31_base_64k_aligned);
+ mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL31_BASE | REMAP_EN);
+ mmio_write_32(APCS_AA64NAA32_REG, 1);
+#else
+ /* Make sure all further warm boots end up in BL32 */
+ CASSERT((BL32_BASE & 0xffff) == 0, assert_bl32_base_64k_aligned);
+ mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL32_BASE | REMAP_EN);
+#endif
+}
+
+/*
+ * MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU,
+ * which allows routing context bank interrupts to one of 3 interrupt numbers
+ * ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number
+ * by default to avoid special setup on the non-secure side.
+ */
+#define CLK_OFF BIT_32(31)
+#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038)
+#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c)
+#define SMMU_CFG_CLK_ENA BIT_32(12)
+#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000)
+#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff)
+
+static void msm8916_configure_smmu(void)
+{
+ /* Enable SMMU configuration clock to enable register access */
+ mmio_setbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
+ while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF)
+ ;
+
+ /* Route all context bank interrupts to non-secure interrupt */
+ mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL);
+
+ /* Disable configuration clock again */
+ mmio_clrbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
+}
+
+void msm8916_configure(void)
+{
+ msm8916_gicv2_configure();
+ msm8916_configure_timer();
+ msm8916_configure_cpu_pm();
+ msm8916_configure_smmu();
+}
diff --git a/plat/qti/msm8916/msm8916_config.h b/plat/qti/msm8916/msm8916_config.h
new file mode 100644
index 0000000..992625b
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_config.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MSM8916_CONFIG_H
+#define MSM8916_CONFIG_H
+
+void msm8916_configure(void);
+
+#endif /* MSM8916_CONFIG_H */
diff --git a/plat/qti/msm8916/msm8916_gicv2.c b/plat/qti/msm8916/msm8916_gicv2.c
index 25a6628..82cecf2 100644
--- a/plat/qti/msm8916/msm8916_gicv2.c
+++ b/plat/qti/msm8916/msm8916_gicv2.c
@@ -10,6 +10,7 @@
#include "msm8916_gicv2.h"
#include <msm8916_mmap.h>
+#include <platform_def.h>
#define IRQ_SEC_SGI_0 8
#define IRQ_SEC_SGI_1 9
@@ -20,8 +21,6 @@
#define IRQ_SEC_SGI_6 14
#define IRQ_SEC_SGI_7 15
-#define IRQ_SEC_PHY_TIMER (16 + 2) /* PPI #2 */
-
static const interrupt_prop_t msm8916_interrupt_props[] = {
INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
@@ -53,6 +52,10 @@
void msm8916_gicv2_init(void)
{
gicv2_driver_init(&msm8916_gic_data);
+}
+
+void msm8916_gicv2_configure(void)
+{
gicv2_distif_init();
gicv2_pcpu_distif_init();
gicv2_cpuif_enable();
diff --git a/plat/qti/msm8916/msm8916_gicv2.h b/plat/qti/msm8916/msm8916_gicv2.h
index 99db0d3..919e294 100644
--- a/plat/qti/msm8916/msm8916_gicv2.h
+++ b/plat/qti/msm8916/msm8916_gicv2.h
@@ -8,5 +8,6 @@
#define MSM8916_GICV2_H
void msm8916_gicv2_init(void);
+void msm8916_gicv2_configure(void);
#endif /* MSM8916_GICV2_H */
diff --git a/plat/qti/msm8916/msm8916_setup.c b/plat/qti/msm8916/msm8916_setup.c
new file mode 100644
index 0000000..26039a9
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_setup.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.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 "msm8916_gicv2.h"
+#include <msm8916_mmap.h>
+#include "msm8916_setup.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 console_t console;
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return PLAT_SYSCNT_FREQ;
+}
+
+#define GPIO_CFG_FUNC(n) ((n) << 2)
+#define GPIO_CFG_DRV_STRENGTH_MA(ma) (((ma) / 2 - 1) << 6)
+
+#define CLK_ENABLE BIT_32(0)
+#define CLK_OFF BIT_32(31)
+#define GCC_BLSP1_AHB_CBCR (GCC_BASE + 0x01008)
+#define GCC_BLSP1_UART_APPS_CBCR(n) (GCC_BASE + \
+ (((n) == 2) ? (0x0302c) : (0x0203c + (((n) - 1) * 0x1000))))
+#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x45004)
+#define BLSP1_AHB_CLK_ENA BIT_32(10)
+
+struct uartdm_gpios {
+ unsigned int tx, rx, func;
+};
+
+static const struct uartdm_gpios uartdm_gpio_map[] = {
+ {0, 1, 0x2}, {4, 5, 0x2},
+};
+
+/*
+ * 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_uart(void)
+{
+ const struct uartdm_gpios *gpios = &uartdm_gpio_map[QTI_UART_NUM - 1];
+
+ CASSERT(QTI_UART_NUM > 0 && QTI_UART_NUM <= ARRAY_SIZE(uartdm_gpio_map),
+ assert_qti_blsp_uart_valid);
+
+ /* Route GPIOs to BLSP UART */
+ mmio_write_32(TLMM_GPIO_CFG(gpios->tx), GPIO_CFG_FUNC(gpios->func) |
+ GPIO_CFG_DRV_STRENGTH_MA(8));
+ mmio_write_32(TLMM_GPIO_CFG(gpios->rx), GPIO_CFG_FUNC(gpios->func) |
+ GPIO_CFG_DRV_STRENGTH_MA(8));
+
+ /* 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 UART clock */
+ mmio_setbits_32(GCC_BLSP1_UART_APPS_CBCR(QTI_UART_NUM), CLK_ENABLE);
+ while (mmio_read_32(GCC_BLSP1_UART_APPS_CBCR(QTI_UART_NUM)) & CLK_OFF)
+ ;
+}
+
+void msm8916_early_platform_setup(void)
+{
+ /* Initialize the debug console as early as possible */
+ msm8916_enable_blsp_uart();
+ console_uartdm_register(&console, BLSP_UART_BASE);
+
+ if (QTI_RUNTIME_UART) {
+ /* Mark UART as runtime usable */
+ console_set_scope(&console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+ }
+}
+
+void msm8916_plat_arch_setup(uintptr_t base, size_t size)
+{
+ mmap_add_region(base, base, size, 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();
+}
+
+void msm8916_platform_setup(void)
+{
+ generic_delay_timer_init();
+ msm8916_gicv2_init();
+}
diff --git a/plat/qti/msm8916/msm8916_setup.h b/plat/qti/msm8916/msm8916_setup.h
new file mode 100644
index 0000000..d2de943
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_setup.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MSM8916_SETUP_H
+#define MSM8916_SETUP_H
+
+void msm8916_early_platform_setup(void);
+void msm8916_plat_arch_setup(uintptr_t base, size_t size);
+void msm8916_platform_setup(void);
+
+#endif /* MSM8916_SETUP_H */
diff --git a/plat/qti/msm8916/platform.mk b/plat/qti/msm8916/platform.mk
index 107296b..7e698fb 100644
--- a/plat/qti/msm8916/platform.mk
+++ b/plat/qti/msm8916/platform.mk
@@ -7,35 +7,37 @@
include drivers/arm/gic/v2/gicv2.mk
include lib/xlat_tables_v2/xlat_tables.mk
-PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS}
+PLAT_BL_COMMON_SOURCES := ${GICV2_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ plat/common/plat_gicv2.c \
+ plat/qti/msm8916/msm8916_gicv2.c \
+ plat/qti/msm8916/msm8916_setup.c \
+ plat/qti/msm8916/${ARCH}/msm8916_helpers.S \
+ plat/qti/msm8916/${ARCH}/uartdm_console.S
-PLAT_INCLUDES := -Iinclude/plat/arm/common/${ARCH} \
- -Iplat/qti/msm8916/include
+MSM8916_PM_SOURCES := lib/cpus/${ARCH}/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/qti/msm8916/msm8916_config.c \
+ plat/qti/msm8916/msm8916_cpu_boot.c \
+ plat/qti/msm8916/msm8916_pm.c \
+ plat/qti/msm8916/msm8916_topology.c
-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_cpu_boot.c \
- plat/qti/msm8916/msm8916_gicv2.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
+BL31_SOURCES += ${MSM8916_PM_SOURCES} \
+ plat/qti/msm8916/msm8916_bl31_setup.c
+
+PLAT_INCLUDES := -Iplat/qti/msm8916/include
+
+ifeq (${ARCH},aarch64)
+# arm_macros.S exists only on aarch64 currently
+PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH}
+endif
# 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
@@ -61,5 +63,27 @@
ERRATA_A53_855873 := 0 # Workaround works only for >= r0p3
ERRATA_A53_1530924 := 1
+# Build config flags
+# ------------------
+BL31_BASE ?= 0x86500000
+PRELOADED_BL33_BASE ?= 0x8f600000
+
+ifeq (${ARCH},aarch64)
+BL32_BASE ?= BL31_LIMIT
$(eval $(call add_define,BL31_BASE))
+else
+# There is no BL31 on aarch32, so reuse its location for BL32
+BL32_BASE ?= $(BL31_BASE)
+endif
$(eval $(call add_define,BL32_BASE))
+
+# UART number to use for TF-A output during early boot
+QTI_UART_NUM ?= 2
+$(eval $(call assert_numeric,QTI_UART_NUM))
+$(eval $(call add_define,QTI_UART_NUM))
+
+# Set to 1 on the command line to keep using UART after early boot.
+# Requires reserving the UART and related clocks inside the normal world.
+QTI_RUNTIME_UART ?= 0
+$(eval $(call assert_boolean,QTI_RUNTIME_UART))
+$(eval $(call add_define,QTI_RUNTIME_UART))
diff --git a/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c b/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c
new file mode 100644
index 0000000..78ab0c7
--- /dev/null
+++ b/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/debug.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <platform_sp_min.h>
+
+#include "../msm8916_config.h"
+#include "../msm8916_setup.h"
+
+static struct {
+ entry_point_info_t bl33;
+} image_ep_info = {
+ /* 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_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS),
+};
+
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ msm8916_early_platform_setup();
+}
+
+void sp_min_plat_arch_setup(void)
+{
+ msm8916_plat_arch_setup(BL32_BASE, BL32_END - BL32_BASE);
+ enable_mmu_svc_mon(0);
+}
+
+void sp_min_platform_setup(void)
+{
+ INFO("SP_MIN: Platform setup start\n");
+ msm8916_platform_setup();
+ msm8916_configure();
+ INFO("SP_MIN: Platform setup done\n");
+}
+
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+ return &image_ep_info.bl33;
+}
diff --git a/plat/qti/msm8916/sp_min/sp_min-msm8916.mk b/plat/qti/msm8916/sp_min/sp_min-msm8916.mk
new file mode 100644
index 0000000..be07f94
--- /dev/null
+++ b/plat/qti/msm8916/sp_min/sp_min-msm8916.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_SOURCES += ${MSM8916_PM_SOURCES} \
+ plat/common/${ARCH}/platform_mp_stack.S \
+ plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c
+
+override RESET_TO_SP_MIN := 1
diff --git a/plat/qti/msm8916/tsp/msm8916_tsp_setup.c b/plat/qti/msm8916/tsp/msm8916_tsp_setup.c
new file mode 100644
index 0000000..218af57
--- /dev/null
+++ b/plat/qti/msm8916/tsp/msm8916_tsp_setup.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <platform_tsp.h>
+
+#include "../msm8916_setup.h"
+#include <platform_def.h>
+
+void tsp_early_platform_setup(void)
+{
+ msm8916_early_platform_setup();
+}
+
+void tsp_plat_arch_setup(void)
+{
+ msm8916_plat_arch_setup(BL32_BASE, BL32_END - BL32_BASE);
+ enable_mmu_el1(0);
+}
+
+void tsp_platform_setup(void)
+{
+ INFO("TSP: Platform setup start\n");
+ msm8916_platform_setup();
+ INFO("TSP: Platform setup done\n");
+
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
diff --git a/plat/qti/msm8916/tsp/tsp-msm8916.mk b/plat/qti/msm8916/tsp/tsp-msm8916.mk
new file mode 100644
index 0000000..0d50058
--- /dev/null
+++ b/plat/qti/msm8916/tsp/tsp-msm8916.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2023, Stephan Gerhold <stephan@gerhold.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_SOURCES += plat/common/${ARCH}/platform_mp_stack.S \
+ plat/qti/msm8916/tsp/msm8916_tsp_setup.c