Page MenuHomePhabricator

Platarmboardfvpaarch64fvp Helperssvsplatarmboardfvp Rfvp R Helperss
Updated 1,222 Days AgoPublic

/*                                                            /*
 * Copyright (c) 2013-2019, ARM Limited and Contributors.  |   * Copyright (c) 2013-2021, ARM Limited and Contributors. 
 *                                                             *
 * SPDX-License-Identifier: BSD-3-Clause                       * SPDX-License-Identifier: BSD-3-Clause
 */                                                            */

#include <arch.h>                                             #include <arch.h>
#include <asm_macros.S>                                       #include <asm_macros.S>
#include <drivers/arm/gicv2.h>                                #include <drivers/arm/gicv2.h>
#include <drivers/arm/gicv3.h>                                #include <drivers/arm/gicv3.h>
#include <drivers/arm/fvp/fvp_pwrc.h>                         #include <drivers/arm/fvp/fvp_pwrc.h>
#include <platform_def.h>                                     #include <platform_def.h>

        .globl  plat_secondary_cold_boot_setup                        .globl  plat_secondary_cold_boot_setup
        .globl  plat_get_my_entrypoint                                .globl  plat_get_my_entrypoint
        .globl  plat_is_my_cpu_primary                                .globl  plat_is_my_cpu_primary
        .globl  plat_arm_calc_core_pos                                .globl  plat_arm_calc_core_pos

        /* -----------------------------------------------            /* -----------------------------------------------
         * void plat_secondary_cold_boot_setup (void);                 * void plat_secondary_cold_boot_setup (void);
         *                                                             *
         * This function performs any platform specific ac             * This function performs any platform specific ac
         * needed for a secondary cpu after a cold reset e             * needed for a secondary cpu after a cold reset e
         * mark the cpu's presence, mechanism to place it              * mark the cpu's presence, mechanism to place it 
         * holding pen etc.                                            * holding pen etc.
         * TODO: Should we read the PSYS register to make              * TODO: Should we read the PSYS register to make 
         * that the request has gone through.                          * that the request has gone through.
         * -----------------------------------------------             * -----------------------------------------------
         */                                                            */
