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