diff options
Diffstat (limited to 'arch/arm/mach-tegra/sleep-tegra30.S')
-rw-r--r-- | arch/arm/mach-tegra/sleep-tegra30.S | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S new file mode 100644 index 000000000000..562a8e7e413d --- /dev/null +++ b/arch/arm/mach-tegra/sleep-tegra30.S | |||
@@ -0,0 +1,171 @@ | |||
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 | |||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/asm-offsets.h> | ||
21 | |||
22 | #include "sleep.h" | ||
23 | #include "flowctrl.h" | ||
24 | |||
25 | #define TEGRA30_POWER_HOTPLUG_SHUTDOWN (1 << 27) /* Hotplug shutdown */ | ||
26 | |||
27 | #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) | ||
28 | /* | ||
29 | * tegra30_hotplug_shutdown(void) | ||
30 | * | ||
31 | * Powergates the current CPU. | ||
32 | * Should never return. | ||
33 | */ | ||
34 | ENTRY(tegra30_hotplug_shutdown) | ||
35 | /* Turn off SMP coherency */ | ||
36 | exit_smp r4, r5 | ||
37 | |||
38 | /* Powergate this CPU */ | ||
39 | mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN | ||
40 | bl tegra30_cpu_shutdown | ||
41 | mov pc, lr @ should never get here | ||
42 | ENDPROC(tegra30_hotplug_shutdown) | ||
43 | |||
44 | /* | ||
45 | * tegra30_cpu_shutdown(unsigned long flags) | ||
46 | * | ||
47 | * Puts the current CPU in wait-for-event mode on the flow controller | ||
48 | * and powergates it -- flags (in R0) indicate the request type. | ||
49 | * Must never be called for CPU 0. | ||
50 | * | ||
51 | * corrupts r0-r4, r12 | ||
52 | */ | ||
53 | ENTRY(tegra30_cpu_shutdown) | ||
54 | cpu_id r3 | ||
55 | cmp r3, #0 | ||
56 | moveq pc, lr @ Must never be called for CPU 0 | ||
57 | |||
58 | ldr r12, =TEGRA_FLOW_CTRL_VIRT | ||
59 | cpu_to_csr_reg r1, r3 | ||
60 | add r1, r1, r12 @ virtual CSR address for this CPU | ||
61 | cpu_to_halt_reg r2, r3 | ||
62 | add r2, r2, r12 @ virtual HALT_EVENTS address for this CPU | ||
63 | |||
64 | /* | ||
65 | * Clear this CPU's "event" and "interrupt" flags and power gate | ||
66 | * it when halting but not before it is in the "WFE" state. | ||
67 | */ | ||
68 | movw r12, \ | ||
69 | FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \ | ||
70 | FLOW_CTRL_CSR_ENABLE | ||
71 | mov r4, #(1 << 4) | ||
72 | orr r12, r12, r4, lsl r3 | ||
73 | str r12, [r1] | ||
74 | |||
75 | /* Halt this CPU. */ | ||
76 | mov r3, #0x400 | ||
77 | delay_1: | ||
78 | subs r3, r3, #1 @ delay as a part of wfe war. | ||
79 | bge delay_1; | ||
80 | cpsid a @ disable imprecise aborts. | ||
81 | ldr r3, [r1] @ read CSR | ||
82 | str r3, [r1] @ clear CSR | ||
83 | tst r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN | ||
84 | moveq r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT @ For LP2 | ||
85 | movne r3, #FLOW_CTRL_WAITEVENT @ For hotplug | ||
86 | str r3, [r2] | ||
87 | ldr r0, [r2] | ||
88 | b wfe_war | ||
89 | |||
90 | __cpu_reset_again: | ||
91 | dsb | ||
92 | .align 5 | ||
93 | wfe @ CPU should be power gated here | ||
94 | wfe_war: | ||
95 | b __cpu_reset_again | ||
96 | |||
97 | /* | ||
98 | * 38 nop's, which fills reset of wfe cache line and | ||
99 | * 4 more cachelines with nop | ||
100 | */ | ||
101 | .rept 38 | ||
102 | nop | ||
103 | .endr | ||
104 | b . @ should never get here | ||
105 | |||
106 | ENDPROC(tegra30_cpu_shutdown) | ||
107 | #endif | ||
108 | |||
109 | #ifdef CONFIG_PM_SLEEP | ||
110 | /* | ||
111 | * tegra30_sleep_cpu_secondary_finish(unsigned long v2p) | ||
112 | * | ||
113 | * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU. | ||
114 | */ | ||
115 | ENTRY(tegra30_sleep_cpu_secondary_finish) | ||
116 | mov r7, lr | ||
117 | |||
118 | /* Flush and disable the L1 data cache */ | ||
119 | bl tegra_disable_clean_inv_dcache | ||
120 | |||
121 | /* Powergate this CPU. */ | ||
122 | mov r0, #0 @ power mode flags (!hotplug) | ||
123 | bl tegra30_cpu_shutdown | ||
124 | mov r0, #1 @ never return here | ||
125 | mov pc, r7 | ||
126 | ENDPROC(tegra30_sleep_cpu_secondary_finish) | ||
127 | |||
128 | /* | ||
129 | * tegra30_tear_down_cpu | ||
130 | * | ||
131 | * Switches the CPU to enter sleep. | ||
132 | */ | ||
133 | ENTRY(tegra30_tear_down_cpu) | ||
134 | mov32 r6, TEGRA_FLOW_CTRL_BASE | ||
135 | |||
136 | b tegra30_enter_sleep | ||
137 | ENDPROC(tegra30_tear_down_cpu) | ||
138 | |||
139 | /* | ||
140 | * tegra30_enter_sleep | ||
141 | * | ||
142 | * uses flow controller to enter sleep state | ||
143 | * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 | ||
144 | * executes from SDRAM with target state is LP2 | ||
145 | * r6 = TEGRA_FLOW_CTRL_BASE | ||
146 | */ | ||
147 | tegra30_enter_sleep: | ||
148 | cpu_id r1 | ||
149 | |||
150 | cpu_to_csr_reg r2, r1 | ||
151 | ldr r0, [r6, r2] | ||
152 | orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | ||
153 | orr r0, r0, #FLOW_CTRL_CSR_ENABLE | ||
154 | str r0, [r6, r2] | ||
155 | |||
156 | mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT | ||
157 | orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ | ||
158 | cpu_to_halt_reg r2, r1 | ||
159 | str r0, [r6, r2] | ||
160 | dsb | ||
161 | ldr r0, [r6, r2] /* memory barrier */ | ||
162 | |||
163 | halted: | ||
164 | isb | ||
165 | dsb | ||
166 | wfi /* CPU should be power gated here */ | ||
167 | |||
168 | /* !!!FIXME!!! Implement halt failure handler */ | ||
169 | b halted | ||
170 | |||
171 | #endif | ||