mirror of
https://github.com/torvalds/linux.git
synced 2024-11-30 16:11:38 +00:00
1d328606c6
The "powered-down" cpuidle mode of Tegra20 needs the CPU0 be the last one core to go into this mode before other core. The coupled cpuidle framework can help to sync the MPCore to coupled state then go into "powered-down" idle mode together. The driver can just assume the MPCore come into "powered-down" mode at the same time. No need to take care if the CPU_0 goes into this mode along and only can put it into safe idle mode (WFI). The powered-down state of Tegra20 requires power gating both CPU cores. When the secondary CPU requests to enter powered-down state, it saves its own contexts and then enters WFI for waiting CPU0 in the same state. When the CPU0 requests powered-down state, it attempts to put the secondary CPU into reset to prevent it from waking up. Then power down both CPUs together and power off the cpu rail. Be aware of that, you may see the legacy power state "LP2" in the code which is exactly the same meaning of "CPU power down". Based on the work by: Colin Cross <ccross@android.com> Gary King <gking@nvidia.com> Signed-off-by: Joseph Lo <josephl@nvidia.com> Acked-by: Colin Cross <ccross@android.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
133 lines
3.2 KiB
ArmAsm
133 lines
3.2 KiB
ArmAsm
/*
|
|
* arch/arm/mach-tegra/sleep.S
|
|
*
|
|
* Copyright (c) 2010-2011, NVIDIA Corporation.
|
|
* Copyright (c) 2011, Google, Inc.
|
|
*
|
|
* Author: Colin Cross <ccross@android.com>
|
|
* Gary King <gking@nvidia.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <asm/assembler.h>
|
|
#include <asm/cache.h>
|
|
#include <asm/cp15.h>
|
|
#include <asm/hardware/cache-l2x0.h>
|
|
|
|
#include "iomap.h"
|
|
|
|
#include "flowctrl.h"
|
|
#include "sleep.h"
|
|
|
|
#define CLK_RESET_CCLK_BURST 0x20
|
|
#define CLK_RESET_CCLK_DIVIDER 0x24
|
|
|
|
#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
|
|
/*
|
|
* tegra_disable_clean_inv_dcache
|
|
*
|
|
* disable, clean & invalidate the D-cache
|
|
*
|
|
* Corrupted registers: r1-r3, r6, r8, r9-r11
|
|
*/
|
|
ENTRY(tegra_disable_clean_inv_dcache)
|
|
stmfd sp!, {r0, r4-r5, r7, r9-r11, lr}
|
|
dmb @ ensure ordering
|
|
|
|
/* Disable the D-cache */
|
|
mrc p15, 0, r2, c1, c0, 0
|
|
bic r2, r2, #CR_C
|
|
mcr p15, 0, r2, c1, c0, 0
|
|
isb
|
|
|
|
/* Flush the D-cache */
|
|
bl v7_flush_dcache_louis
|
|
|
|
/* Trun off coherency */
|
|
exit_smp r4, r5
|
|
|
|
ldmfd sp!, {r0, r4-r5, r7, r9-r11, pc}
|
|
ENDPROC(tegra_disable_clean_inv_dcache)
|
|
#endif
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
/*
|
|
* tegra_sleep_cpu_finish(unsigned long v2p)
|
|
*
|
|
* enters suspend in LP2 by turning off the mmu and jumping to
|
|
* tegra?_tear_down_cpu
|
|
*/
|
|
ENTRY(tegra_sleep_cpu_finish)
|
|
/* Flush and disable the L1 data cache */
|
|
bl tegra_disable_clean_inv_dcache
|
|
|
|
mov32 r6, tegra_tear_down_cpu
|
|
ldr r1, [r6]
|
|
add r1, r1, r0
|
|
|
|
mov32 r3, tegra_shut_off_mmu
|
|
add r3, r3, r0
|
|
mov r0, r1
|
|
|
|
mov pc, r3
|
|
ENDPROC(tegra_sleep_cpu_finish)
|
|
|
|
/*
|
|
* tegra_shut_off_mmu
|
|
*
|
|
* r0 = physical address to jump to with mmu off
|
|
*
|
|
* called with VA=PA mapping
|
|
* turns off MMU, icache, dcache and branch prediction
|
|
*/
|
|
.align L1_CACHE_SHIFT
|
|
.pushsection .idmap.text, "ax"
|
|
ENTRY(tegra_shut_off_mmu)
|
|
mrc p15, 0, r3, c1, c0, 0
|
|
movw r2, #CR_I | CR_Z | CR_C | CR_M
|
|
bic r3, r3, r2
|
|
dsb
|
|
mcr p15, 0, r3, c1, c0, 0
|
|
isb
|
|
#ifdef CONFIG_CACHE_L2X0
|
|
/* Disable L2 cache */
|
|
mov32 r4, TEGRA_ARM_PERIF_BASE + 0x3000
|
|
mov r5, #0
|
|
str r5, [r4, #L2X0_CTRL]
|
|
#endif
|
|
mov pc, r0
|
|
ENDPROC(tegra_shut_off_mmu)
|
|
.popsection
|
|
|
|
/*
|
|
* tegra_switch_cpu_to_pllp
|
|
*
|
|
* In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp
|
|
*/
|
|
ENTRY(tegra_switch_cpu_to_pllp)
|
|
/* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */
|
|
mov32 r5, TEGRA_CLK_RESET_BASE
|
|
mov r0, #(2 << 28) @ burst policy = run mode
|
|
orr r0, r0, #(4 << 4) @ use PLLP in run mode burst
|
|
str r0, [r5, #CLK_RESET_CCLK_BURST]
|
|
mov r0, #0
|
|
str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
|
|
mov pc, lr
|
|
ENDPROC(tegra_switch_cpu_to_pllp)
|
|
#endif
|