Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[deliverable/linux.git] / arch / arm / mach-tegra / sleep-tegra20.S
1 /*
2 * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
3 * Copyright (c) 2011, Google, Inc.
4 *
5 * Author: Colin Cross <ccross@android.com>
6 * Gary King <gking@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <linux/linkage.h>
22
23 #include <asm/assembler.h>
24 #include <asm/proc-fns.h>
25 #include <asm/cp15.h>
26 #include <asm/cache.h>
27
28 #include "irammap.h"
29 #include "sleep.h"
30 #include "flowctrl.h"
31
32 #define EMC_CFG 0xc
33 #define EMC_ADR_CFG 0x10
34 #define EMC_REFRESH 0x70
35 #define EMC_NOP 0xdc
36 #define EMC_SELF_REF 0xe0
37 #define EMC_REQ_CTRL 0x2b0
38 #define EMC_EMC_STATUS 0x2b4
39
40 #define CLK_RESET_CCLK_BURST 0x20
41 #define CLK_RESET_CCLK_DIVIDER 0x24
42 #define CLK_RESET_SCLK_BURST 0x28
43 #define CLK_RESET_SCLK_DIVIDER 0x2c
44 #define CLK_RESET_PLLC_BASE 0x80
45 #define CLK_RESET_PLLM_BASE 0x90
46 #define CLK_RESET_PLLP_BASE 0xa0
47
48 #define APB_MISC_XM2CFGCPADCTRL 0x8c8
49 #define APB_MISC_XM2CFGDPADCTRL 0x8cc
50 #define APB_MISC_XM2CLKCFGPADCTRL 0x8d0
51 #define APB_MISC_XM2COMPPADCTRL 0x8d4
52 #define APB_MISC_XM2VTTGENPADCTRL 0x8d8
53 #define APB_MISC_XM2CFGCPADCTRL2 0x8e4
54 #define APB_MISC_XM2CFGDPADCTRL2 0x8e8
55
56 .macro pll_enable, rd, r_car_base, pll_base
57 ldr \rd, [\r_car_base, #\pll_base]
58 tst \rd, #(1 << 30)
59 orreq \rd, \rd, #(1 << 30)
60 streq \rd, [\r_car_base, #\pll_base]
61 .endm
62
63 .macro emc_device_mask, rd, base
64 ldr \rd, [\base, #EMC_ADR_CFG]
65 tst \rd, #(0x3 << 24)
66 moveq \rd, #(0x1 << 8) @ just 1 device
67 movne \rd, #(0x3 << 8) @ 2 devices
68 .endm
69
70 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
71 /*
72 * tegra20_hotplug_shutdown(void)
73 *
74 * puts the current cpu in reset
75 * should never return
76 */
77 ENTRY(tegra20_hotplug_shutdown)
78 /* Put this CPU down */
79 cpu_id r0
80 bl tegra20_cpu_shutdown
81 mov pc, lr @ should never get here
82 ENDPROC(tegra20_hotplug_shutdown)
83
84 /*
85 * tegra20_cpu_shutdown(int cpu)
86 *
87 * r0 is cpu to reset
88 *
89 * puts the specified CPU in wait-for-event mode on the flow controller
90 * and puts the CPU in reset
91 * can be called on the current cpu or another cpu
92 * if called on the current cpu, does not return
93 * MUST NOT BE CALLED FOR CPU 0.
94 *
95 * corrupts r0-r3, r12
96 */
97 ENTRY(tegra20_cpu_shutdown)
98 cmp r0, #0
99 moveq pc, lr @ must not be called for CPU 0
100 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
101 mov r12, #CPU_RESETTABLE
102 str r12, [r1]
103
104 cpu_to_halt_reg r1, r0
105 ldr r3, =TEGRA_FLOW_CTRL_VIRT
106 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
107 str r2, [r3, r1] @ put flow controller in wait event mode
108 ldr r2, [r3, r1]
109 isb
110 dsb
111 movw r1, 0x1011
112 mov r1, r1, lsl r0
113 ldr r3, =TEGRA_CLK_RESET_VIRT
114 str r1, [r3, #0x340] @ put slave CPU in reset
115 isb
116 dsb
117 cpu_id r3
118 cmp r3, r0
119 beq .
120 mov pc, lr
121 ENDPROC(tegra20_cpu_shutdown)
122 #endif
123
124 #ifdef CONFIG_PM_SLEEP
125 /*
126 * tegra_pen_lock
127 *
128 * spinlock implementation with no atomic test-and-set and no coherence
129 * using Peterson's algorithm on strongly-ordered registers
130 * used to synchronize a cpu waking up from wfi with entering lp2 on idle
131 *
132 * The reference link of Peterson's algorithm:
133 * http://en.wikipedia.org/wiki/Peterson's_algorithm
134 *
135 * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
136 * on cpu 0:
137 * r2 = flag[0] (in SCRATCH38)
138 * r3 = flag[1] (in SCRATCH39)
139 * on cpu1:
140 * r2 = flag[1] (in SCRATCH39)
141 * r3 = flag[0] (in SCRATCH38)
142 *
143 * must be called with MMU on
144 * corrupts r0-r3, r12
145 */
146 ENTRY(tegra_pen_lock)
147 mov32 r3, TEGRA_PMC_VIRT
148 cpu_id r0
149 add r1, r3, #PMC_SCRATCH37
150 cmp r0, #0
151 addeq r2, r3, #PMC_SCRATCH38
152 addeq r3, r3, #PMC_SCRATCH39
153 addne r2, r3, #PMC_SCRATCH39
154 addne r3, r3, #PMC_SCRATCH38
155
156 mov r12, #1
157 str r12, [r2] @ flag[cpu] = 1
158 dsb
159 str r12, [r1] @ !turn = cpu
160 1: dsb
161 ldr r12, [r3]
162 cmp r12, #1 @ flag[!cpu] == 1?
163 ldreq r12, [r1]
164 cmpeq r12, r0 @ !turn == cpu?
165 beq 1b @ while !turn == cpu && flag[!cpu] == 1
166
167 mov pc, lr @ locked
168 ENDPROC(tegra_pen_lock)
169
170 ENTRY(tegra_pen_unlock)
171 dsb
172 mov32 r3, TEGRA_PMC_VIRT
173 cpu_id r0
174 cmp r0, #0
175 addeq r2, r3, #PMC_SCRATCH38
176 addne r2, r3, #PMC_SCRATCH39
177 mov r12, #0
178 str r12, [r2]
179 mov pc, lr
180 ENDPROC(tegra_pen_unlock)
181
182 /*
183 * tegra20_cpu_clear_resettable(void)
184 *
185 * Called to clear the "resettable soon" flag in PMC_SCRATCH41 when
186 * it is expected that the secondary CPU will be idle soon.
187 */
188 ENTRY(tegra20_cpu_clear_resettable)
189 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
190 mov r12, #CPU_NOT_RESETTABLE
191 str r12, [r1]
192 mov pc, lr
193 ENDPROC(tegra20_cpu_clear_resettable)
194
195 /*
196 * tegra20_cpu_set_resettable_soon(void)
197 *
198 * Called to set the "resettable soon" flag in PMC_SCRATCH41 when
199 * it is expected that the secondary CPU will be idle soon.
200 */
201 ENTRY(tegra20_cpu_set_resettable_soon)
202 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
203 mov r12, #CPU_RESETTABLE_SOON
204 str r12, [r1]
205 mov pc, lr
206 ENDPROC(tegra20_cpu_set_resettable_soon)
207
208 /*
209 * tegra20_cpu_is_resettable_soon(void)
210 *
211 * Returns true if the "resettable soon" flag in PMC_SCRATCH41 has been
212 * set because it is expected that the secondary CPU will be idle soon.
213 */
214 ENTRY(tegra20_cpu_is_resettable_soon)
215 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
216 ldr r12, [r1]
217 cmp r12, #CPU_RESETTABLE_SOON
218 moveq r0, #1
219 movne r0, #0
220 mov pc, lr
221 ENDPROC(tegra20_cpu_is_resettable_soon)
222
223 /*
224 * tegra20_sleep_core_finish(unsigned long v2p)
225 *
226 * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
227 * tegra20_tear_down_core in IRAM
228 */
229 ENTRY(tegra20_sleep_core_finish)
230 /* Flush, disable the L1 data cache and exit SMP */
231 bl tegra_disable_clean_inv_dcache
232
233 mov32 r3, tegra_shut_off_mmu
234 add r3, r3, r0
235
236 mov32 r0, tegra20_tear_down_core
237 mov32 r1, tegra20_iram_start
238 sub r0, r0, r1
239 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
240 add r0, r0, r1
241
242 mov pc, r3
243 ENDPROC(tegra20_sleep_core_finish)
244
245 /*
246 * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
247 *
248 * Enters WFI on secondary CPU by exiting coherency.
249 */
250 ENTRY(tegra20_sleep_cpu_secondary_finish)
251 stmfd sp!, {r4-r11, lr}
252
253 mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency
254
255 /* Flush and disable the L1 data cache */
256 mov r0, #TEGRA_FLUSH_CACHE_LOUIS
257 bl tegra_disable_clean_inv_dcache
258
259 mov32 r0, TEGRA_PMC_VIRT + PMC_SCRATCH41
260 mov r3, #CPU_RESETTABLE
261 str r3, [r0]
262
263 bl tegra_cpu_do_idle
264
265 /*
266 * cpu may be reset while in wfi, which will return through
267 * tegra_resume to cpu_resume
268 * or interrupt may wake wfi, which will return here
269 * cpu state is unchanged - MMU is on, cache is on, coherency
270 * is off, and the data cache is off
271 *
272 * r11 contains the original actlr
273 */
274
275 bl tegra_pen_lock
276
277 mov32 r3, TEGRA_PMC_VIRT
278 add r0, r3, #PMC_SCRATCH41
279 mov r3, #CPU_NOT_RESETTABLE
280 str r3, [r0]
281
282 bl tegra_pen_unlock
283
284 /* Re-enable the data cache */
285 mrc p15, 0, r10, c1, c0, 0
286 orr r10, r10, #CR_C
287 mcr p15, 0, r10, c1, c0, 0
288 isb
289
290 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
291
292 /* Invalidate the TLBs & BTAC */
293 mov r1, #0
294 mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs
295 mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC
296 dsb
297 isb
298
299 /* the cpu was running with coherency disabled,
300 * caches may be out of date */
301 bl v7_flush_kern_cache_louis
302
303 ldmfd sp!, {r4 - r11, pc}
304 ENDPROC(tegra20_sleep_cpu_secondary_finish)
305
306 /*
307 * tegra20_tear_down_cpu
308 *
309 * Switches the CPU cluster to PLL-P and enters sleep.
310 */
311 ENTRY(tegra20_tear_down_cpu)
312 bl tegra_switch_cpu_to_pllp
313 b tegra20_enter_sleep
314 ENDPROC(tegra20_tear_down_cpu)
315
316 /* START OF ROUTINES COPIED TO IRAM */
317 .align L1_CACHE_SHIFT
318 .globl tegra20_iram_start
319 tegra20_iram_start:
320
321 /*
322 * tegra20_lp1_reset
323 *
324 * reset vector for LP1 restore; copied into IRAM during suspend.
325 * Brings the system back up to a safe staring point (SDRAM out of
326 * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
327 * system clock running on the same PLL that it suspended at), and
328 * jumps to tegra_resume to restore virtual addressing and PLLX.
329 * The physical address of tegra_resume expected to be stored in
330 * PMC_SCRATCH41.
331 *
332 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
333 */
334 ENTRY(tegra20_lp1_reset)
335 /*
336 * The CPU and system bus are running at 32KHz and executing from
337 * IRAM when this code is executed; immediately switch to CLKM and
338 * enable PLLM, PLLP, PLLC.
339 */
340 mov32 r0, TEGRA_CLK_RESET_BASE
341
342 mov r1, #(1 << 28)
343 str r1, [r0, #CLK_RESET_SCLK_BURST]
344 str r1, [r0, #CLK_RESET_CCLK_BURST]
345 mov r1, #0
346 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
347 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
348
349 pll_enable r1, r0, CLK_RESET_PLLM_BASE
350 pll_enable r1, r0, CLK_RESET_PLLP_BASE
351 pll_enable r1, r0, CLK_RESET_PLLC_BASE
352
353 adr r2, tegra20_sdram_pad_address
354 adr r4, tegra20_sdram_pad_save
355 mov r5, #0
356
357 ldr r6, tegra20_sdram_pad_size
358 padload:
359 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
360
361 ldr r1, [r4, r5]
362 str r1, [r7] @ restore the value in pad_save
363
364 add r5, r5, #4
365 cmp r6, r5
366 bne padload
367
368 padload_done:
369 /* 255uS delay for PLL stabilization */
370 mov32 r7, TEGRA_TMRUS_BASE
371 ldr r1, [r7]
372 add r1, r1, #0xff
373 wait_until r1, r7, r9
374
375 adr r4, tegra20_sclk_save
376 ldr r4, [r4]
377 str r4, [r0, #CLK_RESET_SCLK_BURST]
378 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
379 str r4, [r0, #CLK_RESET_CCLK_BURST]
380
381 mov32 r0, TEGRA_EMC_BASE
382 ldr r1, [r0, #EMC_CFG]
383 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
384 str r1, [r0, #EMC_CFG]
385
386 mov r1, #0
387 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
388 mov r1, #1
389 str r1, [r0, #EMC_NOP]
390 str r1, [r0, #EMC_NOP]
391 str r1, [r0, #EMC_REFRESH]
392
393 emc_device_mask r1, r0
394
395 exit_selfrefresh_loop:
396 ldr r2, [r0, #EMC_EMC_STATUS]
397 ands r2, r2, r1
398 bne exit_selfrefresh_loop
399
400 mov r1, #0 @ unstall all transactions
401 str r1, [r0, #EMC_REQ_CTRL]
402
403 mov32 r0, TEGRA_PMC_BASE
404 ldr r0, [r0, #PMC_SCRATCH41]
405 mov pc, r0 @ jump to tegra_resume
406 ENDPROC(tegra20_lp1_reset)
407
408 /*
409 * tegra20_tear_down_core
410 *
411 * copied into and executed from IRAM
412 * puts memory in self-refresh for LP0 and LP1
413 */
414 tegra20_tear_down_core:
415 bl tegra20_sdram_self_refresh
416 bl tegra20_switch_cpu_to_clk32k
417 b tegra20_enter_sleep
418
419 /*
420 * tegra20_switch_cpu_to_clk32k
421 *
422 * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
423 * to the 32KHz clock.
424 */
425 tegra20_switch_cpu_to_clk32k:
426 /*
427 * start by switching to CLKM to safely disable PLLs, then switch to
428 * CLKS.
429 */
430 mov r0, #(1 << 28)
431 str r0, [r5, #CLK_RESET_SCLK_BURST]
432 str r0, [r5, #CLK_RESET_CCLK_BURST]
433 mov r0, #0
434 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
435 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
436
437 /* 2uS delay delay between changing SCLK and disabling PLLs */
438 mov32 r7, TEGRA_TMRUS_BASE
439 ldr r1, [r7]
440 add r1, r1, #2
441 wait_until r1, r7, r9
442
443 /* disable PLLM, PLLP and PLLC */
444 ldr r0, [r5, #CLK_RESET_PLLM_BASE]
445 bic r0, r0, #(1 << 30)
446 str r0, [r5, #CLK_RESET_PLLM_BASE]
447 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
448 bic r0, r0, #(1 << 30)
449 str r0, [r5, #CLK_RESET_PLLP_BASE]
450 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
451 bic r0, r0, #(1 << 30)
452 str r0, [r5, #CLK_RESET_PLLC_BASE]
453
454 /* switch to CLKS */
455 mov r0, #0 /* brust policy = 32KHz */
456 str r0, [r5, #CLK_RESET_SCLK_BURST]
457
458 mov pc, lr
459
460 /*
461 * tegra20_enter_sleep
462 *
463 * uses flow controller to enter sleep state
464 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
465 * executes from SDRAM with target state is LP2
466 */
467 tegra20_enter_sleep:
468 mov32 r6, TEGRA_FLOW_CTRL_BASE
469
470 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
471 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
472 cpu_id r1
473 cpu_to_halt_reg r1, r1
474 str r0, [r6, r1]
475 dsb
476 ldr r0, [r6, r1] /* memory barrier */
477
478 halted:
479 dsb
480 wfe /* CPU should be power gated here */
481 isb
482 b halted
483
484 /*
485 * tegra20_sdram_self_refresh
486 *
487 * called with MMU off and caches disabled
488 * puts sdram in self refresh
489 * must be executed from IRAM
490 */
491 tegra20_sdram_self_refresh:
492 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
493
494 mov r2, #3
495 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
496
497 emcidle:
498 ldr r2, [r1, #EMC_EMC_STATUS]
499 tst r2, #4
500 beq emcidle
501
502 mov r2, #1
503 str r2, [r1, #EMC_SELF_REF]
504
505 emc_device_mask r2, r1
506
507 emcself:
508 ldr r3, [r1, #EMC_EMC_STATUS]
509 and r3, r3, r2
510 cmp r3, r2
511 bne emcself @ loop until DDR in self-refresh
512
513 adr r2, tegra20_sdram_pad_address
514 adr r3, tegra20_sdram_pad_safe
515 adr r4, tegra20_sdram_pad_save
516 mov r5, #0
517
518 ldr r6, tegra20_sdram_pad_size
519 padsave:
520 ldr r0, [r2, r5] @ r0 is the addr in the pad_address
521
522 ldr r1, [r0]
523 str r1, [r4, r5] @ save the content of the addr
524
525 ldr r1, [r3, r5]
526 str r1, [r0] @ set the save val to the addr
527
528 add r5, r5, #4
529 cmp r6, r5
530 bne padsave
531 padsave_done:
532
533 mov32 r5, TEGRA_CLK_RESET_BASE
534 ldr r0, [r5, #CLK_RESET_SCLK_BURST]
535 adr r2, tegra20_sclk_save
536 str r0, [r2]
537 dsb
538 mov pc, lr
539
540 tegra20_sdram_pad_address:
541 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
542 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
543 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
544 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
545 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
546 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
547 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
548
549 tegra20_sdram_pad_size:
550 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
551
552 tegra20_sdram_pad_safe:
553 .word 0x8
554 .word 0x8
555 .word 0x0
556 .word 0x8
557 .word 0x5500
558 .word 0x08080040
559 .word 0x0
560
561 tegra20_sclk_save:
562 .word 0x0
563
564 tegra20_sdram_pad_save:
565 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
566 .long 0
567 .endr
568
569 .ltorg
570 /* dummy symbol for end of IRAM */
571 .align L1_CACHE_SHIFT
572 .globl tegra20_iram_end
573 tegra20_iram_end:
574 b .
575 #endif
This page took 0.063069 seconds and 5 git commands to generate.