1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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,
59 tst \rd,
60 orreq \rd, \rd,
61 streq \rd, [\r_car_base,
62.endm
63
64.macro emc_device_mask, rd, base
65 ldr \rd, [\base,
66 tst \rd,
67 moveq \rd,
68 movne \rd,
69.endm
70
71
72
73
74
75
76
77
78ENTRY(tegra20_hotplug_shutdown)
79
80 cpu_id r0
81 bl tegra20_cpu_shutdown
82 ret lr @ should never get here
83ENDPROC(tegra20_hotplug_shutdown)
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98ENTRY(tegra20_cpu_shutdown)
99 cmp r0,
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,
104 strb r12, [r1, r2]
105
106 cpu_to_halt_reg r1, r0
107 ldr r3, =TEGRA_FLOW_CTRL_VIRT
108 mov r2,
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,
117 isb
118 dsb
119 cpu_id r3
120 cmp r3, r0
121 beq .
122 ret lr
123ENDPROC(tegra20_cpu_shutdown)
124#endif
125
126#ifdef CONFIG_PM_SLEEP
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148ENTRY(tegra_pen_lock)
149 mov32 r3, TEGRA_PMC_VIRT
150 cpu_id r0
151 add r1, r3,
152 cmp r0,
153 addeq r2, r3,
154 addeq r3, r3,
155 addne r2, r3,
156 addne r3, r3,
157
158 mov r12,
159 str r12, [r2] @ flag[cpu] = 1
160 dsb
161 str r12, [r1] @ !turn = cpu
1621: dsb
163 ldr r12, [r3]
164 cmp r12,
165 ldreq r12, [r1]
166 cmpeq r12, r0 @ !turn == cpu?
167 beq 1b @ while !turn == cpu && flag[!cpu] == 1
168
169 ret lr @ locked
170ENDPROC(tegra_pen_lock)
171
172ENTRY(tegra_pen_unlock)
173 dsb
174 mov32 r3, TEGRA_PMC_VIRT
175 cpu_id r0
176 cmp r0,
177 addeq r2, r3,
178 addne r2, r3,
179 mov r12,
180 str r12, [r2]
181 ret lr
182ENDPROC(tegra_pen_unlock)
183
184
185
186
187
188
189
190ENTRY(tegra20_cpu_clear_resettable)
191 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
192 ldr r2, =__tegra20_cpu1_resettable_status_offset
193 mov r12,
194 strb r12, [r1, r2]
195 ret lr
196ENDPROC(tegra20_cpu_clear_resettable)
197
198
199
200
201
202
203
204ENTRY(tegra20_cpu_set_resettable_soon)
205 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
206 ldr r2, =__tegra20_cpu1_resettable_status_offset
207 mov r12,
208 strb r12, [r1, r2]
209 ret lr
210ENDPROC(tegra20_cpu_set_resettable_soon)
211
212
213
214
215
216
217
218ENTRY(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,
223 moveq r0,
224 movne r0,
225 ret lr
226ENDPROC(tegra20_cpu_is_resettable_soon)
227
228
229
230
231
232
233
234ENTRY(tegra20_sleep_core_finish)
235 mov r4, r0
236
237 mov r0,
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
251ENDPROC(tegra20_sleep_core_finish)
252
253
254
255
256
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
264 mov r0,
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,
270 strb r3, [r0, r4]
271
272 bl tegra_cpu_do_idle
273
274
275
276
277
278
279
280
281
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,
289 strb r3, [r0, r4]
290
291 bl tegra_pen_unlock
292
293
294 mrc p15, 0, r10, c1, c0, 0
295 orr r10, r10,
296 mcr p15, 0, r10, c1, c0, 0
297 isb
298
299 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
300
301
302 mov r1,
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
309
310 bl v7_flush_kern_cache_louis
311
312 ldmfd sp!, {r4 - r11, pc}
313ENDPROC(tegra20_sleep_cpu_secondary_finish)
314
315
316
317
318
319
320ENTRY(tegra20_tear_down_cpu)
321 bl tegra_switch_cpu_to_pllp
322 b tegra20_enter_sleep
323ENDPROC(tegra20_tear_down_cpu)
324
325
326 .align L1_CACHE_SHIFT
327 .globl tegra20_iram_start
328tegra20_iram_start:
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343ENTRY(tegra20_lp1_reset)
344
345
346
347
348
349 mov32 r0, TEGRA_CLK_RESET_BASE
350
351 mov r1,
352 str r1, [r0,
353 str r1, [r0,
354 mov r1,
355 str r1, [r0,
356 str r1, [r0,
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,
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,
374 cmp r6, r5
375 bne padload
376
377padload_done:
378
379 mov32 r7, TEGRA_TMRUS_BASE
380 ldr r1, [r7]
381 add r1, r1,
382 wait_until r1, r7, r9
383
384 adr r4, tegra20_sclk_save
385 ldr r4, [r4]
386 str r4, [r0,
387 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
388 str r4, [r0,
389
390 mov32 r0, TEGRA_EMC_BASE
391 ldr r1, [r0,
392 bic r1, r1,
393 str r1, [r0,
394
395 mov r1,
396 str r1, [r0,
397 mov r1,
398 str r1, [r0,
399 str r1, [r0,
400 str r1, [r0,
401
402 emc_device_mask r1, r0
403
404exit_selfrefresh_loop:
405 ldr r2, [r0,
406 ands r2, r2, r1
407 bne exit_selfrefresh_loop
408
409 mov r1,
410 str r1, [r0,
411
412 mov32 r0, TEGRA_PMC_BASE
413 ldr r0, [r0,
414 ret r0 @ jump to tegra_resume
415ENDPROC(tegra20_lp1_reset)
416
417
418
419
420
421
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
430
431
432
433
434tegra20_switch_cpu_to_clk32k:
435
436
437
438
439 mov r0,
440 str r0, [r5,
441 str r0, [r5,
442 mov r0,
443 str r0, [r5,
444 str r0, [r5,
445
446
447 mov32 r7, TEGRA_TMRUS_BASE
448 ldr r1, [r7]
449 add r1, r1,
450 wait_until r1, r7, r9
451
452
453 ldr r0, [r5,
454 bic r0, r0,
455 str r0, [r5,
456 ldr r0, [r5,
457 bic r0, r0,
458 str r0, [r5,
459 ldr r0, [r5,
460 bic r0, r0,
461 str r0, [r5,
462
463
464 mov r0,
465 str r0, [r5,
466
467 ret lr
468
469
470
471
472
473
474
475
476tegra20_enter_sleep:
477 mov32 r6, TEGRA_FLOW_CTRL_BASE
478
479 mov r0,
480 orr r0, r0,
481 cpu_id r1
482 cpu_to_halt_reg r1, r1
483 str r0, [r6, r1]
484 dsb
485 ldr r0, [r6, r1]
486
487halted:
488 dsb
489 wfe
490 isb
491 b halted
492
493
494
495
496
497
498
499
500tegra20_sdram_self_refresh:
501 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
502
503 mov r2,
504 str r2, [r1,
505
506emcidle:
507 ldr r2, [r1,
508 tst r2,
509 beq emcidle
510
511 mov r2,
512 str r2, [r1,
513
514 emc_device_mask r2, r1
515
516emcself:
517 ldr r3, [r1,
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,
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,
538 cmp r6, r5
539 bne padsave
540padsave_done:
541
542 mov32 r5, TEGRA_CLK_RESET_BASE
543 ldr r0, [r5,
544 adr r2, tegra20_sclk_save
545 str r0, [r2]
546 dsb
547 ret lr
548
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
580 .align L1_CACHE_SHIFT
581 .globl tegra20_iram_end
582tegra20_iram_end:
583 b .
584#endif
585