1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <drivers/arm/fvp/fvp_pwrc.h>
#include <drivers/arm/gicv2.h>
#include <drivers/arm/gicv3.h>
#include <platform_def.h>
.globl plat_secondary_cold_boot_setup
.globl plat_get_my_entrypoint
.globl plat_is_my_cpu_primary
/* -----------------------------------------------------
* 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.
* TODO: Should we read the PSYS register to make sure
* that the request has gone through.
* -----------------------------------------------------
*/
func plat_secondary_cold_boot_setup
/* ---------------------------------------------
* Power down this cpu.
* TODO: Do we need to worry about powering the
* cluster down as well here? That will need
* locks which we won't have unless an elf-
* loader zeroes out the zi section.
* ---------------------------------------------
*/
mrs x0, mpidr_el1
mov_imm x1, PWRC_BASE
str w0, [x1, #PPOFFR_OFF]
/* ---------------------------------------------
* There is no sane reason to come out of this
* wfi so panic if we do. This cpu will be pow-
* ered on and reset by the cpu_on pm api
* ---------------------------------------------
*/
dsb sy
wfi
no_ret plat_panic_handler
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 warm
* boot. On FVP_R, this information can be queried from the power
* controller. The Power Control SYS Status Register (PSYSR) indicates
* the wake-up reason for the CPU.
*
* For a cold boot, return 0.
* For a warm boot, read the mailbox and return the address it contains.
*
* TODO: PSYSR is a common register and should be
* accessed using locks. Since it is not possible
* to use locks immediately after a cold reset
* we are relying on the fact that after a cold
* reset all cpus will read the same WK field
* ---------------------------------------------------------------------
*/
func plat_get_my_entrypoint
/* ---------------------------------------------------------------------
* When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
* WakeRequest signal" then it is a warm boot.
* ---------------------------------------------------------------------
*/
mrs x2, mpidr_el1
mov_imm x1, PWRC_BASE
str w2, [x1, #PSYSR_OFF]
ldr w2, [x1, #PSYSR_OFF]
ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
cmp w2, #WKUP_PPONR
beq warm_reset
cmp w2, #WKUP_GICREQ
beq warm_reset
/* Cold reset */
mov x0, #0
ret
warm_reset:
/* ---------------------------------------------------------------------
* A mailbox is maintained in the trusted SRAM. It is flushed out of the
* caches after every update using normal memory so it is safe to read
* it here with SO attributes.
* ---------------------------------------------------------------------
*/
mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
ldr x0, [x0]
cbz x0, _panic_handler
ret
/* ---------------------------------------------------------------------
* The power controller indicates this is a warm reset but the mailbox
* is empty. This should never happen!
* ---------------------------------------------------------------------
*/
_panic_handler:
no_ret plat_panic_handler
endfunc plat_get_my_entrypoint
/* -----------------------------------------------------
* 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
mov_imm x1, MPIDR_AFFINITY_MASK
and x0, x0, x1
cmp x0, #FVP_R_PRIMARY_CPU
cset w0, eq
ret
endfunc plat_is_my_cpu_primary
|