0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/linkage.h>
0011
0012 #include <soc/tegra/flowctrl.h>
0013
0014 #include <asm/assembler.h>
0015 #include <asm/proc-fns.h>
0016 #include <asm/cp15.h>
0017 #include <asm/cache.h>
0018
0019 #include "irammap.h"
0020 #include "reset.h"
0021 #include "sleep.h"
0022
0023 #define EMC_CFG 0xc
0024 #define EMC_ADR_CFG 0x10
0025 #define EMC_NOP 0xdc
0026 #define EMC_SELF_REF 0xe0
0027 #define EMC_REQ_CTRL 0x2b0
0028 #define EMC_EMC_STATUS 0x2b4
0029
0030 #define CLK_RESET_CCLK_BURST 0x20
0031 #define CLK_RESET_CCLK_DIVIDER 0x24
0032 #define CLK_RESET_SCLK_BURST 0x28
0033 #define CLK_RESET_SCLK_DIVIDER 0x2c
0034 #define CLK_RESET_PLLC_BASE 0x80
0035 #define CLK_RESET_PLLM_BASE 0x90
0036 #define CLK_RESET_PLLP_BASE 0xa0
0037
0038 #define APB_MISC_XM2CFGCPADCTRL 0x8c8
0039 #define APB_MISC_XM2CFGDPADCTRL 0x8cc
0040 #define APB_MISC_XM2CLKCFGPADCTRL 0x8d0
0041 #define APB_MISC_XM2COMPPADCTRL 0x8d4
0042 #define APB_MISC_XM2VTTGENPADCTRL 0x8d8
0043 #define APB_MISC_XM2CFGCPADCTRL2 0x8e4
0044 #define APB_MISC_XM2CFGDPADCTRL2 0x8e8
0045
0046 #define PLLC_STORE_MASK (1 << 0)
0047 #define PLLM_STORE_MASK (1 << 1)
0048 #define PLLP_STORE_MASK (1 << 2)
0049
0050 .macro test_pll_state, rd, test_mask
0051 ldr \rd, tegra_pll_state
0052 tst \rd, #\test_mask
0053 .endm
0054
0055 .macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask
0056 ldr \rd, [\r_car_base, #\pll_base]
0057 tst \rd, #(1 << 30)
0058 ldr \rd, tegra_pll_state
0059 biceq \rd, \rd, #\pll_mask
0060 orrne \rd, \rd, #\pll_mask
0061 adr \tmp, tegra_pll_state
0062 str \rd, [\tmp]
0063 .endm
0064
0065 .macro pll_enable, rd, r_car_base, pll_base, test_mask
0066 test_pll_state \rd, \test_mask
0067 beq 1f
0068
0069 ldr \rd, [\r_car_base, #\pll_base]
0070 tst \rd, #(1 << 30)
0071 orreq \rd, \rd, #(1 << 30)
0072 streq \rd, [\r_car_base, #\pll_base]
0073 1:
0074 .endm
0075
0076 .macro emc_device_mask, rd, base
0077 ldr \rd, [\base, #EMC_ADR_CFG]
0078 tst \rd, #(0x3 << 24)
0079 moveq \rd, #(0x1 << 8) @ just 1 device
0080 movne \rd, #(0x3 << 8) @ 2 devices
0081 .endm
0082
0083 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
0084
0085
0086
0087
0088
0089
0090 ENTRY(tegra20_hotplug_shutdown)
0091
0092 cpu_id r0
0093 bl tegra20_cpu_shutdown
0094 ret lr @ should never get here
0095 ENDPROC(tegra20_hotplug_shutdown)
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 ENTRY(tegra20_cpu_shutdown)
0111 cmp r0, #0
0112 reteq lr @ must not be called for CPU 0
0113
0114 cpu_to_halt_reg r1, r0
0115 ldr r3, =TEGRA_FLOW_CTRL_VIRT
0116 mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
0117 str r2, [r3, r1] @ put flow controller in wait event mode
0118 ldr r2, [r3, r1]
0119 isb
0120 dsb
0121 movw r1, 0x1011
0122 mov r1, r1, lsl r0
0123 ldr r3, =TEGRA_CLK_RESET_VIRT
0124 str r1, [r3, #0x340] @ put slave CPU in reset
0125 isb
0126 dsb
0127 cpu_id r3
0128 cmp r3, r0
0129 beq .
0130 ret lr
0131 ENDPROC(tegra20_cpu_shutdown)
0132 #endif
0133
0134 #ifdef CONFIG_PM_SLEEP
0135
0136
0137
0138
0139
0140
0141 ENTRY(tegra20_sleep_core_finish)
0142 mov r4, r0
0143
0144 mov r0, #TEGRA_FLUSH_CACHE_ALL
0145 bl tegra_disable_clean_inv_dcache
0146 mov r0, r4
0147
0148 mov32 r3, tegra_shut_off_mmu
0149 add r3, r3, r0
0150
0151 mov32 r0, tegra20_tear_down_core
0152 mov32 r1, tegra20_iram_start
0153 sub r0, r0, r1
0154 mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
0155 add r0, r0, r1
0156
0157 ret r3
0158 ENDPROC(tegra20_sleep_core_finish)
0159
0160
0161
0162
0163
0164
0165 ENTRY(tegra20_tear_down_cpu)
0166 bl tegra_switch_cpu_to_pllp
0167 b tegra20_enter_sleep
0168 ENDPROC(tegra20_tear_down_cpu)
0169
0170
0171 .align L1_CACHE_SHIFT
0172 .globl tegra20_iram_start
0173 tegra20_iram_start:
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 ENTRY(tegra20_lp1_reset)
0189
0190
0191
0192
0193
0194 mov32 r0, TEGRA_CLK_RESET_BASE
0195
0196 mov r1, #(1 << 28)
0197 str r1, [r0, #CLK_RESET_SCLK_BURST]
0198 str r1, [r0, #CLK_RESET_CCLK_BURST]
0199 mov r1, #0
0200 str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
0201 str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
0202
0203 pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
0204 pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
0205 pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
0206
0207 adr r2, tegra20_sdram_pad_address
0208 adr r4, tegra20_sdram_pad_save
0209 mov r5, #0
0210
0211 ldr r6, tegra20_sdram_pad_size
0212 padload:
0213 ldr r7, [r2, r5] @ r7 is the addr in the pad_address
0214
0215 ldr r1, [r4, r5]
0216 str r1, [r7] @ restore the value in pad_save
0217
0218 add r5, r5, #4
0219 cmp r6, r5
0220 bne padload
0221
0222 padload_done:
0223
0224 mov32 r7, TEGRA_TMRUS_BASE
0225 ldr r1, [r7]
0226 add r1, r1, #0xff
0227 wait_until r1, r7, r9
0228
0229 adr r4, tegra20_sclk_save
0230 ldr r4, [r4]
0231 str r4, [r0, #CLK_RESET_SCLK_BURST]
0232 mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
0233 str r4, [r0, #CLK_RESET_CCLK_BURST]
0234
0235 mov32 r0, TEGRA_EMC_BASE
0236 ldr r1, [r0, #EMC_CFG]
0237 bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
0238 str r1, [r0, #EMC_CFG]
0239
0240 mov r1, #0
0241 str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
0242 mov r1, #1
0243 str r1, [r0, #EMC_NOP]
0244 str r1, [r0, #EMC_NOP]
0245
0246 emc_device_mask r1, r0
0247
0248 exit_selfrefresh_loop:
0249 ldr r2, [r0, #EMC_EMC_STATUS]
0250 ands r2, r2, r1
0251 bne exit_selfrefresh_loop
0252
0253 mov r1, #0 @ unstall all transactions
0254 str r1, [r0, #EMC_REQ_CTRL]
0255
0256 mov32 r0, TEGRA_PMC_BASE
0257 ldr r0, [r0, #PMC_SCRATCH41]
0258 ret r0 @ jump to tegra_resume
0259 ENDPROC(tegra20_lp1_reset)
0260
0261
0262
0263
0264
0265
0266
0267 tegra20_tear_down_core:
0268 bl tegra20_sdram_self_refresh
0269 bl tegra20_switch_cpu_to_clk32k
0270 b tegra20_enter_sleep
0271
0272
0273
0274
0275
0276
0277
0278 tegra20_switch_cpu_to_clk32k:
0279
0280
0281
0282
0283 mov r0, #(1 << 28)
0284 str r0, [r5, #CLK_RESET_SCLK_BURST]
0285 str r0, [r5, #CLK_RESET_CCLK_BURST]
0286 mov r0, #0
0287 str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
0288 str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
0289
0290
0291 mov32 r7, TEGRA_TMRUS_BASE
0292 ldr r1, [r7]
0293 add r1, r1, #2
0294 wait_until r1, r7, r9
0295
0296 store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK
0297 store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK
0298 store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK
0299
0300
0301 ldr r0, [r5, #CLK_RESET_PLLM_BASE]
0302 bic r0, r0, #(1 << 30)
0303 str r0, [r5, #CLK_RESET_PLLM_BASE]
0304 ldr r0, [r5, #CLK_RESET_PLLP_BASE]
0305 bic r0, r0, #(1 << 30)
0306 str r0, [r5, #CLK_RESET_PLLP_BASE]
0307 ldr r0, [r5, #CLK_RESET_PLLC_BASE]
0308 bic r0, r0, #(1 << 30)
0309 str r0, [r5, #CLK_RESET_PLLC_BASE]
0310
0311
0312 mov r0, #0
0313 str r0, [r5, #CLK_RESET_SCLK_BURST]
0314
0315 ret lr
0316
0317
0318
0319
0320
0321
0322
0323
0324 tegra20_enter_sleep:
0325 mov32 r6, TEGRA_FLOW_CTRL_BASE
0326
0327 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
0328 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
0329 cpu_id r1
0330 cpu_to_halt_reg r1, r1
0331 str r0, [r6, r1]
0332 dsb
0333 ldr r0, [r6, r1]
0334
0335 halted:
0336 dsb
0337 wfe
0338 isb
0339 b halted
0340
0341
0342
0343
0344
0345
0346
0347
0348 tegra20_sdram_self_refresh:
0349 mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
0350
0351 mov r2, #3
0352 str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
0353
0354 emcidle:
0355 ldr r2, [r1, #EMC_EMC_STATUS]
0356 tst r2, #4
0357 beq emcidle
0358
0359 mov r2, #1
0360 str r2, [r1, #EMC_SELF_REF]
0361
0362 emc_device_mask r2, r1
0363
0364 emcself:
0365 ldr r3, [r1, #EMC_EMC_STATUS]
0366 and r3, r3, r2
0367 cmp r3, r2
0368 bne emcself @ loop until DDR in self-refresh
0369
0370 adr r2, tegra20_sdram_pad_address
0371 adr r3, tegra20_sdram_pad_safe
0372 adr r4, tegra20_sdram_pad_save
0373 mov r5, #0
0374
0375 ldr r6, tegra20_sdram_pad_size
0376 padsave:
0377 ldr r0, [r2, r5] @ r0 is the addr in the pad_address
0378
0379 ldr r1, [r0]
0380 str r1, [r4, r5] @ save the content of the addr
0381
0382 ldr r1, [r3, r5]
0383 str r1, [r0] @ set the save val to the addr
0384
0385 add r5, r5, #4
0386 cmp r6, r5
0387 bne padsave
0388 padsave_done:
0389
0390 mov32 r5, TEGRA_CLK_RESET_BASE
0391 ldr r0, [r5, #CLK_RESET_SCLK_BURST]
0392 adr r2, tegra20_sclk_save
0393 str r0, [r2]
0394 dsb
0395 ret lr
0396
0397 tegra20_sdram_pad_address:
0398 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
0399 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
0400 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
0401 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
0402 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
0403 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
0404 .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
0405
0406 tegra20_sdram_pad_size:
0407 .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
0408
0409 tegra20_sdram_pad_safe:
0410 .word 0x8
0411 .word 0x8
0412 .word 0x0
0413 .word 0x8
0414 .word 0x5500
0415 .word 0x08080040
0416 .word 0x0
0417
0418 tegra20_sclk_save:
0419 .word 0x0
0420
0421 tegra20_sdram_pad_save:
0422 .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
0423 .long 0
0424 .endr
0425
0426 tegra_pll_state:
0427 .word 0x0
0428
0429 .ltorg
0430
0431 .align L1_CACHE_SHIFT
0432 .globl tegra20_iram_end
0433 tegra20_iram_end:
0434 b .
0435 #endif