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