arm: tegra: Move driver files to drivers/platform
[linux-3.10.git] / arch / arm64 / mach-tegra / reset-handler.S
1 /*
2  * Copyright (c) 2013-2014, 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/assembler.h>
23 #include <asm/memory.h>
24
25 #include <linux/platform/tegra/flowctrl.h>
26 #include "iomap.h"
27 #include <linux/platform/tegra/reset.h>
28
29 #define PMC_SCRATCH41   0x140
30 #define INVALID_HWID    ~0
31
32 #define CNTFRQ  12000000
33 #define GIC_DIST_BASE   0x50041000
34 #define GIC_CPU_BASE    0x50042000
35
36 /* returns the offset of the flow controller csr register for a cpu */
37 .macro cpu_to_csr_reg rd, rcpu
38         cmp     \rcpu, #0
39         beq 1f
40         sub     \rd, \rcpu, #1
41         lsl     \rd, \rd, #3
42         add     \rd, \rd, #0x18
43         b       2f
44 1:
45         mov     \rd, #8
46 2:
47 .endm
48
49 #ifdef CONFIG_PM_SLEEP
50 /*
51  *      CPU boot vector after LP0 exit.
52  */
53 ENTRY(tegra_resume)
54         /*
55          * EL3 initialisation
56          */
57         mrs     x0, CurrentEL
58         cmp     x0, #0xc                        // EL3?
59         b.ne    start_ns                        // skip EL3 initialisation
60
61         mov     x0, #0x30                               // RES1
62         orr     x0, x0, #(1 << 10)              // 64-bit EL1 (skip EL2)
63         msr     scr_el3, x0
64
65         msr     cptr_el3, xzr                   // Disable copro. traps to EL3
66         msr     sctlr_el2, xzr
67
68         ldr     x0, =CNTFRQ
69         msr     cntfrq_el0, x0
70
71         /*
72          * Check for the primary CPU to avoid a race on the distributor
73          * registers.
74          */
75         mrs     x0, mpidr_el1
76         tst     x0, #15
77         b.ne    1f                              // secondary CPU
78
79         ldr     x1, =GIC_DIST_BASE              // GICD_CTLR
80         mov     w0, #3                          // EnableGrp0 | EnableGrp1
81         str     w0, [x1]
82
83 1:      ldr     x1, =GIC_DIST_BASE + 0x80       // GICD_IGROUPR
84         mov     w0, #0                          // Grp0 (secure) interrupts
85         str     w0, [x1], #4                    // SGI and PPI (#0~31)
86         b.ne    2f                              // Only local interrupts for secondary CPUs
87         str     w0, [x1], #4                    // SPI (#32~191)
88         str     w0, [x1], #4
89         str     w0, [x1], #4
90         str     w0, [x1], #4
91         str     w0, [x1], #4
92
93 2:      ldr     x1, =GIC_CPU_BASE               // GICC_CTLR
94         ldr     w0, [x1]
95         mov     w0, #3                          // EnableGrp0 | EnableGrp1
96         str     w0, [x1]
97
98         mov     w0, #1 << 7                     // allow NS access to GICC_PMR
99         str     w0, [x1, #4]                    // GICC_PMR
100
101         msr     sctlr_el2, xzr
102
103         /*
104          * Prepare the switch to the secure EL1_SP1 mode from EL3
105          */
106         adr     x0, start_ns                    // Return after mode switch
107         mov     x1, #0x3c5              // EL1_SP1 | D | A | I | F
108         msr     elr_el3, x0
109         msr     spsr_el3, x1
110         eret
111
112 start_ns:
113         mrs     x0, mpidr_el1
114         and x0, x0, #15
115
116         /* Clear the flow controller flags for this CPU. */
117         cpu_to_csr_reg  x1, x0
118         ldr     x2, =TEGRA_FLOW_CTRL_BASE
119         ldr     x3, [x2, x1]
120
121         /* Clear event & intr flag */
122         orr     x3, x3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
123
124         /* enable, cluster_switch, immed, & bitmaps */
125         movz    x0, #0x3ffd
126
127         bic     x3, x3, x0
128         str     x3, [x2, x1]
129
130 done:
131         b       cpu_resume
132 ENDPROC(tegra_resume)
133 #endif
134
135 #ifdef CONFIG_PM_SLEEP
136 /* start of timestamps */
137 .globl tegra_resume_timestamps_start
138 tegra_resume_timestamps_start:
139
140 .globl tegra_resume_smc_entry_time
141 tegra_resume_smc_entry_time:
142         .long   0
143 .globl tegra_resume_smc_exit_time
144 tegra_resume_smc_exit_time:
145         .long   0
146 .globl tegra_resume_entry_time
147 tegra_resume_entry_time:
148         .long   0
149
150 /* end of timestamps */
151 .global tegra_resume_timestamps_end
152 tegra_resume_timestamps_end:
153 #endif
154
155         .align L1_CACHE_SHIFT
156 ENTRY(__tegra_cpu_reset_handler_start)
157
158 /*
159  * __tegra_cpu_reset_handler:
160  *
161  * Common handler for all CPU reset events.
162  *
163  * Register usage within the reset handler:
164  *
165  *      Others: scratch
166  *      x6  = SoC ID << 8
167  *      x7  = CPU present (to the OS) mask
168  *      x8  = CPU in LP1 state mask
169  *      x9  = CPU in LP2 state mask
170  *      x10 = CPU number
171  *      x11 = CPU mask
172  *      x12 = pointer to reset handler data
173  *
174  * NOTE: This code is copied to IRAM. All code and data accesses
175  *       must be position-independent.
176  */
177
178         .align L1_CACHE_SHIFT
179 ENTRY(__tegra_cpu_reset_handler)
180         disable_irq
181
182 #ifdef CONFIG_SMP
183         mrs     x10, mpidr_el1
184 #else
185         mov x10, #0
186 #endif
187
188         and     x10, x10, #0xf
189         and     x10, x10, #0x3          /* x10 = cpu id */
190
191         mov x11, #1
192         lsl x11, x11, x10               /* x11 = CPU mask */
193
194         adr x12, __tegra_cpu_reset_handler_data
195
196 #ifdef CONFIG_SMP
197         /* Does the OS know about this CPU? */
198         ldr     x7, [x12, #RESET_DATA(MASK_PRESENT)]
199         tst     x7, x11                 /* if !present */
200         beq             __die           /* CPU not present (to OS) */
201 #endif
202
203         /* Waking up from LP1? */
204         ldr     x8, [x12, #RESET_DATA(MASK_LP1)]
205         tst     x8, x11                         /* if in_lp1 */
206         beq     __is_not_lp1
207         cmp     x10, #0
208         bne     __die                           /* only CPU0 can be here */
209         ldr     lr, [x12, #RESET_DATA(STARTUP_LP1)]
210         cmp     lr, #0
211         beq     __die                           /* no LP1 startup handler */
212         ret
213 __is_not_lp1:
214
215         /* Waking up from LP2? */
216         ldr     x9, [x12, #RESET_DATA(MASK_LP2)]
217         tst     x9, x11                         /* if in_lp2 */
218         beq     __is_not_lp2
219         ldr     lr, [x12, #RESET_DATA(STARTUP_LP2)]
220         cmp     lr, #0
221         beq     __die                           /* no LP2 startup handler */
222         ret
223
224 __is_not_lp2:
225
226 #ifdef CONFIG_SMP
227         ldr     lr, [x12, #RESET_DATA(STARTUP_SECONDARY)]
228         cmp     lr, #0
229         beq     __die                   /* no secondary startup handler */
230         ret
231 #endif
232
233 /*
234  * We don't know why the CPU reset. Just kill it.
235  */
236
237 __die:
238         /* just spin here for now */
239         b       .
240 ENDPROC(__tegra_cpu_reset_handler)
241
242         .align L1_CACHE_SHIFT
243         .type   __tegra_cpu_reset_handler_data, %object
244         .globl  __tegra_cpu_reset_handler_data
245 __tegra_cpu_reset_handler_data:
246         .rept   TEGRA_RESET_DATA_SIZE
247         .quad   0
248         .endr
249         .align L1_CACHE_SHIFT
250
251 ENTRY(__tegra_cpu_reset_handler_end)