blob: e15d587f2901e4133566551a929fd06176298323 [file] [log] [blame]
Marc Zyngier0237c632014-07-18 21:06:38 +01001/*
2 * Copyright (C) 2013 - ARM Ltd
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 * Based on code by Carl van Schaik <carl@ok-labs.com>.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <config.h>
Wang Dongshengf8fc7be2015-06-04 12:01:08 +080021
22#include <asm/arch-armv7/generictimer.h>
Jan Kiszkafdb0ff72014-12-31 13:46:40 +010023#include <asm/gic.h>
Jan Kiszka2ecdd682015-04-21 07:18:26 +020024#include <asm/macro.h>
Marc Zyngier0237c632014-07-18 21:06:38 +010025#include <asm/psci.h>
26#include <asm/arch/cpu.h>
27
28/*
29 * Memory layout:
30 *
31 * SECURE_RAM to text_end :
32 * ._secure_text section
33 * text_end to ALIGN_PAGE(text_end):
34 * nothing
35 * ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000)
36 * 1kB of stack per CPU (4 CPUs max).
37 */
38
39 .pushsection ._secure.text, "ax"
40
41 .arch_extension sec
42
Iain Paton630df142015-03-28 10:26:38 +000043#define ONE_MS (CONFIG_TIMER_CLK_FREQ / 1000)
Marc Zyngier0237c632014-07-18 21:06:38 +010044#define TEN_MS (10 * ONE_MS)
Jan Kiszkafdb0ff72014-12-31 13:46:40 +010045#define GICD_BASE 0x1c81000
46#define GICC_BASE 0x1c82000
Marc Zyngier0237c632014-07-18 21:06:38 +010047
Jan Kiszkafdb0ff72014-12-31 13:46:40 +010048.globl psci_fiq_enter
49psci_fiq_enter:
50 push {r0-r12}
51
52 @ Switch to secure
53 mrc p15, 0, r7, c1, c1, 0
54 bic r8, r7, #1
55 mcr p15, 0, r8, c1, c1, 0
56 isb
57
58 @ Validate reason based on IAR and acknowledge
59 movw r8, #(GICC_BASE & 0xffff)
60 movt r8, #(GICC_BASE >> 16)
61 ldr r9, [r8, #GICC_IAR]
62 movw r10, #0x3ff
63 movt r10, #0
64 cmp r9, r10 @ skip spurious interrupt 1023
65 beq out
66 movw r10, #0x3fe @ ...and 1022
67 cmp r9, r10
68 beq out
69 str r9, [r8, #GICC_EOIR] @ acknowledge the interrupt
70 dsb
71
72 @ Compute CPU number
73 lsr r9, r9, #10
74 and r9, r9, #0xf
75
76 movw r8, #(SUN7I_CPUCFG_BASE & 0xffff)
77 movt r8, #(SUN7I_CPUCFG_BASE >> 16)
78
79 @ Wait for the core to enter WFI
80 lsl r11, r9, #6 @ x64
81 add r11, r11, r8
82
831: ldr r10, [r11, #0x48]
84 tst r10, #(1 << 2)
85 bne 2f
86 timer_wait r10, ONE_MS
87 b 1b
88
89 @ Reset CPU
902: mov r10, #0
91 str r10, [r11, #0x40]
92
93 @ Lock CPU
94 mov r10, #1
95 lsl r9, r10, r9 @ r9 is now CPU mask
96 ldr r10, [r8, #0x1e4]
97 bic r10, r10, r9
98 str r10, [r8, #0x1e4]
99
100 @ Set power gating
101 ldr r10, [r8, #0x1b4]
102 orr r10, r10, #1
103 str r10, [r8, #0x1b4]
104 timer_wait r10, ONE_MS
105
106 @ Activate power clamp
107 mov r10, #1
1081: str r10, [r8, #0x1b0]
109 lsl r10, r10, #1
110 orr r10, r10, #1
111 tst r10, #0x100
112 beq 1b
113
114 @ Restore security level
115out: mcr p15, 0, r7, c1, c1, 0
116
117 pop {r0-r12}
118 subs pc, lr, #4
119
Marc Zyngier0237c632014-07-18 21:06:38 +0100120 @ r1 = target CPU
121 @ r2 = target PC
122.globl psci_cpu_on
123psci_cpu_on:
Jan Kiszkab73b1e22015-04-21 07:18:30 +0200124 push {lr}
125
126 mov r0, r1
127 bl psci_get_cpu_stack_top @ get stack top of target CPU
128 str r2, [r0] @ store target PC at stack top
Marc Zyngier0237c632014-07-18 21:06:38 +0100129 dsb
130
Hans de Goede316e29b2014-10-27 23:59:27 +0100131 movw r0, #(SUN7I_CPUCFG_BASE & 0xffff)
132 movt r0, #(SUN7I_CPUCFG_BASE >> 16)
Marc Zyngier0237c632014-07-18 21:06:38 +0100133
134 @ CPU mask
135 and r1, r1, #3 @ only care about first cluster
136 mov r4, #1
137 lsl r4, r4, r1
138
Jan Kiszkab6680e62015-04-21 07:18:28 +0200139 ldr r6, =psci_cpu_entry
Marc Zyngier0237c632014-07-18 21:06:38 +0100140 str r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
141
142 @ Assert reset on target CPU
143 mov r6, #0
144 lsl r5, r1, #6 @ 64 bytes per CPU
145 add r5, r5, #0x40 @ Offset from base
146 add r5, r5, r0 @ CPU control block
147 str r6, [r5] @ Reset CPU
148
149 @ l1 invalidate
Chen-Yu Tsaif147d942015-05-28 21:25:29 +0800150 ldr r6, [r0, #0x184] @ CPUCFG_GEN_CTRL_REG
Marc Zyngier0237c632014-07-18 21:06:38 +0100151 bic r6, r6, r4
152 str r6, [r0, #0x184]
153
Chen-Yu Tsaif147d942015-05-28 21:25:29 +0800154 @ Lock CPU (Disable external debug access)
155 ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
Marc Zyngier0237c632014-07-18 21:06:38 +0100156 bic r6, r6, r4
157 str r6, [r0, #0x1e4]
158
159 @ Release power clamp
160 movw r6, #0x1ff
161 movt r6, #0
1621: lsrs r6, r6, #1
Chen-Yu Tsaif147d942015-05-28 21:25:29 +0800163 str r6, [r0, #0x1b0] @ CPU1_PWR_CLAMP
Marc Zyngier0237c632014-07-18 21:06:38 +0100164 bne 1b
165
166 timer_wait r1, TEN_MS
167
168 @ Clear power gating
Chen-Yu Tsaif147d942015-05-28 21:25:29 +0800169 ldr r6, [r0, #0x1b4] @ CPU1_PWROFF_REG
Marc Zyngier0237c632014-07-18 21:06:38 +0100170 bic r6, r6, #1
171 str r6, [r0, #0x1b4]
172
173 @ Deassert reset on target CPU
174 mov r6, #3
175 str r6, [r5]
176
Chen-Yu Tsaif147d942015-05-28 21:25:29 +0800177 @ Unlock CPU (Enable external debug access)
178 ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
Marc Zyngier0237c632014-07-18 21:06:38 +0100179 orr r6, r6, r4
180 str r6, [r0, #0x1e4]
181
182 mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS
Jan Kiszkab73b1e22015-04-21 07:18:30 +0200183 pop {pc}
Marc Zyngier0237c632014-07-18 21:06:38 +0100184
Jan Kiszkafdb0ff72014-12-31 13:46:40 +0100185.globl psci_cpu_off
186psci_cpu_off:
Jan Kiszka80c26bc2015-04-21 07:18:27 +0200187 bl psci_cpu_off_common
Jan Kiszkafdb0ff72014-12-31 13:46:40 +0100188
189 @ Ask CPU0 to pull the rug...
190 movw r0, #(GICD_BASE & 0xffff)
191 movt r0, #(GICD_BASE >> 16)
192 movw r1, #15 @ SGI15
193 movt r1, #1 @ Target is CPU0
194 str r1, [r0, #GICD_SGIR]
195 dsb
196
1971: wfi
198 b 1b
199
Jan Kiszkaf2f9a802014-12-31 13:46:42 +0100200.globl psci_arch_init
201psci_arch_init:
Jan Kiszka2ecdd682015-04-21 07:18:26 +0200202 mov r6, lr
203
Jan Kiszkaf2f9a802014-12-31 13:46:42 +0100204 movw r4, #(GICD_BASE & 0xffff)
205 movt r4, #(GICD_BASE >> 16)
206
207 ldr r5, [r4, #GICD_IGROUPRn]
208 bic r5, r5, #(1 << 15) @ SGI15 as Group-0
209 str r5, [r4, #GICD_IGROUPRn]
210
211 mov r5, #0 @ Set SGI15 priority to 0
212 strb r5, [r4, #(GICD_IPRIORITYRn + 15)]
213
214 add r4, r4, #0x1000 @ GICC address
215
216 mov r5, #0xff
217 str r5, [r4, #GICC_PMR] @ Be cool with non-secure
218
219 ldr r5, [r4, #GICC_CTLR]
220 orr r5, r5, #(1 << 3) @ Switch FIQEn on
221 str r5, [r4, #GICC_CTLR]
222
223 mrc p15, 0, r5, c1, c1, 0 @ Read SCR
224 orr r5, r5, #4 @ Enable FIQ in monitor mode
225 bic r5, r5, #1 @ Secure mode
226 mcr p15, 0, r5, c1, c1, 0 @ Write SCR
227 isb
228
Jan Kiszka9c0f35a2015-04-21 07:18:29 +0200229 bl psci_get_cpu_id @ CPU ID => r0
230 bl psci_get_cpu_stack_top @ stack top => r0
231 mov sp, r0
Jan Kiszkaf2f9a802014-12-31 13:46:42 +0100232
Jan Kiszka2ecdd682015-04-21 07:18:26 +0200233 bx r6
Jan Kiszkaf2f9a802014-12-31 13:46:42 +0100234
Jan Kiszka9c0f35a2015-04-21 07:18:29 +0200235 .globl psci_text_end
236psci_text_end:
Marc Zyngier0237c632014-07-18 21:06:38 +0100237 .popsection