blob: 5c8e638ee51a3b590cc8274a3edb22e5a93dd996 [file] [log] [blame]
Joseph Lo453689e2012-08-16 17:31:52 +08001/*
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
Jon Hunter7e10cf72017-03-28 13:42:54 +010023#include <soc/tegra/flowctrl.h>
24
Joseph Lo453689e2012-08-16 17:31:52 +080025#include <asm/assembler.h>
Joseph Lo5c1350b2013-01-15 22:10:38 +000026#include <asm/proc-fns.h>
27#include <asm/cp15.h>
Joseph Lo731a9272013-08-12 17:40:05 +080028#include <asm/cache.h>
Joseph Lo453689e2012-08-16 17:31:52 +080029
Stephen Warrenfddb7702013-08-20 16:19:15 -060030#include "irammap.h"
Joseph Lo453689e2012-08-16 17:31:52 +080031#include "sleep.h"
Joseph Lo453689e2012-08-16 17:31:52 +080032
Joseph Lo731a9272013-08-12 17:40:05 +080033#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
Joseph Lo453689e2012-08-16 17:31:52 +080071#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 */
78ENTRY(tegra20_hotplug_shutdown)
Joseph Lo453689e2012-08-16 17:31:52 +080079 /* Put this CPU down */
80 cpu_id r0
81 bl tegra20_cpu_shutdown
Russell King6ebbf2c2014-06-30 16:29:12 +010082 ret lr @ should never get here
Joseph Lo453689e2012-08-16 17:31:52 +080083ENDPROC(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 */
98ENTRY(tegra20_cpu_shutdown)
99 cmp r0, #0
Russell King6ebbf2c2014-06-30 16:29:12 +0100100 reteq lr @ must not be called for CPU 0
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300101 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
102 ldr r2, =__tegra20_cpu1_resettable_status_offset
Joseph Lo1d328602013-01-16 17:33:55 +0000103 mov r12, #CPU_RESETTABLE
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300104 strb r12, [r1, r2]
Joseph Lo453689e2012-08-16 17:31:52 +0800105
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 .
Russell King6ebbf2c2014-06-30 16:29:12 +0100122 ret lr
Joseph Lo453689e2012-08-16 17:31:52 +0800123ENDPROC(tegra20_cpu_shutdown)
124#endif
Joseph Lo5c1350b2013-01-15 22:10:38 +0000125
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 */
148ENTRY(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
1621: 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
Russell King6ebbf2c2014-06-30 16:29:12 +0100169 ret lr @ locked
Joseph Lo5c1350b2013-01-15 22:10:38 +0000170ENDPROC(tegra_pen_lock)
171
172ENTRY(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]
Russell King6ebbf2c2014-06-30 16:29:12 +0100181 ret lr
Joseph Lo5c1350b2013-01-15 22:10:38 +0000182ENDPROC(tegra_pen_unlock)
183
184/*
185 * tegra20_cpu_clear_resettable(void)
186 *
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300187 * Called to clear the "resettable soon" flag in IRAM variable when
Joseph Lo5c1350b2013-01-15 22:10:38 +0000188 * it is expected that the secondary CPU will be idle soon.
189 */
190ENTRY(tegra20_cpu_clear_resettable)
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300191 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
192 ldr r2, =__tegra20_cpu1_resettable_status_offset
Joseph Lo5c1350b2013-01-15 22:10:38 +0000193 mov r12, #CPU_NOT_RESETTABLE
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300194 strb r12, [r1, r2]
Russell King6ebbf2c2014-06-30 16:29:12 +0100195 ret lr
Joseph Lo5c1350b2013-01-15 22:10:38 +0000196ENDPROC(tegra20_cpu_clear_resettable)
197
198/*
199 * tegra20_cpu_set_resettable_soon(void)
200 *
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300201 * Called to set the "resettable soon" flag in IRAM variable when
Joseph Lo5c1350b2013-01-15 22:10:38 +0000202 * it is expected that the secondary CPU will be idle soon.
203 */
204ENTRY(tegra20_cpu_set_resettable_soon)
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300205 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
206 ldr r2, =__tegra20_cpu1_resettable_status_offset
Joseph Lo5c1350b2013-01-15 22:10:38 +0000207 mov r12, #CPU_RESETTABLE_SOON
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300208 strb r12, [r1, r2]
Russell King6ebbf2c2014-06-30 16:29:12 +0100209 ret lr
Joseph Lo5c1350b2013-01-15 22:10:38 +0000210ENDPROC(tegra20_cpu_set_resettable_soon)
211
212/*
Joseph Lo1d328602013-01-16 17:33:55 +0000213 * tegra20_cpu_is_resettable_soon(void)
214 *
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300215 * Returns true if the "resettable soon" flag in IRAM variable has been
Joseph Lo1d328602013-01-16 17:33:55 +0000216 * set because it is expected that the secondary CPU will be idle soon.
217 */
218ENTRY(tegra20_cpu_is_resettable_soon)
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300219 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
220 ldr r2, =__tegra20_cpu1_resettable_status_offset
221 ldrb r12, [r1, r2]
Joseph Lo1d328602013-01-16 17:33:55 +0000222 cmp r12, #CPU_RESETTABLE_SOON
223 moveq r0, #1
224 movne r0, #0
Russell King6ebbf2c2014-06-30 16:29:12 +0100225 ret lr
Joseph Lo1d328602013-01-16 17:33:55 +0000226ENDPROC(tegra20_cpu_is_resettable_soon)
227
228/*
Joseph Lo731a9272013-08-12 17:40:05 +0800229 * 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 */
234ENTRY(tegra20_sleep_core_finish)
Jon Hunter5883ac22015-11-19 14:19:47 +0000235 mov r4, r0
Joseph Lo731a9272013-08-12 17:40:05 +0800236 /* Flush, disable the L1 data cache and exit SMP */
Jon Hunter5883ac22015-11-19 14:19:47 +0000237 mov r0, #TEGRA_FLUSH_CACHE_ALL
Joseph Lo731a9272013-08-12 17:40:05 +0800238 bl tegra_disable_clean_inv_dcache
Jon Hunter5883ac22015-11-19 14:19:47 +0000239 mov r0, r4
Joseph Lo731a9272013-08-12 17:40:05 +0800240
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
Stephen Warrenfddb7702013-08-20 16:19:15 -0600247 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
Joseph Lo731a9272013-08-12 17:40:05 +0800248 add r0, r0, r1
249
Russell King6ebbf2c2014-06-30 16:29:12 +0100250 ret r3
Joseph Lo731a9272013-08-12 17:40:05 +0800251ENDPROC(tegra20_sleep_core_finish)
252
253/*
Joseph Lo5c1350b2013-01-15 22:10:38 +0000254 * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
255 *
256 * Enters WFI on secondary CPU by exiting coherency.
257 */
258ENTRY(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 */
Joseph Loac2527b2013-07-03 17:50:38 +0800264 mov r0, #TEGRA_FLUSH_CACHE_LOUIS
Joseph Lo5c1350b2013-01-15 22:10:38 +0000265 bl tegra_disable_clean_inv_dcache
266
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300267 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
268 ldr r4, =__tegra20_cpu1_resettable_status_offset
Joseph Lo5c1350b2013-01-15 22:10:38 +0000269 mov r3, #CPU_RESETTABLE
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300270 strb r3, [r0, r4]
Joseph Lo5c1350b2013-01-15 22:10:38 +0000271
Arnd Bergmann20588422013-04-23 15:36:26 +0200272 bl tegra_cpu_do_idle
Joseph Lo5c1350b2013-01-15 22:10:38 +0000273
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
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300286 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
287 ldr r4, =__tegra20_cpu1_resettable_status_offset
Joseph Lo5c1350b2013-01-15 22:10:38 +0000288 mov r3, #CPU_NOT_RESETTABLE
Dmitry Osipenko4d48edb2015-01-15 13:58:57 +0300289 strb r3, [r0, r4]
Joseph Lo5c1350b2013-01-15 22:10:38 +0000290
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}
313ENDPROC(tegra20_sleep_cpu_secondary_finish)
Joseph Lo1d328602013-01-16 17:33:55 +0000314
315/*
316 * tegra20_tear_down_cpu
317 *
318 * Switches the CPU cluster to PLL-P and enters sleep.
319 */
320ENTRY(tegra20_tear_down_cpu)
321 bl tegra_switch_cpu_to_pllp
322 b tegra20_enter_sleep
323ENDPROC(tegra20_tear_down_cpu)
324
Joseph Lo731a9272013-08-12 17:40:05 +0800325/* START OF ROUTINES COPIED TO IRAM */
326 .align L1_CACHE_SHIFT
327 .globl tegra20_iram_start
328tegra20_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 *
Stephen Warrenfddb7702013-08-20 16:19:15 -0600341 * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
Joseph Lo731a9272013-08-12 17:40:05 +0800342 */
343ENTRY(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
367padload:
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
377padload_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
404exit_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]
Russell King6ebbf2c2014-06-30 16:29:12 +0100414 ret r0 @ jump to tegra_resume
Joseph Lo731a9272013-08-12 17:40:05 +0800415ENDPROC(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 */
423tegra20_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 */
434tegra20_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
Russell King6ebbf2c2014-06-30 16:29:12 +0100467 ret lr
Joseph Lo731a9272013-08-12 17:40:05 +0800468
Joseph Lo1d328602013-01-16 17:33:55 +0000469/*
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 */
476tegra20_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
487halted:
488 dsb
489 wfe /* CPU should be power gated here */
490 isb
491 b halted
492
Joseph Lo731a9272013-08-12 17:40:05 +0800493/*
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 */
500tegra20_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
506emcidle:
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
516emcself:
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
528padsave:
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
540padsave_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
Russell King6ebbf2c2014-06-30 16:29:12 +0100547 ret lr
Joseph Lo731a9272013-08-12 17:40:05 +0800548
549tegra20_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
558tegra20_sdram_pad_size:
559 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
560
561tegra20_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
570tegra20_sclk_save:
571 .word 0x0
572
573tegra20_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
582tegra20_iram_end:
583 b .
Joseph Lo5c1350b2013-01-15 22:10:38 +0000584#endif