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