blob: 143972d26813061863dca1be47cc4c6fc849dc50 [file] [log] [blame]
Soby Mathew0d268dc2016-07-11 14:13:56 +01001/*
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +00002 * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
Soby Mathew0d268dc2016-07-11 14:13:56 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soby Mathew0d268dc2016-07-11 14:13:56 +01005 */
6
7#include <arch.h>
8#include <asm_macros.S>
9#include <platform_def.h>
10#include "../drivers/pwrc/fvp_pwrc.h"
11#include "../fvp_def.h"
12
Yatharth Kocharf528faf2016-06-28 16:58:26 +010013 .globl plat_secondary_cold_boot_setup
Soby Mathew0d268dc2016-07-11 14:13:56 +010014 .globl plat_get_my_entrypoint
15 .globl plat_is_my_cpu_primary
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +000016 .globl plat_arm_calc_core_pos
Soby Mathew0d268dc2016-07-11 14:13:56 +010017
Yatharth Kocharf528faf2016-06-28 16:58:26 +010018 /* --------------------------------------------------------------------
19 * void plat_secondary_cold_boot_setup (void);
20 *
21 * For AArch32, cold-booting secondary CPUs is not yet
22 * implemented and they panic.
23 * --------------------------------------------------------------------
24 */
25func plat_secondary_cold_boot_setup
26cb_panic:
27 b cb_panic
28endfunc plat_secondary_cold_boot_setup
29
Soby Mathew0d268dc2016-07-11 14:13:56 +010030 /* ---------------------------------------------------------------------
31 * unsigned long plat_get_my_entrypoint (void);
32 *
33 * Main job of this routine is to distinguish between a cold and warm
34 * boot. On FVP, this information can be queried from the power
35 * controller. The Power Control SYS Status Register (PSYSR) indicates
36 * the wake-up reason for the CPU.
37 *
38 * For a cold boot, return 0.
39 * For a warm boot, read the mailbox and return the address it contains.
40 *
41 * TODO: PSYSR is a common register and should be
42 * accessed using locks. Since it is not possible
43 * to use locks immediately after a cold reset
44 * we are relying on the fact that after a cold
45 * reset all cpus will read the same WK field
46 * ---------------------------------------------------------------------
47 */
48func plat_get_my_entrypoint
49 /* ---------------------------------------------------------------------
50 * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
51 * WakeRequest signal" then it is a warm boot.
52 * ---------------------------------------------------------------------
53 */
54 ldcopr r2, MPIDR
55 ldr r1, =PWRC_BASE
56 str r2, [r1, #PSYSR_OFF]
57 ldr r2, [r1, #PSYSR_OFF]
58 ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
59 cmp r2, #WKUP_PPONR
60 beq warm_reset
61 cmp r2, #WKUP_GICREQ
62 beq warm_reset
63
64 /* Cold reset */
65 mov r0, #0
66 bx lr
67
68warm_reset:
69 /* ---------------------------------------------------------------------
70 * A mailbox is maintained in the trusted SRAM. It is flushed out of the
71 * caches after every update using normal memory so it is safe to read
72 * it here with SO attributes.
73 * ---------------------------------------------------------------------
74 */
75 ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE
76 ldr r0, [r0]
77 cmp r0, #0
78 beq _panic
79 bx lr
80
81 /* ---------------------------------------------------------------------
82 * The power controller indicates this is a warm reset but the mailbox
83 * is empty. This should never happen!
84 * ---------------------------------------------------------------------
85 */
86_panic:
87 b _panic
88endfunc plat_get_my_entrypoint
89
90 /* -----------------------------------------------------
91 * unsigned int plat_is_my_cpu_primary (void);
92 *
93 * Find out whether the current cpu is the primary
94 * cpu.
95 * -----------------------------------------------------
96 */
97func plat_is_my_cpu_primary
98 ldcopr r0, MPIDR
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +000099 ldr r1, =MPIDR_AFFINITY_MASK
Soby Mathew0d268dc2016-07-11 14:13:56 +0100100 and r0, r1
101 cmp r0, #FVP_PRIMARY_CPU
102 moveq r0, #1
103 movne r0, #0
104 bx lr
105endfunc plat_is_my_cpu_primary
Jeenu Viswambharan528d21b2016-11-15 13:53:57 +0000106
107 /* -----------------------------------------------------
108 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
109 *
110 * Function to calculate the core position on FVP.
111 *
112 * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER) +
113 * (CPUId * FVP_MAX_PE_PER_CPU) +
114 * ThreadId
115 * -----------------------------------------------------
116 */
117func plat_arm_calc_core_pos
118 mov r3, r0
119
120 /*
121 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
122 * look as if in a multi-threaded implementation
123 */
124 tst r0, #MPIDR_MT_MASK
125 lsleq r3, r0, #MPIDR_AFFINITY_BITS
126
127 /* Extract individual affinity fields from MPIDR */
128 mov r2, #FVP_MAX_PE_PER_CPU
129 ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
130 ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
131 mla r0, r1, r2, r0
132
133 mov r1, #FVP_MAX_CPUS_PER_CLUSTER
134 ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
135 mla r0, r1, r2, r0
136
137 bx lr
138endfunc plat_arm_calc_core_pos