1
2
3
4
5
6
7
8
9
10 #include <linux/linkage.h>
11
12 #include <soc/tegra/flowctrl.h>
13
14 #include <asm/assembler.h>
15 #include <asm/proc-fns.h>
16 #include <asm/cp15.h>
17 #include <asm/cache.h>
18
19 #include "irammap.h"
20 #include "reset.h"
21 #include "sleep.h"
22
23 #define EMC_CFG 0xc
24 #define EMC_ADR_CFG 0x10
25 #define EMC_NOP 0xdc
26 #define EMC_SELF_REF 0xe0
27 #define EMC_REQ_CTRL 0x2b0
28 #define EMC_EMC_STATUS 0x2b4
29
30 #define CLK_RESET_CCLK_BURST 0x20
31 #define CLK_RESET_CCLK_DIVIDER 0x24
32 #define CLK_RESET_SCLK_BURST 0x28
33 #define CLK_RESET_SCLK_DIVIDER 0x2c
34 #define CLK_RESET_PLLC_BASE 0x80
35 #define CLK_RESET_PLLM_BASE 0x90
36 #define CLK_RESET_PLLP_BASE 0xa0
37
38 #define APB_MISC_XM2CFGCPADCTRL 0x8c8
39 #define APB_MISC_XM2CFGDPADCTRL 0x8cc
40 #define APB_MISC_XM2CLKCFGPADCTRL 0x8d0
41 #define APB_MISC_XM2COMPPADCTRL 0x8d4
42 #define APB_MISC_XM2VTTGENPADCTRL 0x8d8
43 #define APB_MISC_XM2CFGCPADCTRL2 0x8e4
44 #define APB_MISC_XM2CFGDPADCTRL2 0x8e8
45
46 #define __tegra20_cpu1_resettable_status_offset \
47 (__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS))
48
49 .macro pll_enable, rd, r_car_base, pll_base
50 ldr \rd, [\r_car_base, #\pll_base]
51 tst \rd, #(1 << 30)
52 orreq \rd, \rd, #(1 << 30)
53 streq \rd, [\r_car_base, #\pll_base]
54 .endm
55
56 .macro emc_device_mask, rd, base
57 ldr \rd, [\base, #EMC_ADR_CFG]
58 tst \rd, #(0x3 << 24)
59 moveq \rd, #(0x1 << 8) @ just 1 device
60 movne \rd, #(0x3 << 8) @ 2 devices
61 .endm
62
63 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
64
65
66
67
68
69
70 ENTRY(tegra20_hotplug_shutdown)
71
72 cpu_id r0
73 bl tegra20_cpu_shutdown
74 ret lr @ should never get here
75 ENDPROC(tegra20_hotplug_shutdown)
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 ENTRY(tegra20_cpu_shutdown)
91 cmp r0, #0
92 reteq lr @ must not be called for CPU 0
93 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
94 ldr r2, =__tegra20_cpu1_resettable_status_offset
95 mov r12, #CPU_RESETTABLE
96 strb r12, [r1, r2]
97
98 cpu_to_halt_reg r1, r0
99 ldr r3, =TEGRA_FLOW_CTRL_VIRT
100 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
101 str r2, [r3, r1] @ put flow controller in wait event mode
102 ldr r2, [r3, r1]
103 isb
104 dsb
105 movw r1, 0x1011
106 mov r1, r1, lsl r0
107 ldr r3, =TEGRA_CLK_RESET_VIRT
108 str r1, [r3, #0x340] @ put slave CPU in reset
109 isb
110 dsb
111 cpu_id r3
112 cmp r3, r0
113 beq .
114 ret lr
115 ENDPROC(tegra20_cpu_shutdown)
116 #endif
117
118 #ifdef CONFIG_PM_SLEEP
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 ENTRY(tegra_pen_lock)
141 mov32 r3, TEGRA_PMC_VIRT
142 cpu_id r0
143 add r1, r3, #PMC_SCRATCH37
144 cmp r0, #0
145 addeq r2, r3, #PMC_SCRATCH38
146 addeq r3, r3, #PMC_SCRATCH39
147 addne r2, r3, #PMC_SCRATCH39
148 addne r3, r3, #PMC_SCRATCH38
149
150 mov r12, #1
151 str r12, [r2] @ flag[cpu] = 1
152 dsb
153 str r12, [r1] @ !turn = cpu
154 1: dsb
155 ldr r12, [r3]
156 cmp r12, #1 @ flag[!cpu] == 1?
157 ldreq r12, [r1]
158 cmpeq r12, r0 @ !turn == cpu?
159 beq 1b @ while !turn == cpu && flag[!cpu] == 1
160
161 ret lr @ locked
162 ENDPROC(tegra_pen_lock)
163
164 ENTRY(tegra_pen_unlock)
165 dsb
166 mov32 r3, TEGRA_PMC_VIRT
167 cpu_id r0
168 cmp r0, #0
169 addeq r2, r3, #PMC_SCRATCH38
170 addne r2, r3, #PMC_SCRATCH39
171 mov r12, #0
172 str r12, [r2]
173 ret lr
174 ENDPROC(tegra_pen_unlock)
175
176
177
178
179
180
181
182 ENTRY(tegra20_cpu_clear_resettable)
183 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
184 ldr r2, =__tegra20_cpu1_resettable_status_offset
185 mov r12, #CPU_NOT_RESETTABLE
186 strb r12, [r1, r2]
187 ret lr
188 ENDPROC(tegra20_cpu_clear_resettable)
189
190
191
192
193
194
195
196 ENTRY(tegra20_cpu_set_resettable_soon)
197 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
198 ldr r2, =__tegra20_cpu1_resettable_status_offset
199 mov r12, #CPU_RESETTABLE_SOON
200 strb r12, [r1, r2]
201 ret lr
202 ENDPROC(tegra20_cpu_set_resettable_soon)
203
204
205
206
207
208
209
210 ENTRY(tegra20_cpu_is_resettable_soon)
211 mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT
212 ldr r2, =__tegra20_cpu1_resettable_status_offset
213 ldrb r12, [r1, r2]
214 cmp r12, #CPU_RESETTABLE_SOON
215 moveq r0, #1
216 movne r0, #0
217 ret lr
218 ENDPROC(tegra20_cpu_is_resettable_soon)
219
220
221
222
223
224
225
226 ENTRY(tegra20_sleep_core_finish)
227 mov r4, r0
228
229 mov r0, #TEGRA_FLUSH_CACHE_ALL
230 bl tegra_disable_clean_inv_dcache
231 mov r0, r4
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 ret r3
243 ENDPROC(tegra20_sleep_core_finish)
244
245
246
247
248
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
256 mov r0, #TEGRA_FLUSH_CACHE_LOUIS
257 bl tegra_disable_clean_inv_dcache
258
259 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
260 ldr r4, =__tegra20_cpu1_resettable_status_offset
261 mov r3, #CPU_RESETTABLE
262 strb r3, [r0, r4]
263
264 bl tegra_cpu_do_idle
265
266
267
268
269
270
271
272
273
274
275
276 bl tegra_pen_lock
277
278 mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT
279 ldr r4, =__tegra20_cpu1_resettable_status_offset
280 mov r3, #CPU_NOT_RESETTABLE
281 strb r3, [r0, r4]
282
283 bl tegra_pen_unlock
284
285
286 mrc p15, 0, r10, c1, c0, 0
287 orr r10, r10, #CR_C
288 mcr p15, 0, r10, c1, c0, 0
289 isb
290
291 mcr p15, 0, r11, c1, c0, 1 @ reenable coherency
292
293
294 mov r1, #0
295 mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs
296 mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC
297 dsb
298 isb
299
300
301
302 bl v7_flush_kern_cache_louis
303
304 ldmfd sp!, {r4 - r11, pc}
305 ENDPROC(tegra20_sleep_cpu_secondary_finish)
306
307
308
309
310
311
312 ENTRY(tegra20_tear_down_cpu)
313 bl tegra_switch_cpu_to_pllp
314 b tegra20_enter_sleep
315 ENDPROC(tegra20_tear_down_cpu)
316
317
318 .align L1_CACHE_SHIFT
319 .globl tegra20_iram_start
320 tegra20_iram_start:
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 ENTRY(tegra20_lp1_reset)
336
337
338
339
340
341 mov32 r0, TEGRA_CLK_RESET_BASE
342
343 mov r1, #(1 << 28)
344 str r1, [r0, #CLK_RESET_SCLK_BURST]
345 str r1, [r0, #CLK_RESET_CCLK_BURST]
346 mov r1, #0
347 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
348 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
349
350 pll_enable r1, r0, CLK_RESET_PLLM_BASE
351 pll_enable r1, r0, CLK_RESET_PLLP_BASE
352 pll_enable r1, r0, CLK_RESET_PLLC_BASE
353
354 adr r2, tegra20_sdram_pad_address
355 adr r4, tegra20_sdram_pad_save
356 mov r5, #0
357
358 ldr r6, tegra20_sdram_pad_size
359 padload:
360 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
361
362 ldr r1, [r4, r5]
363 str r1, [r7] @ restore the value in pad_save
364
365 add r5, r5, #4
366 cmp r6, r5
367 bne padload
368
369 padload_done:
370
371 mov32 r7, TEGRA_TMRUS_BASE
372 ldr r1, [r7]
373 add r1, r1, #0xff
374 wait_until r1, r7, r9
375
376 adr r4, tegra20_sclk_save
377 ldr r4, [r4]
378 str r4, [r0, #CLK_RESET_SCLK_BURST]
379 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
380 str r4, [r0, #CLK_RESET_CCLK_BURST]
381
382 mov32 r0, TEGRA_EMC_BASE
383 ldr r1, [r0, #EMC_CFG]
384 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
385 str r1, [r0, #EMC_CFG]
386
387 mov r1, #0
388 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
389 mov r1, #1
390 str r1, [r0, #EMC_NOP]
391 str r1, [r0, #EMC_NOP]
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 ret r0 @ jump to tegra_resume
406 ENDPROC(tegra20_lp1_reset)
407
408
409
410
411
412
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
421
422
423
424
425 tegra20_switch_cpu_to_clk32k:
426
427
428
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
438 mov32 r7, TEGRA_TMRUS_BASE
439 ldr r1, [r7]
440 add r1, r1, #2
441 wait_until r1, r7, r9
442
443
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
455 mov r0, #0
456 str r0, [r5, #CLK_RESET_SCLK_BURST]
457
458 ret lr
459
460
461
462
463
464
465
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]
477
478 halted:
479 dsb
480 wfe
481 isb
482 b halted
483
484
485
486
487
488
489
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 ret 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
571 .align L1_CACHE_SHIFT
572 .globl tegra20_iram_end
573 tegra20_iram_end:
574 b .
575 #endif