blob: b9ea78b84e5479135b8bc1e5b306536dbf4e9c37 [file] [log] [blame]
Marc Zyngierd5db7022014-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>
21#include <asm/psci.h>
22#include <asm/arch/cpu.h>
23
24/*
25 * Memory layout:
26 *
27 * SECURE_RAM to text_end :
28 * ._secure_text section
29 * text_end to ALIGN_PAGE(text_end):
30 * nothing
31 * ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000)
32 * 1kB of stack per CPU (4 CPUs max).
33 */
34
35 .pushsection ._secure.text, "ax"
36
37 .arch_extension sec
38
39#define ONE_MS (CONFIG_SYS_CLK_FREQ / 1000)
40#define TEN_MS (10 * ONE_MS)
41
42.macro timer_wait reg, ticks
43 @ Program CNTP_TVAL
44 movw \reg, #(\ticks & 0xffff)
45 movt \reg, #(\ticks >> 16)
46 mcr p15, 0, \reg, c14, c2, 0
47 isb
48 @ Enable physical timer, mask interrupt
49 mov \reg, #3
50 mcr p15, 0, \reg, c14, c2, 1
51 @ Poll physical timer until ISTATUS is on
521: isb
53 mrc p15, 0, \reg, c14, c2, 1
54 ands \reg, \reg, #4
55 bne 1b
56 @ Disable timer
57 mov \reg, #0
58 mcr p15, 0, \reg, c14, c2, 1
59 isb
60.endm
61
62.globl psci_arch_init
63psci_arch_init:
64 mrc p15, 0, r5, c1, c1, 0 @ Read SCR
65 bic r5, r5, #1 @ Secure mode
66 mcr p15, 0, r5, c1, c1, 0 @ Write SCR
67 isb
68
69 mrc p15, 0, r4, c0, c0, 5 @ MPIDR
70 and r4, r4, #3 @ cpu number in cluster
71 mov r5, #400 @ 1kB of stack per CPU
72 mul r4, r4, r5
73
74 adr r5, text_end @ end of text
75 add r5, r5, #0x2000 @ Skip two pages
76 lsr r5, r5, #12 @ Align to start of page
77 lsl r5, r5, #12
78 sub sp, r5, r4 @ here's our stack!
79
80 bx lr
81
82 @ r1 = target CPU
83 @ r2 = target PC
84.globl psci_cpu_on
85psci_cpu_on:
86 adr r0, _target_pc
87 str r2, [r0]
88 dsb
89
Hans de Goede9d8a5332014-10-27 23:59:27 +010090 movw r0, #(SUN7I_CPUCFG_BASE & 0xffff)
91 movt r0, #(SUN7I_CPUCFG_BASE >> 16)
Marc Zyngierd5db7022014-07-18 21:06:38 +010092
93 @ CPU mask
94 and r1, r1, #3 @ only care about first cluster
95 mov r4, #1
96 lsl r4, r4, r1
97
98 adr r6, _sunxi_cpu_entry
99 str r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
100
101 @ Assert reset on target CPU
102 mov r6, #0
103 lsl r5, r1, #6 @ 64 bytes per CPU
104 add r5, r5, #0x40 @ Offset from base
105 add r5, r5, r0 @ CPU control block
106 str r6, [r5] @ Reset CPU
107
108 @ l1 invalidate
109 ldr r6, [r0, #0x184]
110 bic r6, r6, r4
111 str r6, [r0, #0x184]
112
113 @ Lock CPU
114 ldr r6, [r0, #0x1e4]
115 bic r6, r6, r4
116 str r6, [r0, #0x1e4]
117
118 @ Release power clamp
119 movw r6, #0x1ff
120 movt r6, #0
1211: lsrs r6, r6, #1
122 str r6, [r0, #0x1b0]
123 bne 1b
124
125 timer_wait r1, TEN_MS
126
127 @ Clear power gating
128 ldr r6, [r0, #0x1b4]
129 bic r6, r6, #1
130 str r6, [r0, #0x1b4]
131
132 @ Deassert reset on target CPU
133 mov r6, #3
134 str r6, [r5]
135
136 @ Unlock CPU
137 ldr r6, [r0, #0x1e4]
138 orr r6, r6, r4
139 str r6, [r0, #0x1e4]
140
141 mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS
142 mov pc, lr
143
144_target_pc:
145 .word 0
146
147_sunxi_cpu_entry:
148 @ Set SMP bit
149 mrc p15, 0, r0, c1, c0, 1
150 orr r0, r0, #0x40
151 mcr p15, 0, r0, c1, c0, 1
152 isb
153
154 bl _nonsec_init
155 bl psci_arch_init
156
157 adr r0, _target_pc
158 ldr r0, [r0]
159 b _do_nonsec_entry
160
161text_end:
162 .popsection