ARM: rockchip: rk3228: implement function rk3228_restart
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-tegra / reset-handler.S
1 /*
2  * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/linkage.h>
18 #include <linux/init.h>
19
20 #include <asm/cache.h>
21 #include <asm/asm-offsets.h>
22 #include <asm/hardware/cache-l2x0.h>
23
24 #include "flowctrl.h"
25 #include "iomap.h"
26 #include "reset.h"
27 #include "sleep.h"
28
29 #define APB_MISC_GP_HIDREV      0x804
30 #define PMC_SCRATCH41   0x140
31
32 #define RESET_DATA(x)   ((TEGRA_RESET_##x)*4)
33
34 #ifdef CONFIG_PM_SLEEP
35 /*
36  *      tegra_resume
37  *
38  *        CPU boot vector when restarting the a CPU following
39  *        an LP2 transition. Also branched to by LP0 and LP1 resume after
40  *        re-enabling sdram.
41  */
42 ENTRY(tegra_resume)
43         bl      v7_invalidate_l1
44
45         cpu_id  r0
46         cmp     r0, #0                          @ CPU0?
47  THUMB( it      ne )
48         bne     cpu_resume                      @ no
49
50 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
51         /* Are we on Tegra20? */
52         mov32   r6, TEGRA_APB_MISC_BASE
53         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
54         and     r0, r0, #0xff00
55         cmp     r0, #(0x20 << 8)
56         beq     1f                              @ Yes
57         /* Clear the flow controller flags for this CPU. */
58         mov32   r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR   @ CPU0 CSR
59         ldr     r1, [r2]
60         /* Clear event & intr flag */
61         orr     r1, r1, \
62                 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
63         movw    r0, #0x0FFD     @ enable, cluster_switch, immed, & bitmaps
64         bic     r1, r1, r0
65         str     r1, [r2]
66 1:
67 #endif
68
69 #ifdef CONFIG_HAVE_ARM_SCU
70         /* enable SCU */
71         mov32   r0, TEGRA_ARM_PERIF_BASE
72         ldr     r1, [r0]
73         orr     r1, r1, #1
74         str     r1, [r0]
75 #endif
76
77         /* L2 cache resume & re-enable */
78         l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
79
80         b       cpu_resume
81 ENDPROC(tegra_resume)
82 #endif
83
84 #ifdef CONFIG_CACHE_L2X0
85         .globl  l2x0_saved_regs_addr
86 l2x0_saved_regs_addr:
87         .long   0
88 #endif
89
90         .align L1_CACHE_SHIFT
91 ENTRY(__tegra_cpu_reset_handler_start)
92
93 /*
94  * __tegra_cpu_reset_handler:
95  *
96  * Common handler for all CPU reset events.
97  *
98  * Register usage within the reset handler:
99  *
100  *      Others: scratch
101  *      R6  = SoC ID << 8
102  *      R7  = CPU present (to the OS) mask
103  *      R8  = CPU in LP1 state mask
104  *      R9  = CPU in LP2 state mask
105  *      R10 = CPU number
106  *      R11 = CPU mask
107  *      R12 = pointer to reset handler data
108  *
109  * NOTE: This code is copied to IRAM. All code and data accesses
110  *       must be position-independent.
111  */
112
113         .align L1_CACHE_SHIFT
114 ENTRY(__tegra_cpu_reset_handler)
115
116         cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
117
118         mov32   r6, TEGRA_APB_MISC_BASE
119         ldr     r6, [r6, #APB_MISC_GP_HIDREV]
120         and     r6, r6, #0xff00
121 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
122 t20_check:
123         cmp     r6, #(0x20 << 8)
124         bne     after_t20_check
125 t20_errata:
126         # Tegra20 is a Cortex-A9 r1p1
127         mrc     p15, 0, r0, c1, c0, 0   @ read system control register
128         orr     r0, r0, #1 << 14        @ erratum 716044
129         mcr     p15, 0, r0, c1, c0, 0   @ write system control register
130         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
131         orr     r0, r0, #1 << 4         @ erratum 742230
132         orr     r0, r0, #1 << 11        @ erratum 751472
133         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
134         b       after_errata
135 after_t20_check:
136 #endif
137 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
138 t30_check:
139         cmp     r6, #(0x30 << 8)
140         bne     after_t30_check
141 t30_errata:
142         # Tegra30 is a Cortex-A9 r2p9
143         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
144         orr     r0, r0, #1 << 6         @ erratum 743622
145         orr     r0, r0, #1 << 11        @ erratum 751472
146         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
147         b       after_errata
148 after_t30_check:
149 #endif
150 after_errata:
151         mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
152         and     r10, r10, #0x3                  @ R10 = CPU number
153         mov     r11, #1
154         mov     r11, r11, lsl r10               @ R11 = CPU mask
155         adr     r12, __tegra_cpu_reset_handler_data
156
157 #ifdef CONFIG_SMP
158         /* Does the OS know about this CPU? */
159         ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
160         tst     r7, r11                         @ if !present
161         bleq    __die                           @ CPU not present (to OS)
162 #endif
163
164 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
165         /* Are we on Tegra20? */
166         cmp     r6, #(0x20 << 8)
167         bne     1f
168         /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
169         mov32   r5, TEGRA_PMC_BASE
170         mov     r0, #0
171         cmp     r10, #0
172         strne   r0, [r5, #PMC_SCRATCH41]
173 1:
174 #endif
175
176         /* Waking up from LP2? */
177         ldr     r9, [r12, #RESET_DATA(MASK_LP2)]
178         tst     r9, r11                         @ if in_lp2
179         beq     __is_not_lp2
180         ldr     lr, [r12, #RESET_DATA(STARTUP_LP2)]
181         cmp     lr, #0
182         bleq    __die                           @ no LP2 startup handler
183         bx      lr
184
185 __is_not_lp2:
186
187 #ifdef CONFIG_SMP
188         /*
189          * Can only be secondary boot (initial or hotplug) but CPU 0
190          * cannot be here.
191          */
192         cmp     r10, #0
193         bleq    __die                           @ CPU0 cannot be here
194         ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
195         cmp     lr, #0
196         bleq    __die                           @ no secondary startup handler
197         bx      lr
198 #endif
199
200 /*
201  * We don't know why the CPU reset. Just kill it.
202  * The LR register will contain the address we died at + 4.
203  */
204
205 __die:
206         sub     lr, lr, #4
207         mov32   r7, TEGRA_PMC_BASE
208         str     lr, [r7, #PMC_SCRATCH41]
209
210         mov32   r7, TEGRA_CLK_RESET_BASE
211
212         /* Are we on Tegra20? */
213         mov32   r6, TEGRA_APB_MISC_BASE
214         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
215         and     r0, r0, #0xff00
216         cmp     r0, #(0x20 << 8)
217         bne     1f
218
219 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
220         mov32   r0, 0x1111
221         mov     r1, r0, lsl r10
222         str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
223 #endif
224 1:
225 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
226         mov32   r6, TEGRA_FLOW_CTRL_BASE
227
228         cmp     r10, #0
229         moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
230         moveq   r2, #FLOW_CTRL_CPU0_CSR
231         movne   r1, r10, lsl #3
232         addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
233         addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
234
235         /* Clear CPU "event" and "interrupt" flags and power gate
236            it when halting but not before it is in the "WFI" state. */
237         ldr     r0, [r6, +r2]
238         orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
239         orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
240         str     r0, [r6, +r2]
241
242         /* Unconditionally halt this CPU */
243         mov     r0, #FLOW_CTRL_WAITEVENT
244         str     r0, [r6, +r1]
245         ldr     r0, [r6, +r1]                   @ memory barrier
246
247         dsb
248         isb
249         wfi                                     @ CPU should be power gated here
250
251         /* If the CPU didn't power gate above just kill it's clock. */
252
253         mov     r0, r11, lsl #8
254         str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
255 #endif
256
257         /* If the CPU still isn't dead, just spin here. */
258         b       .
259 ENDPROC(__tegra_cpu_reset_handler)
260
261         .align L1_CACHE_SHIFT
262         .type   __tegra_cpu_reset_handler_data, %object
263         .globl  __tegra_cpu_reset_handler_data
264 __tegra_cpu_reset_handler_data:
265         .rept   TEGRA_RESET_DATA_SIZE
266         .long   0
267         .endr
268         .align L1_CACHE_SHIFT
269
270 ENTRY(__tegra_cpu_reset_handler_end)