blob: 09035a19bef893d3caad1f6b7650f9b35d0a62d4 [file] [log] [blame]
rutigl@gmail.comdefbeed2023-03-19 09:19:05 +02001/*
2 * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved.
3 *
4 * Copyright (C) 2022-2023 Nuvoton Ltd.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#ifndef NUVOTON_HELPERS_S
10#define NUVOTON_HELPERS_S
11
12#include <asm_macros.S>
13#include <cortex_a35.h>
14#include <platform_def.h>
15
16 .globl plat_is_my_cpu_primary
17 .globl plat_my_core_pos
18 .globl plat_calc_core_pos
19 .globl plat_reset_handler
20 .globl plat_get_my_entrypoint
21 .globl plat_secondary_cold_boot_setup
22 .globl plat_crash_console_init
23 .globl plat_crash_console_putc
24 .globl plat_crash_console_flush
25 .globl platform_mem_init
26 .globl npcm845x_mailbox_init
27
28 /* --------------------------------------------------------------------
29 * Helper macro that reads the part number of the current CPU and jumps
30 * to the given label if it matches the CPU MIDR provided.
31 *
32 * Clobbers x0.
33 * --------------------------------------------------------------------
34 */
35 .macro jump_if_cpu_midr _cpu_midr, _label
36
37 mrs x0, midr_el1
38 ubfx x0, x0, MIDR_PN_SHIFT, #12
39 cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
40 b.eq \_label
41
42 .endm
43
44 /* ----------------------------------------------
45 * The mailbox_base is used to distinguish warm/cold
46 * reset. The mailbox_base is in the data section, not
47 * in .bss, this allows function to start using this
48 * variable before the runtime memory is initialized.
49 * ----------------------------------------------
50 */
51 .section .data.mailbox_base
52 .align 3
53 mailbox_base: .quad 0x0
54
55 /* ---------------------------------------------
56 * void plat_reset_handler(void);
57 *
58 * To add: Determine the SoC type and call the appropriate
59 * reset handler.
60 *----------------------------------------------- */
61
62func plat_reset_handler
63 ret
64endfunc plat_reset_handler
65
66 /* ----------------------------------------------
67 * unsigned int plat_is_my_cpu_primary(void);
68 * This function checks if this is the primary CPU
69 * ----------------------------------------------
70 */
71func plat_is_my_cpu_primary
72 mrs x0, mpidr_el1
73 and x0, x0, #(MPIDR_CPU_MASK)
74 cmp x0, #PLAT_PRIMARY_CPU
75 cset x0, eq
76 ret
77endfunc plat_is_my_cpu_primary
78
79 /* ----------------------------------------------
80 * unsigned int plat_my_core_pos(void)
81 * This Function uses the plat_calc_core_pos()
82 * to get the index of the calling CPU.
83 * ----------------------------------------------
84 */
85func plat_my_core_pos
86 mrs x0, mpidr_el1
87 and x1, x0, #MPIDR_CPU_MASK
88 and x0, x0, #MPIDR_CLUSTER_MASK
89 add x0, x1, x0, LSR #6
90 ret
91endfunc plat_my_core_pos
92
93 /*
94 * unsigned int plat_calc_core_pos(uint64_t mpidr)
95 * helper function to calculate the core position.
96 * With this function.
97 */
98func plat_calc_core_pos
99 and x1, x0, #MPIDR_CPU_MASK
100 and x0, x0, #MPIDR_CLUSTER_MASK
101 add x0, x1, x0, LSR #6
102 ret
103endfunc plat_calc_core_pos
104
105 /* ---------------------------------------------
106 * function to get the entrypoint.
107 * ---------------------------------------------
108 */
109 /* ---------------------------------------------------------------------
110 * uintptr_t plat_get_my_entrypoint (void);
111 *
112 * Main job of this routine is to distinguish between a cold and a warm
113 * boot.
114 *
115 * This functions returns:
116 * - 0 for a cold boot.
117 * - Any other value for a warm boot.
118 * ---------------------------------------------------------------------
119 */
120func plat_get_my_entrypoint
121 mov x1, x30
122 bl plat_is_my_cpu_primary
123 /*
124 * Secondaries always cold boot.
125 */
126 cbz w0, 1f
127 /*
128 * Primaries warm boot if they are requested
129 * to power off.
130 */
131 mov_imm x0, PLAT_NPCM_TM_HOLD_BASE
132 ldr x0, [x0]
133 cmp x0, PLAT_NPCM_TM_HOLD_STATE_BSP_OFF
134 adr x0, plat_wait_for_warm_boot
135 csel x0, x0, xzr, eq
136 ret x1
1371: mov x0, #0
138 ret x1
139endfunc plat_get_my_entrypoint
140
141func npcm845x_mailbox_init
142 adrp x1, mailbox_base
143 str x0, [x1, :lo12:mailbox_base]
144 ret
145endfunc npcm845x_mailbox_init
146
147func plat_wait_for_warm_boot
148 /*
149 * Calculate address of our hold entry.
150 * As the function will never return, there is no need to save LR.
151 */
152 bl plat_my_core_pos
153 lsl x0, x0, #3
154 mov x8, x0
155 mov_imm x2, PLAT_NPCM_TM_HOLD_BASE
156 add x0, x0, x2
157 mov_imm x2, PLAT_NPCM_TRUSTED_NOTIFICATION_BASE
158 add x8, x8, x2
159 /*
160 * This code runs way before requesting the warmboot of this core,
161 * so it is possible to clear the mailbox before getting a request
162 * to boot.
163 */
164 mov x1, PLAT_NPCM_TM_HOLD_STATE_WAIT
165 str x1,[x0]
166
167 /* Notify that core is in pending state - do not use x0!, uses x7 and x8! */
168 mov x7, PLAT_NPCM_TM_NOTIFICATION_START
169 str x7,[x8]
170 /*
171 * This code runs way before requesting the warmboot of this core,
172 * so it is possible to clear the mailbox before getting a request
173 * to boot.
174 */
175 mov x1, PLAT_NPCM_TM_HOLD_STATE_WAIT
176 str x1,[x0]
177 /* Wait until we have a go */
178poll_mailbox:
179 wfe
180 ldr x1, [x0]
181 cmp x1, PLAT_NPCM_TM_HOLD_STATE_GO
182 bne poll_mailbox
183
184 mov x7, PLAT_NPCM_TM_NOTIFICATION_BR
185 str x7,[x8]
186 /* Jump to the provided entrypoint */
187 mov_imm x0, PLAT_NPCM_TM_ENTRYPOINT
188 ldr x1, [x0]
189 br x1
190endfunc plat_wait_for_warm_boot
191
192func plat_secondary_cold_boot_setup
193 b plat_wait_for_warm_boot
194endfunc plat_secondary_cold_boot_setup
195
196func plat_crash_console_init
197 mov x0, #1
198 ret
199endfunc plat_crash_console_init
200
201func plat_crash_console_putc
202 ret
203endfunc plat_crash_console_putc
204
205func plat_crash_console_flush
206 mov x0, #0
207 ret
208endfunc plat_crash_console_flush
209
210func platform_mem_init
211 ret
212endfunc platform_mem_init
213
214#endif /* NUVOTON_HELPERS_S */