diff options
Diffstat (limited to '')
-rw-r--r-- | arch/arm/mach-tegra/sleep-tegra20.S | 206 |
1 files changed, 33 insertions, 173 deletions
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S index 9a89f30d53ca..a5a36cce142a 100644 --- a/arch/arm/mach-tegra/sleep-tegra20.S +++ b/arch/arm/mach-tegra/sleep-tegra20.S @@ -43,14 +43,34 @@ #define APB_MISC_XM2CFGCPADCTRL2 0x8e4 #define APB_MISC_XM2CFGDPADCTRL2 0x8e8 -#define __tegra20_cpu1_resettable_status_offset \ - (__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS)) +#define PLLC_STORE_MASK (1 << 0) +#define PLLM_STORE_MASK (1 << 1) +#define PLLP_STORE_MASK (1 << 2) + +.macro test_pll_state, rd, test_mask + ldr \rd, tegra_pll_state + tst \rd, #\test_mask +.endm + +.macro store_pll_state, rd, tmp, r_car_base, pll_base, pll_mask + ldr \rd, [\r_car_base, #\pll_base] + tst \rd, #(1 << 30) + ldr \rd, tegra_pll_state + biceq \rd, \rd, #\pll_mask + orrne \rd, \rd, #\pll_mask + adr \tmp, tegra_pll_state + str \rd, [\tmp] +.endm + +.macro pll_enable, rd, r_car_base, pll_base, test_mask + test_pll_state \rd, \test_mask + beq 1f -.macro pll_enable, rd, r_car_base, pll_base ldr \rd, [\r_car_base, #\pll_base] tst \rd, #(1 << 30) orreq \rd, \rd, #(1 << 30) streq \rd, [\r_car_base, #\pll_base] +1: .endm .macro emc_device_mask, rd, base @@ -90,10 +110,6 @@ ENDPROC(tegra20_hotplug_shutdown) ENTRY(tegra20_cpu_shutdown) cmp r0, #0 reteq lr @ must not be called for CPU 0 - mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT - ldr r2, =__tegra20_cpu1_resettable_status_offset - mov r12, #CPU_RESETTABLE - strb r12, [r1, r2] cpu_to_halt_reg r1, r0 ldr r3, =TEGRA_FLOW_CTRL_VIRT @@ -117,107 +133,6 @@ ENDPROC(tegra20_cpu_shutdown) #ifdef CONFIG_PM_SLEEP /* - * tegra_pen_lock - * - * spinlock implementation with no atomic test-and-set and no coherence - * using Peterson's algorithm on strongly-ordered registers - * used to synchronize a cpu waking up from wfi with entering lp2 on idle - * - * The reference link of Peterson's algorithm: - * http://en.wikipedia.org/wiki/Peterson's_algorithm - * - * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm) - * on cpu 0: - * r2 = flag[0] (in SCRATCH38) - * r3 = flag[1] (in SCRATCH39) - * on cpu1: - * r2 = flag[1] (in SCRATCH39) - * r3 = flag[0] (in SCRATCH38) - * - * must be called with MMU on - * corrupts r0-r3, r12 - */ -ENTRY(tegra_pen_lock) - mov32 r3, TEGRA_PMC_VIRT - cpu_id r0 - add r1, r3, #PMC_SCRATCH37 - cmp r0, #0 - addeq r2, r3, #PMC_SCRATCH38 - addeq r3, r3, #PMC_SCRATCH39 - addne r2, r3, #PMC_SCRATCH39 - addne r3, r3, #PMC_SCRATCH38 - - mov r12, #1 - str r12, [r2] @ flag[cpu] = 1 - dsb - str r12, [r1] @ !turn = cpu -1: dsb - ldr r12, [r3] - cmp r12, #1 @ flag[!cpu] == 1? - ldreq r12, [r1] - cmpeq r12, r0 @ !turn == cpu? - beq 1b @ while !turn == cpu && flag[!cpu] == 1 - - ret lr @ locked -ENDPROC(tegra_pen_lock) - -ENTRY(tegra_pen_unlock) - dsb - mov32 r3, TEGRA_PMC_VIRT - cpu_id r0 - cmp r0, #0 - addeq r2, r3, #PMC_SCRATCH38 - addne r2, r3, #PMC_SCRATCH39 - mov r12, #0 - str r12, [r2] - ret lr -ENDPROC(tegra_pen_unlock) - -/* - * tegra20_cpu_clear_resettable(void) - * - * Called to clear the "resettable soon" flag in IRAM variable when - * it is expected that the secondary CPU will be idle soon. - */ -ENTRY(tegra20_cpu_clear_resettable) - mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT - ldr r2, =__tegra20_cpu1_resettable_status_offset - mov r12, #CPU_NOT_RESETTABLE - strb r12, [r1, r2] - ret lr -ENDPROC(tegra20_cpu_clear_resettable) - -/* - * tegra20_cpu_set_resettable_soon(void) - * - * Called to set the "resettable soon" flag in IRAM variable when - * it is expected that the secondary CPU will be idle soon. - */ -ENTRY(tegra20_cpu_set_resettable_soon) - mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT - ldr r2, =__tegra20_cpu1_resettable_status_offset - mov r12, #CPU_RESETTABLE_SOON - strb r12, [r1, r2] - ret lr -ENDPROC(tegra20_cpu_set_resettable_soon) - -/* - * tegra20_cpu_is_resettable_soon(void) - * - * Returns true if the "resettable soon" flag in IRAM variable has been - * set because it is expected that the secondary CPU will be idle soon. - */ -ENTRY(tegra20_cpu_is_resettable_soon) - mov32 r1, TEGRA_IRAM_RESET_BASE_VIRT - ldr r2, =__tegra20_cpu1_resettable_status_offset - ldrb r12, [r1, r2] - cmp r12, #CPU_RESETTABLE_SOON - moveq r0, #1 - movne r0, #0 - ret lr -ENDPROC(tegra20_cpu_is_resettable_soon) - -/* * tegra20_sleep_core_finish(unsigned long v2p) * * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to @@ -243,68 +158,6 @@ ENTRY(tegra20_sleep_core_finish) ENDPROC(tegra20_sleep_core_finish) /* - * tegra20_sleep_cpu_secondary_finish(unsigned long v2p) - * - * Enters WFI on secondary CPU by exiting coherency. - */ -ENTRY(tegra20_sleep_cpu_secondary_finish) - stmfd sp!, {r4-r11, lr} - - mrc p15, 0, r11, c1, c0, 1 @ save actlr before exiting coherency - - /* Flush and disable the L1 data cache */ - mov r0, #TEGRA_FLUSH_CACHE_LOUIS - bl tegra_disable_clean_inv_dcache - - mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT - ldr r4, =__tegra20_cpu1_resettable_status_offset - mov r3, #CPU_RESETTABLE - strb r3, [r0, r4] - - bl tegra_cpu_do_idle - - /* - * cpu may be reset while in wfi, which will return through - * tegra_resume to cpu_resume - * or interrupt may wake wfi, which will return here - * cpu state is unchanged - MMU is on, cache is on, coherency - * is off, and the data cache is off - * - * r11 contains the original actlr - */ - - bl tegra_pen_lock - - mov32 r0, TEGRA_IRAM_RESET_BASE_VIRT - ldr r4, =__tegra20_cpu1_resettable_status_offset - mov r3, #CPU_NOT_RESETTABLE - strb r3, [r0, r4] - - bl tegra_pen_unlock - - /* Re-enable the data cache */ - mrc p15, 0, r10, c1, c0, 0 - orr r10, r10, #CR_C - mcr p15, 0, r10, c1, c0, 0 - isb - - mcr p15, 0, r11, c1, c0, 1 @ reenable coherency - - /* Invalidate the TLBs & BTAC */ - mov r1, #0 - mcr p15, 0, r1, c8, c3, 0 @ invalidate shared TLBs - mcr p15, 0, r1, c7, c1, 6 @ invalidate shared BTAC - dsb - isb - - /* the cpu was running with coherency disabled, - * caches may be out of date */ - bl v7_flush_kern_cache_louis - - ldmfd sp!, {r4 - r11, pc} -ENDPROC(tegra20_sleep_cpu_secondary_finish) - -/* * tegra20_tear_down_cpu * * Switches the CPU cluster to PLL-P and enters sleep. @@ -347,9 +200,9 @@ ENTRY(tegra20_lp1_reset) str r1, [r0, #CLK_RESET_CCLK_DIVIDER] str r1, [r0, #CLK_RESET_SCLK_DIVIDER] - pll_enable r1, r0, CLK_RESET_PLLM_BASE - pll_enable r1, r0, CLK_RESET_PLLP_BASE - pll_enable r1, r0, CLK_RESET_PLLC_BASE + pll_enable r1, r0, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK + pll_enable r1, r0, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK + pll_enable r1, r0, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK adr r2, tegra20_sdram_pad_address adr r4, tegra20_sdram_pad_save @@ -440,6 +293,10 @@ tegra20_switch_cpu_to_clk32k: add r1, r1, #2 wait_until r1, r7, r9 + store_pll_state r0, r1, r5, CLK_RESET_PLLC_BASE, PLLC_STORE_MASK + store_pll_state r0, r1, r5, CLK_RESET_PLLM_BASE, PLLM_STORE_MASK + store_pll_state r0, r1, r5, CLK_RESET_PLLP_BASE, PLLP_STORE_MASK + /* disable PLLM, PLLP and PLLC */ ldr r0, [r5, #CLK_RESET_PLLM_BASE] bic r0, r0, #(1 << 30) @@ -566,6 +423,9 @@ tegra20_sdram_pad_save: .long 0 .endr +tegra_pll_state: + .word 0x0 + .ltorg /* dummy symbol for end of IRAM */ .align L1_CACHE_SHIFT |