blob: 5215c2409140c015a9b3386301c189161a6090d7 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Idle processing for ARMv7-based Qualcomm SoCs.
3 *
4 * Copyright (C) 2007 Google, Inc.
5 * Copyright (c) 2007-2009, 2011 Code Aurora Forum. All rights reserved.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
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 */
17
18#include <linux/linkage.h>
19#include <linux/threads.h>
20#include <asm/assembler.h>
21
22#ifdef CONFIG_MSM_CPU_AVS
23/* 11 general purpose registers (r4-r14), 10 cp15 registers, 3 AVS registers */
24#define CPU_SAVED_STATE_SIZE (4 * 11 + 4 * 10 + 4 * 3)
25#else
26/* 11 general purpose registers (r4-r14), 10 cp15 registers */
27#define CPU_SAVED_STATE_SIZE (4 * 11 + 4 * 10)
28#endif
Maheshkumar Sivasubramanianfa1d0dd2011-07-26 16:02:55 -060029#ifdef CONFIG_ARCH_MSM_KRAIT
30#define SCM_SVC_BOOT 0x1
31#define SCM_CMD_TERMINATE_PC 0x2
32#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070033
34ENTRY(msm_arch_idle)
35 stmfd sp!, {lr}
36#ifdef CONFIG_MSM_JTAG_V7
37 bl msm_save_jtag_debug
38#endif
39#ifdef CONFIG_MSM_ETM
40 bl etm_save_reg_check
41#endif
42 wfi
43#ifdef CONFIG_MSM_ETM
44 bl etm_restore_reg_check
45#endif
46#ifdef CONFIG_MSM_JTAG_V7
47 bl msm_restore_jtag_debug
48#endif
49 ldmfd sp!, {lr}
50 bx lr
51
52ENTRY(msm_pm_collapse)
53#if defined(CONFIG_MSM_FIQ_SUPPORT)
54 cpsid f
55#endif
56
57 ldr r0, =saved_state
58#if (NR_CPUS >= 2)
59 mrc p15, 0, r1, c0, c0, 5 /* MPIDR */
60 ands r1, r1, #15 /* What CPU am I */
61 addne r0, r0, #CPU_SAVED_STATE_SIZE
62#endif
63
64 stmia r0!, {r4-r14}
65 mrc p15, 0, r1, c1, c0, 0 /* MMU control */
66 mrc p15, 0, r2, c2, c0, 0 /* TTBR0 */
67 mrc p15, 0, r3, c3, c0, 0 /* dacr */
68#ifdef CONFIG_ARCH_MSM_SCORPION
69 /* This instruction is not valid for non scorpion processors */
70 mrc p15, 3, r4, c15, c0, 3 /* L2CR1 is the L2 cache control reg 1 */
71#endif
72 mrc p15, 0, r5, c10, c2, 0 /* PRRR */
73 mrc p15, 0, r6, c10, c2, 1 /* NMRR */
74 mrc p15, 0, r7, c1, c0, 1 /* ACTLR */
75 mrc p15, 0, r8, c2, c0, 1 /* TTBR1 */
76 mrc p15, 0, r9, c13, c0, 3 /* TPIDRURO */
77 mrc p15, 0, ip, c13, c0, 1 /* context ID */
78 stmia r0!, {r1-r9, ip}
79#ifdef CONFIG_MSM_CPU_AVS
80 mrc p15, 7, r1, c15, c1, 7 /* AVSCSR is the Adaptive Voltage Scaling
81 * Control and Status Register */
82 mrc p15, 7, r2, c15, c0, 6 /* AVSDSCR is the Adaptive Voltage
83 * Scaling Delay Synthesizer Control
84 * Register */
85#ifndef CONFIG_ARCH_MSM_KRAIT
86 mrc p15, 7, r3, c15, c1, 0 /* TSCSR is the Temperature Status and
87 * Control Register
88 */
89#endif
90
91 stmia r0!, {r1-r3}
92#endif
93
94#ifdef CONFIG_MSM_JTAG_V7
95 bl msm_save_jtag_debug
96#endif
97#ifdef CONFIG_MSM_ETM
98 bl etm_save_reg_check
99#endif
100 bl v7_flush_dcache_all
101
Maheshkumar Sivasubramanianfa1d0dd2011-07-26 16:02:55 -0600102 mrc p15, 0, r4, c1, c0, 0 /* read current CR */
103 bic r0, r4, #(1 << 2) /* clear dcache bit */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700104 bic r0, r0, #(1 << 12) /* clear icache bit */
105 mcr p15, 0, r0, c1, c0, 0 /* disable d/i cache */
106
107 dsb
Maheshkumar Sivasubramanianfa1d0dd2011-07-26 16:02:55 -0600108#ifdef CONFIG_ARCH_MSM_KRAIT
109 ldr r0, =SCM_SVC_BOOT
110 ldr r1, =SCM_CMD_TERMINATE_PC
111 ldr r2, =0
112 bl scm_call_atomic1
113#else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700114 wfi
Maheshkumar Sivasubramanianfa1d0dd2011-07-26 16:02:55 -0600115#endif
116 mcr p15, 0, r4, c1, c0, 0 /* restore d/i cache */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117 isb
118
119#if defined(CONFIG_MSM_FIQ_SUPPORT)
120 cpsie f
121#endif
122#ifdef CONFIG_MSM_ETM
123 bl etm_restore_reg_check
124#endif
125#ifdef CONFIG_MSM_JTAG_V7
126 bl msm_restore_jtag_debug
127#endif
128 ldr r0, =saved_state /* restore registers */
129#if (NR_CPUS >= 2)
130 mrc p15, 0, r1, c0, c0, 5 /* MPIDR */
131 ands r1, r1, #15 /* What CPU am I */
132 addne r0, r0, #CPU_SAVED_STATE_SIZE
133#endif
134
135 ldmfd r0, {r4-r14}
136 mov r0, #0 /* return power collapse failed */
137 bx lr
138
139ENTRY(msm_pm_collapse_exit)
140#if 0 /* serial debug */
141 mov r0, #0x80000016
142 mcr p15, 0, r0, c15, c2, 4
143 mov r0, #0xA9000000
144 add r0, r0, #0x00A00000 /* UART1 */
145 /*add r0, r0, #0x00C00000*/ /* UART3 */
146 mov r1, #'A'
147 str r1, [r0, #0x00C]
148#endif
149 ldr r1, =saved_state_end
150 ldr r2, =msm_pm_collapse_exit
151 adr r3, msm_pm_collapse_exit
152 add r1, r1, r3
153 sub r1, r1, r2
154#if (NR_CPUS >= 2)
155 mrc p15, 0, r2, c0, c0, 5 /* MPIDR */
156 ands r2, r2, #15 /* What CPU am I */
157 subeq r1, r1, #CPU_SAVED_STATE_SIZE
158#endif
159
160#ifdef CONFIG_MSM_CPU_AVS
161 ldmdb r1!, {r2-r4}
162#ifndef CONFIG_ARCH_MSM_KRAIT
163 mcr p15, 7, r4, c15, c1, 0 /* TSCSR */
164#endif
165 mcr p15, 7, r3, c15, c0, 6 /* AVSDSCR */
166 mcr p15, 7, r2, c15, c1, 7 /* AVSCSR */
167#endif
168 ldmdb r1!, {r2-r11}
169 mcr p15, 0, r4, c3, c0, 0 /* dacr */
170 mcr p15, 0, r3, c2, c0, 0 /* TTBR0 */
171#ifdef CONFIG_ARCH_MSM_SCORPION
172 /* This instruction is not valid for non scorpion processors */
173 mcr p15, 3, r5, c15, c0, 3 /* L2CR1 */
174#endif
175 mcr p15, 0, r6, c10, c2, 0 /* PRRR */
176 mcr p15, 0, r7, c10, c2, 1 /* NMRR */
177 mcr p15, 0, r8, c1, c0, 1 /* ACTLR */
178 mcr p15, 0, r9, c2, c0, 1 /* TTBR1 */
179 mcr p15, 0, r10, c13, c0, 3 /* TPIDRURO */
180 mcr p15, 0, r11, c13, c0, 1 /* context ID */
181 isb
182 ldmdb r1!, {r4-r14}
183 ldr r0, =msm_pm_pc_pgd
184 ldr r1, =msm_pm_collapse_exit
185 adr r3, msm_pm_collapse_exit
186 add r0, r0, r3
187 sub r0, r0, r1
188 ldr r0, [r0]
189 mrc p15, 0, r1, c2, c0, 0 /* save current TTBR0 */
190 and r3, r1, #0x7f /* mask to get TTB flags */
191 orr r0, r0, r3 /* add TTB flags to switch TTBR value */
192 mcr p15, 0, r0, c2, c0, 0 /* temporary switch TTBR0 */
193 isb
194 mcr p15, 0, r2, c1, c0, 0 /* MMU control */
195 isb
196msm_pm_mapped_pa:
197 /* Switch to virtual */
198 ldr r0, =msm_pm_pa_to_va
199 mov pc, r0
200msm_pm_pa_to_va:
201 mcr p15, 0, r1, c2, c0, 0 /* restore TTBR0 */
202 isb
203 mcr p15, 0, r3, c8, c7, 0 /* UTLBIALL */
204 mcr p15, 0, r3, c7, c5, 6 /* BPIALL */
205 dsb
206
207 isb
208 stmfd sp!, {lr}
209 bl v7_flush_kern_cache_all
210#ifdef CONFIG_MSM_ETM
211 bl etm_restore_reg_check
212#endif
213#ifdef CONFIG_MSM_JTAG_V7
214 bl msm_restore_jtag_debug
215#endif
216 ldmfd sp!, {lr}
217 mov r0, #1
218 bx lr
219 nop
220 nop
221 nop
222 nop
223 nop
2241: b 1b
225
226ENTRY(msm_pm_boot_entry)
227 mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
228 and r0, r0, #15 /* what CPU am I */
229
230 ldr r1, =msm_pm_boot_vector
231 ldr r2, =msm_pm_boot_entry
232 adr r3, msm_pm_boot_entry
233 add r1, r1, r3 /* translate virt to phys addr */
234 sub r1, r1, r2
235
236 add r1, r1, r0, LSL #2 /* locate boot vector for our cpu */
237 ldr pc, [r1] /* jump */
238
239ENTRY(msm_pm_write_boot_vector)
240 ldr r2, =msm_pm_boot_vector
241 add r2, r2, r0, LSL #2 /* locate boot vector for our cpu */
242 str r1, [r2]
243 bx lr
244
245 .data
246
247 .globl msm_pm_pc_pgd
248msm_pm_pc_pgd:
249 .long 0x0
250
251saved_state:
252#if (NR_CPUS >= 2)
253 .space CPU_SAVED_STATE_SIZE * 2 /* This code only supports 2 cores */
254#else
255 .space CPU_SAVED_STATE_SIZE
256#endif
257saved_state_end:
258
259msm_pm_boot_vector:
260 .space 4 * NR_CPUS