123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <arch.h>
- #include <asm_macros.S>
- #include <assert_macros.S>
- #include <platform_def.h>
- #include <cortex_a72.h>
- .globl plat_crash_console_flush
- .globl plat_crash_console_init
- .globl plat_crash_console_putc
- .globl platform_mem_init
- .globl plat_get_my_entrypoint
- .globl plat_is_my_cpu_primary
- .globl plat_my_core_pos
- .globl plat_reset_handler
- .globl plat_rpi3_calc_core_pos
- .globl plat_secondary_cold_boot_setup
- .globl plat_rpi_get_model
- /* -----------------------------------------------------
- * unsigned int plat_my_core_pos(void)
- *
- * This function uses the plat_rpi3_calc_core_pos()
- * definition to get the index of the calling CPU.
- *
- * When MT is set, lowest affinity represents the thread ID.
- * Since we only support one thread per core, discard this field
- * so cluster and core IDs go back into Aff1 and Aff0 respectively.
- * The upper bits are also affected, but plat_rpi3_calc_core_pos()
- * does not use them.
- * -----------------------------------------------------
- */
- func plat_my_core_pos
- mrs x0, mpidr_el1
- tst x0, #MPIDR_MT_MASK
- lsr x1, x0, #MPIDR_AFFINITY_BITS
- csel x0, x1, x0, ne
- b plat_rpi3_calc_core_pos
- endfunc plat_my_core_pos
- /* -----------------------------------------------------
- * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
- *
- * CorePos = (ClusterId * 4) + CoreId
- * -----------------------------------------------------
- */
- func plat_rpi3_calc_core_pos
- and x1, x0, #MPIDR_CPU_MASK
- and x0, x0, #MPIDR_CLUSTER_MASK
- add x0, x1, x0, LSR #6
- ret
- endfunc plat_rpi3_calc_core_pos
- /* -----------------------------------------------------
- * unsigned int plat_is_my_cpu_primary (void);
- *
- * Find out whether the current cpu is the primary
- * cpu.
- * -----------------------------------------------------
- */
- func plat_is_my_cpu_primary
- mrs x0, mpidr_el1
- and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
- cmp x0, #RPI_PRIMARY_CPU
- cset w0, eq
- ret
- endfunc plat_is_my_cpu_primary
- /* -----------------------------------------------------
- * void plat_wait_for_warm_boot (void);
- *
- * This function performs any platform specific actions
- * needed for a CPU to be put into holding pen to wait
- * for a warm boot request.
- * The function will never return.
- * -----------------------------------------------------
- */
- func plat_wait_for_warm_boot
- /*
- * Calculate address of our hold entry.
- * As the function will never return, there is no need to save LR.
- */
- bl plat_my_core_pos
- lsl x0, x0, #3
- mov_imm x2, PLAT_RPI3_TM_HOLD_BASE
- add x0, x0, x2
- /*
- * This code runs way before requesting the warmboot of this core,
- * so it is possible to clear the mailbox before getting a request
- * to boot.
- */
- mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
- str x1,[x0]
- /* Wait until we have a go */
- poll_mailbox:
- wfe
- ldr x1, [x0]
- cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO
- bne poll_mailbox
- /* Jump to the provided entrypoint */
- mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT
- ldr x1, [x0]
- br x1
- endfunc plat_wait_for_warm_boot
- /* -----------------------------------------------------
- * void plat_secondary_cold_boot_setup (void);
- *
- * This function performs any platform specific actions
- * needed for a secondary cpu after a cold reset e.g
- * mark the cpu's presence, mechanism to place it in a
- * holding pen etc.
- * -----------------------------------------------------
- */
- func plat_secondary_cold_boot_setup
- b plat_wait_for_warm_boot
- endfunc plat_secondary_cold_boot_setup
- /* ---------------------------------------------------------------------
- * uintptr_t plat_get_my_entrypoint (void);
- *
- * Main job of this routine is to distinguish between a cold and a warm
- * boot.
- *
- * This functions returns:
- * - 0 for a cold boot.
- * - Any other value for a warm boot.
- * ---------------------------------------------------------------------
- */
- func plat_get_my_entrypoint
- mov x1, x30
- bl plat_is_my_cpu_primary
- /*
- * Secondaries always cold boot.
- */
- cbz w0, 1f
- /*
- * Primaries warm boot if they are requested
- * to power off.
- */
- mov_imm x0, PLAT_RPI3_TM_HOLD_BASE
- ldr x0, [x0]
- cmp x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF
- adr x0, plat_wait_for_warm_boot
- csel x0, x0, xzr, eq
- ret x1
- 1: mov x0, #0
- ret x1
- endfunc plat_get_my_entrypoint
- /* ---------------------------------------------
- * void platform_mem_init (void);
- *
- * No need to carry out any memory initialization.
- * ---------------------------------------------
- */
- func platform_mem_init
- ret
- endfunc platform_mem_init
- /* ---------------------------------------------
- * int plat_crash_console_init(void)
- * Function to initialize the crash console
- * without a C Runtime to print crash report.
- * Clobber list : x0 - x3
- * ---------------------------------------------
- */
- func plat_crash_console_init
- mov_imm x0, PLAT_RPI_CRASH_UART_BASE
- #if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
- mov_imm x1, RPI4_PL011_UART_CLOCK
- mov_imm x2, PLAT_RPI_UART_BAUDRATE
- b console_pl011_core_init
- #else
- mov x1, xzr
- mov x2, xzr
- b console_16550_core_init
- #endif
- endfunc plat_crash_console_init
- /* ---------------------------------------------
- * int plat_crash_console_putc(int c)
- * Function to print a character on the crash
- * console without a C Runtime.
- * Clobber list : x1, x2
- * ---------------------------------------------
- */
- func plat_crash_console_putc
- mov_imm x1, PLAT_RPI_CRASH_UART_BASE
- #if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
- b console_pl011_core_putc
- #else
- b console_16550_core_putc
- #endif
- endfunc plat_crash_console_putc
- /* ---------------------------------------------
- * void plat_crash_console_flush()
- * Function to force a write of all buffered
- * data that hasn't been output.
- * Out : void.
- * Clobber list : x0, x1
- * ---------------------------------------------
- */
- func plat_crash_console_flush
- mov_imm x0, PLAT_RPI_CRASH_UART_BASE
- #if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
- b console_pl011_core_flush
- #else
- b console_16550_core_flush
- #endif
- endfunc plat_crash_console_flush
- /* ---------------------------------------------
- * int plat_rpi_get_model()
- * Macro to determine whether we are running on
- * a Raspberry Pi 3 or 4. Just checks the MIDR for
- * being either a Cortex-A72 or a Cortex-A53.
- * Out : return 4 if RPi4, 3 otherwise.
- * Clobber list : x0
- * ---------------------------------------------
- */
- .macro _plat_rpi_get_model
- mrs x0, midr_el1
- and x0, x0, #0xf0 /* Isolate low byte of part number */
- cmp w0, #0x80 /* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */
- mov w0, #3
- csinc w0, w0, w0, ne
- .endm
- func plat_rpi_get_model
- _plat_rpi_get_model
- ret
- endfunc plat_rpi_get_model
- /* ---------------------------------------------
- * void plat_reset_handler(void);
- * ---------------------------------------------
- */
- func plat_reset_handler
- /* L2 cache setup only needed on RPi4 */
- _plat_rpi_get_model
- cmp w0, #4
- b.ne 1f
- /* ------------------------------------------------
- * Set L2 read/write cache latency:
- * - L2 Data RAM latency: 3 cycles (0b010)
- * - L2 Data RAM setup: 1 cycle (bit 5)
- * ------------------------------------------------
- */
- mrs x0, CORTEX_A72_L2CTLR_EL1
- mov x1, #0x22
- orr x0, x0, x1
- msr CORTEX_A72_L2CTLR_EL1, x0
- isb
- 1:
- ret
- endfunc plat_reset_handler
|