Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
0004  * Copyright (c) 2011, Google, Inc.
0005  *
0006  * Author: Colin Cross <ccross@android.com>
0007  *         Gary King <gking@nvidia.com>
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  * tegra20_hotplug_shutdown(void)
0086  *
0087  * puts the current cpu in reset
0088  * should never return
0089  */
0090 ENTRY(tegra20_hotplug_shutdown)
0091     /* Put this CPU down */
0092     cpu_id  r0
0093     bl  tegra20_cpu_shutdown
0094     ret lr          @ should never get here
0095 ENDPROC(tegra20_hotplug_shutdown)
0096 
0097 /*
0098  * tegra20_cpu_shutdown(int cpu)
0099  *
0100  * r0 is cpu to reset
0101  *
0102  * puts the specified CPU in wait-for-event mode on the flow controller
0103  * and puts the CPU in reset
0104  * can be called on the current cpu or another cpu
0105  * if called on the current cpu, does not return
0106  * MUST NOT BE CALLED FOR CPU 0.
0107  *
0108  * corrupts r0-r3, r12
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  * tegra20_sleep_core_finish(unsigned long v2p)
0137  *
0138  * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
0139  * tegra20_tear_down_core in IRAM
0140  */
0141 ENTRY(tegra20_sleep_core_finish)
0142     mov     r4, r0
0143     /* Flush, disable the L1 data cache and exit SMP */
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  * tegra20_tear_down_cpu
0162  *
0163  * Switches the CPU cluster to PLL-P and enters sleep.
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 /* START OF ROUTINES COPIED TO IRAM */
0171     .align L1_CACHE_SHIFT
0172     .globl tegra20_iram_start
0173 tegra20_iram_start:
0174 
0175 /*
0176  * tegra20_lp1_reset
0177  *
0178  * reset vector for LP1 restore; copied into IRAM during suspend.
0179  * Brings the system back up to a safe staring point (SDRAM out of
0180  * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
0181  * system clock running on the same PLL that it suspended at), and
0182  * jumps to tegra_resume to restore virtual addressing and PLLX.
0183  * The physical address of tegra_resume expected to be stored in
0184  * PMC_SCRATCH41.
0185  *
0186  * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
0187  */
0188 ENTRY(tegra20_lp1_reset)
0189     /*
0190      * The CPU and system bus are running at 32KHz and executing from
0191      * IRAM when this code is executed; immediately switch to CLKM and
0192      * enable PLLM, PLLP, PLLC.
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     /* 255uS delay for PLL stabilization */
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  * tegra20_tear_down_core
0263  *
0264  * copied into and executed from IRAM
0265  * puts memory in self-refresh for LP0 and LP1
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  * tegra20_switch_cpu_to_clk32k
0274  *
0275  * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
0276  * to the 32KHz clock.
0277  */
0278 tegra20_switch_cpu_to_clk32k:
0279     /*
0280      * start by switching to CLKM to safely disable PLLs, then switch to
0281      * CLKS.
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     /* 2uS delay delay between changing SCLK and disabling PLLs */
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     /* disable PLLM, PLLP and PLLC */
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     /* switch to CLKS */
0312     mov r0, #0  /* brust policy = 32KHz */
0313     str r0, [r5, #CLK_RESET_SCLK_BURST]
0314 
0315     ret lr
0316 
0317 /*
0318  * tegra20_enter_sleep
0319  *
0320  * uses flow controller to enter sleep state
0321  * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
0322  * executes from SDRAM with target state is LP2
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] /* memory barrier */
0334 
0335 halted:
0336     dsb
0337     wfe /* CPU should be power gated here */
0338     isb
0339     b   halted
0340 
0341 /*
0342  * tegra20_sdram_self_refresh
0343  *
0344  * called with MMU off and caches disabled
0345  * puts sdram in self refresh
0346  * must be executed from IRAM
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 /* dummy symbol for end of IRAM */
0431     .align L1_CACHE_SHIFT
0432     .globl tegra20_iram_end
0433 tegra20_iram_end:
0434     b   .
0435 #endif