func plat_secondary_cold_boot_setup                           func plat_secondary_cold_boot_setup
#ifndef EL3_PAYLOAD_BASE                                   <
        /* ---------------------------------------------              /* ---------------------------------------------
         * Power down this cpu.                                        * Power down this cpu.
         * TODO: Do we need to worry about powering the                * TODO: Do we need to worry about powering the
         * cluster down as well here. That will need       |           * cluster down as well here? That will need
         * locks which we won't have unless an elf-                    * locks which we won't have unless an elf-
         * loader zeroes out the zi section.                           * loader zeroes out the zi section.
         * ---------------------------------------------               * ---------------------------------------------
         */                                                            */
        mrs     x0, mpidr_el1                                         mrs     x0, mpidr_el1
        mov_imm x1, PWRC_BASE                                         mov_imm x1, PWRC_BASE
        str     w0, [x1, #PPOFFR_OFF]                                 str     w0, [x1, #PPOFFR_OFF]

        /* ---------------------------------------------              /* ---------------------------------------------
         * There is no sane reason to come out of this                 * There is no sane reason to come out of this
         * wfi so panic if we do. This cpu will be pow-                * wfi so panic if we do. This cpu will be pow-
         * ered on and reset by the cpu_on pm api                      * ered on and reset by the cpu_on pm api
         * ---------------------------------------------               * ---------------------------------------------
         */                                                            */
        dsb     sy                                                    dsb     sy
        wfi                                                           wfi
        no_ret  plat_panic_handler                                    no_ret  plat_panic_handler
#else                                                      <
        mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE          <
                                                           <
        /* Wait until the entrypoint gets populated */     <
poll_mailbox:                                              <
        ldr     x1, [x0]                                   <
        cbz     x1, 1f                                     <
        br      x1                                         <
1:                                                         <
        wfe                                                <
        b       poll_mailbox                               <
#endif /* EL3_PAYLOAD_BASE */                              <
endfunc plat_secondary_cold_boot_setup                        endfunc plat_secondary_cold_boot_setup

        /* -----------------------------------------------            /* -----------------------------------------------
         * uintptr_t plat_get_my_entrypoint (void);                    * uintptr_t plat_get_my_entrypoint (void);
         *                                                             *
         * Main job of this routine is to distinguish betw             * Main job of this routine is to distinguish betw
         * boot. On FVP, this information can be queried f |           * boot. On FVP_R, this information can be queried
         * controller. The Power Control SYS Status Regist             * controller. The Power Control SYS Status Regist
         * the wake-up reason for the CPU.                             * the wake-up reason for the CPU.
         *                                                             *
         * For a cold boot, return 0.                                  * For a cold boot, return 0.
         * For a warm boot, read the mailbox and return th             * For a warm boot, read the mailbox and return th
         *                                                             *
         * TODO: PSYSR is a common register and should be              * TODO: PSYSR is a common register and should be
         *      accessed using locks. Since it is not poss             *      accessed using locks. Since it is not poss
         *      to use locks immediately after a cold rese             *      to use locks immediately after a cold rese
         *      we are relying on the fact that after a co             *      we are relying on the fact that after a co
         *      reset all cpus will read the same WK field             *      reset all cpus will read the same WK field
         * -----------------------------------------------             * -----------------------------------------------
         */                                                            */
func plat_get_my_entrypoint                                   func plat_get_my_entrypoint
        /* -----------------------------------------------            /* -----------------------------------------------
         * When bit PSYSR.WK indicates either "Wake by PPO             * When bit PSYSR.WK indicates either "Wake by PPO
         * WakeRequest signal" then it is a warm boot.                 * WakeRequest signal" then it is a warm boot.
         * -----------------------------------------------             * -----------------------------------------------
         */                                                            */
        mrs     x2, mpidr_el1                                         mrs     x2, mpidr_el1
        mov_imm x1, PWRC_BASE                                         mov_imm x1, PWRC_BASE
        str     w2, [x1, #PSYSR_OFF]                                  str     w2, [x1, #PSYSR_OFF]
        ldr     w2, [x1, #PSYSR_OFF]                                  ldr     w2, [x1, #PSYSR_OFF]
        ubfx    w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH              ubfx    w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
        cmp     w2, #WKUP_PPONR                                       cmp     w2, #WKUP_PPONR
        beq     warm_reset                                            beq     warm_reset
        cmp     w2, #WKUP_GICREQ                                      cmp     w2, #WKUP_GICREQ
        beq     warm_reset                                            beq     warm_reset

        /* Cold reset */                                              /* Cold reset */
        mov     x0, #0                                                mov     x0, #0
        ret                                                           ret

warm_reset:                                                   warm_reset:
        /* -----------------------------------------------            /* -----------------------------------------------
         * A mailbox is maintained in the trusted SRAM. It             * A mailbox is maintained in the trusted SRAM. It
         * caches after every update using normal memory s             * caches after every update using normal memory s
         * it here with SO attributes.                                 * it here with SO attributes.
         * -----------------------------------------------             * -----------------------------------------------
         */                                                            */
        mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE                     mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
        ldr     x0, [x0]                                              ldr     x0, [x0]
        cbz     x0, _panic_handler                                    cbz     x0, _panic_handler
        ret                                                           ret

        /* -----------------------------------------------            /* -----------------------------------------------
         * The power controller indicates this is a warm r             * The power controller indicates this is a warm r
         * is empty. This should never happen!                         * is empty. This should never happen!
         * -----------------------------------------------             * -----------------------------------------------
         */                                                            */
_panic_handler:                                               _panic_handler:
        no_ret  plat_panic_handler                                    no_ret  plat_panic_handler
endfunc plat_get_my_entrypoint                                endfunc plat_get_my_entrypoint

        /* -----------------------------------------------            /* -----------------------------------------------
         * unsigned int plat_is_my_cpu_primary (void);                 * unsigned int plat_is_my_cpu_primary (void);
         *                                                             *
         * Find out whether the current cpu is the primary             * Find out whether the current cpu is the primary
         * cpu.                                                        * cpu.
         * -----------------------------------------------             * -----------------------------------------------
         */                                                            */
func plat_is_my_cpu_primary                                   func plat_is_my_cpu_primary
        mrs     x0, mpidr_el1                                         mrs     x0, mpidr_el1
        mov_imm x1, MPIDR_AFFINITY_MASK                               mov_imm x1, MPIDR_AFFINITY_MASK
        and     x0, x0, x1                                            and     x0, x0, x1
        cmp     x0, #FVP_PRIMARY_CPU                       |          cmp     x0, #FVP_R_PRIMARY_CPU
        cset    w0, eq                                                cset    w0, eq
        ret                                                           ret
endfunc plat_is_my_cpu_primary                                endfunc plat_is_my_cpu_primary

        /* -----------------------------------------------            /* -----------------------------------------------
         * unsigned int plat_arm_calc_core_pos(u_register_             * unsigned int plat_arm_calc_core_pos(u_register_
         *                                                             *
         * Function to calculate the core position on FVP. |           * Function to calculate the core position on FVP_
         *                                                             *
         * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX |           * (ClusterId * FVP_R_MAX_CPUS_PER_CLUSTER * FVP_R
         * (CPUId * FVP_MAX_PE_PER_CPU) +                  |           * (CPUId * FVP_R_MAX_PE_PER_CPU) +
         * ThreadId                                                    * ThreadId
         *                                                             *
         * which can be simplified as:                                 * which can be simplified as:
         *                                                             *
         * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) |           * ((ClusterId * FVP_R_MAX_CPUS_PER_CLUSTER + CPUI
         * + ThreadId                                                  * + ThreadId
         * -----------------------------------------------             * -----------------------------------------------
         */                                                            */
func plat_arm_calc_core_pos                                   func plat_arm_calc_core_pos
        /*                                                            /*
         * Check for MT bit in MPIDR. If not set, shift MP             * Check for MT bit in MPIDR. If not set, shift MP
         * look as if in a multi-threaded implementation.              * look as if in a multi-threaded implementation.
         */                                                            */
        tst     x0, #MPIDR_MT_MASK                                    tst     x0, #MPIDR_MT_MASK
        lsl     x3, x0, #MPIDR_AFFINITY_BITS                          lsl     x3, x0, #MPIDR_AFFINITY_BITS
        csel    x3, x3, x0, eq                                        csel    x3, x3, x0, eq

        /* Extract individual affinity fields from MPIDR *            /* Extract individual affinity fields from MPIDR *
        ubfx    x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY            ubfx    x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY
        ubfx    x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY            ubfx    x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY
        ubfx    x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY            ubfx    x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY

        /* Compute linear position */                                 /* Compute linear position */
        mov     x4, #FVP_MAX_CPUS_PER_CLUSTER              |          mov     x4, #FVP_R_MAX_CPUS_PER_CLUSTER
        madd    x1, x2, x4, x1                                        madd    x1, x2, x4, x1
        mov     x5, #FVP_MAX_PE_PER_CPU                    |          mov     x5, #FVP_R_MAX_PE_PER_CPU
        madd    x0, x1, x5, x0                                        madd    x0, x1, x5, x0
        ret                                                           ret
endfunc plat_arm_calc_core_pos                                endfunc plat_arm_calc_core_pos
Last Author
garymorrison-arm
Last Edited
Jul 2 2021, 10:47 PM