• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
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
13	.globl	plat_secondary_cold_boot_setup
14	.globl	plat_get_my_entrypoint
15	.globl	plat_is_my_cpu_primary
16	.globl	plat_arm_calc_core_pos
17
18	/* --------------------------------------------------------------------
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
30	/* ---------------------------------------------------------------------
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
99	ldr	r1, =MPIDR_AFFINITY_MASK
100	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
106
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
139