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
This commit is contained in:
Manish V Badarkhe 2023-06-22 17:00:52 +02:00 committed by TrustedFirmware Code Review
commit c4c7efe79e
18 changed files with 868 additions and 245 deletions

View file

@ -7,7 +7,7 @@ APQ8016(E), ...) that are all very similar. A popular device based on APQ8016E
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 @@ trial and error to actually make it work.
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 @@ will be added later once ready.
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 @@ use e.g. `qtestsign`_::
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 @@ to the ``tz`` partition on the device. BL31 should be running after a reboot.
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 @@ this (with ``DEBUG=1``, otherwise only the ``NOTICE`` lines are shown)::
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

View file

@ -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

View file

@ -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

View file

@ -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 @@ endfunc plat_crash_console_init
* -------------------------------------------------
*/
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 @@ endfunc plat_crash_console_putc
* -------------------------------------------------
*/
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,44 +93,43 @@ endfunc plat_my_core_pos
*/
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

View file

@ -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)

View file

@ -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 */

View file

@ -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 @@ static struct {
.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");
}

View file

@ -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();
}

View file

@ -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 */

View file

@ -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 @@ static const gicv2_driver_data_t msm8916_gic_data = {
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();

View file

@ -8,5 +8,6 @@
#define MSM8916_GICV2_H
void msm8916_gicv2_init(void);
void msm8916_gicv2_configure(void);
#endif /* MSM8916_GICV2_H */

View file

@ -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();
}

View file

@ -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 */

View file

@ -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_843419 := 1
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))

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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