/* * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope 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, see . */ #ifndef __MACH_TEGRA_SLEEP_H #define __MACH_TEGRA_SLEEP_H #include "iomap.h" #ifndef __ASSEMBLY__ enum { TEGRA_ID_CPU_SUSPEND_LP0 = 1, TEGRA_ID_CPU_SUSPEND_LP1 = 2, TEGRA_ID_CPU_SUSPEND_LP1_STOP_MCCLK = 3, TEGRA_ID_CPU_SUSPEND_CLUSTER = 4, TEGRA_ID_CPU_SUSPEND_STDBY = 5, }; #define TEGRA_PWR_DN_AFFINITY_CPU 0 #define TEGRA_PWR_DN_AFFINITY_CLUSTER 1 #endif #define TEGRA_POWER_LP1_AUDIO (1 << 25) /* do not turn off pll-p in LP1 */ #ifdef CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE /* Power gate CRAIL partition */ #define TEGRA_POWER_CLUSTER_PART_CRAIL (1 << 25) /* Power gate CxNC partition */ #define TEGRA_POWER_CLUSTER_PART_NONCPU (1 << 24) #define TEGRA_POWER_CLUSTER_PART_MASK (TEGRA_POWER_CLUSTER_PART_CRAIL | \ TEGRA_POWER_CLUSTER_PART_NONCPU) #define TEGRA_POWER_CLUSTER_PART_DEFAULT TEGRA_POWER_CLUSTER_PART_CRAIL #else #define TEGRA_POWER_CLUSTER_PART_DEFAULT 0 #endif #define TEGRA_POWER_CLUSTER_PART_SHIFT 24 #define TEGRA_POWER_CLUSTER_FORCE_SHIFT 2 #define TEGRA_POWER_CLUSTER_FORCE_MASK (1 << TEGRA_POWER_CLUSTER_FORCE_SHIFT) /* Stop MC clock */ #define TEGRA_POWER_STOP_MC_CLK (1 << 23) #define TEGRA_POWER_SDRAM_SELFREFRESH (1 << 26) /* SDRAM is in self-refresh */ #define TEGRA_POWER_HOTPLUG_SHUTDOWN (1 << 27) /* Hotplug shutdown */ #define TEGRA_POWER_CLUSTER_G (1 << 28) /* G CPU */ #define TEGRA_POWER_CLUSTER_LP (1 << 29) /* LP CPU */ #define TEGRA_POWER_CLUSTER_MASK (TEGRA_POWER_CLUSTER_G | \ TEGRA_POWER_CLUSTER_LP) #define TEGRA_POWER_CLUSTER_IMMEDIATE (1 << 30) /* Immediate wake */ #define TEGRA_POWER_CLUSTER_FORCE (1 << 31) /* Force switch */ #define TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K) #define PMC_SCRATCH1_ECO 0x264 /* PMC_LP_STATE_SCRATCH_REG is used to store the Warmboot flag for LP0 */ #define PMC_SCRATCH0 0x50 /* PMC_LP_STATE_SCRATCH_REG is used to store the Warmboot flag for LP0 */ #define PMC_LP_STATE_SCRATCH_REG 0x50 #define PMC_LP_STATE_BIT_OFFSET 28 #define PMC_LP_STATE_BIT_MASK 0x3 #define PMC_LP_STATE_LP0 0 #define PMC_LP_STATE_LP1 1 #define PMC_LP_STATE_LP1BB 2 #define PMC_SCRATCH1_ECO 0x264 /* PMC registers to query occurence of BB paging event */ #define PMC_IPC_STS 0x500 #define PMC_IPC_STS_MEM_REQ_SOON (1 << 4) #define PMC_IPC_STS_MEM_REQ (1 << 3) #define PMC_IPC_SET 0x504 #define PMC_IPC_SET_MEM_STS (1 << 5) #define PMC_IPC_CLR 0x508 #define PMC_IPC_CLR_MEM_STS (1 << 5) /* PMC register to program mem_req->0 interrupt for LP1BB */ #define PMC_WAKE_STATUS 0x14 #define PMC_WAKE2_MASK 0x160 #define PMC_WAKE2_LEVEL 0x164 #define PMC_WAKE2_STATUS 0x168 #define PMC_WAKE2_BB_MEM_REQ (1 << 29) /* Additional PMC Control register */ #define PMC_CTRL2 0x440 #define PMC_CTRL2_WAKE_DET_EN (1 << 9) /* PMC register for sampling of PMC_WAKE_LVL values */ #define PMC_AUTO_WAKE_LVL 0xd8 /* PMC_SCRATCH2 is used for PLLM boot state if PLLM auto-restart is enabled */ #define PMC_SCRATCH2 0x58 /* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock in Tegra2 idle * PMC_SCRATCH37[25] is used to query Audio HUB */ #define PMC_SCRATCH37 0x130 #define PMC_SCRATCH38 0x134 /* PMC_SCRATCH39 stores the reset vector of the AVP (always 0) after LP0 */ #define PMC_SCRATCH39 0x138 /* PMC_SCRATCH41 stores the reset vector of the CPU after LP0 and LP1 */ #define PMC_SCRATCH41 0x140 /* Legacy Interrupt Controller register to allow PMC Wake events * to be propagated to LIC as interrupts. */ #define TRI_ICTLR_VIRQ_CPU 0x0 #define TRI_ICTLR_CPU_IER_SET 0x24 #define TRI_ICTLR_CPU_IER_CLR 0x28 #define TRI_ICTLR_PMC_WAKE_INT (1 << 12) #ifdef CONFIG_ARCH_TEGRA_2x_SOC #define CPU_RESETTABLE 2 #define CPU_RESETTABLE_SOON 1 #define CPU_NOT_RESETTABLE 0 #endif #define FLOW_CTRL_HALT_CPU0_EVENTS 0x0 #define FLOW_CTRL_WAITEVENT (2 << 29) #define FLOW_CTRL_WAIT_FOR_INTERRUPT (4 << 29) #define FLOW_CTRL_JTAG_RESUME (1 << 28) #define FLOW_CTRL_HALT_CPU_IRQ (1 << 10) #define FLOW_CTRL_HALT_CPU_FIQ (1 << 8) #define FLOW_CTRL_HALT_LIC_IRQ (1 << 11) #define FLOW_CTRL_HALT_LIC_FIQ (1 << 10) #define FLOW_CTRL_HALT_GIC_IRQ (1 << 9) #define FLOW_CTRL_HALT_GIC_FIQ (1 << 8) #define FLOW_CTRL_IMMEDIATE_WAKE (1 << 3) #define FLOW_CTRL_CPU0_CSR 0x8 #define FLOW_CTRL_CSR_INTR_FLAG (1 << 15) #define FLOW_CTRL_CSR_EVENT_FLAG (1 << 14) #define FLOW_CTRL_CSR_ENABLE_EXT_NONE (0) #define FLOW_CTRL_CSR_ENABLE_EXT_CRAIL (1<<13) #define FLOW_CTRL_CSR_ENABLE_EXT_NCPU (1<<12) #define FLOW_CTRL_CSR_ENABLE_EXT_MASK ( \ FLOW_CTRL_CSR_ENABLE_EXT_NCPU | \ FLOW_CTRL_CSR_ENABLE_EXT_CRAIL ) #define FLOW_CTRL_CSR_ENABLE_EXT_EMU FLOW_CTRL_CSR_ENABLE_EXT_MASK #define FLOW_CTRL_CSR_IMMEDIATE_WAKE (1<<3) #define FLOW_CTRL_CSR_SWITCH_CLUSTER (1<<2) #define FLOW_CTRL_CSR_ENABLE (1 << 0) #define FLOW_CTRL_HALT_CPU1_EVENTS 0x14 #define FLOW_CTRL_CPU1_CSR 0x18 #ifdef CONFIG_ARCH_TEGRA_2x_SOC #define FLOW_CTRL_CSR_WFE_CPU0 (1 << 4) #define FLOW_CTRL_CSR_WFE_BITMAP (3 << 4) #define FLOW_CTRL_CSR_WFI_BITMAP 0 #else #define FLOW_CTRL_CSR_WFE_BITMAP (0xF << 4) #define FLOW_CTRL_CSR_WFI_CPU0 (1 << 8) #define FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8) #endif #ifdef CONFIG_CACHE_L2X0 #define TEGRA_PL310_VIRT (TEGRA_ARM_PL310_BASE - IO_CPU_PHYS + IO_CPU_VIRT) #endif #ifdef CONFIG_HAVE_ARM_SCU #define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \ + IO_CPU_VIRT) #endif #define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \ + IO_PPSB_VIRT) #define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \ + IO_PPSB_VIRT) #ifdef __ASSEMBLY__ /* waits until the microsecond counter (base) ticks, for exact timing loops */ .macro wait_for_us, rd, base, tmp ldr \rd, [\base] 1001: ldr \tmp, [\base] cmp \rd, \tmp beq 1001b mov \tmp, \rd .endm /* waits until the microsecond counter (base) is > rn */ .macro wait_until, rn, base, tmp add \rn, \rn, #1 1002: ldr \tmp, [\base] sub \tmp, \tmp, \rn ands \tmp, \tmp, #0x80000000 dmb sy bne 1002b .endm /* returns the offset of the flow controller halt register for a cpu */ .macro cpu_to_halt_reg rd, rcpu cmp \rcpu, #0 mov \rd, #0 beq 1001f sub \rd, \rcpu, #1 lsl \rd, \rd, #3 add \rd, \rd, #0x14 1001: .endm /* returns the offset of the flow controller csr register for a cpu */ .macro cpu_to_csr_reg rd, rcpu cmp \rcpu, #0 mov \rd, #0x8 beq 1001f sub \rd, \rcpu, #1 lsl \rd, \rd, #3 add \rd, \rd, #0x18 1001: .endm /* Issue a Dummy DVM op to make subsequent DSB issue a DVM_SYNC in A15. This is for a bug where DSB-lite( with no DVM_SYNC component) doesn't trigger the logic returned to drain all other DSBs. */ .macro dummy_dvm_op, tmp1, tmp2 mrc p15, 0, \tmp1, c0, c0, 0 movw \tmp2, #0xC0F0 @ Cortex a15 part number and \tmp1, \tmp1, \tmp2 cmp \tmp1, \tmp2 moveq \tmp1, #0 mcreq p15, 0, \tmp1, c7, c5, 6 .endm /* returns the ID of the current processor */ .macro cpu_id, rd #ifndef CONFIG_ARM64 mrc p15, 0, \rd, c0, c0, 5 and \rd, \rd, #0xF #else mrs \rd, mpidr_el1 and \rd, \rd, #0xF #endif .endm /* loads a 32-bit value into a register without a data access */ .macro mov32, reg, val #ifndef CONFIG_ARM64 movw \reg, #:lower16:\val movt \reg, #:upper16:\val #else ldr \reg, =\val #endif .endm /* Macro to exit SMP coherency. */ .macro exit_smp, tmp1, tmp2 mrc p15, 0, \tmp1, c1, c0, 1 @ ACTLR bic \tmp1, \tmp1, #(1<<6) | (1<<0) @ clear ACTLR.SMP | ACTLR.FW #ifdef CONFIG_ARM_ERRATA_799270 ldr \tmp2, =TEGRA_CLK_RESET_VIRT ldr \tmp2, [\tmp2, #0x70] @ BOND_OUT_L and \tmp2, \tmp2, #0 orr \tmp1, \tmp1, \tmp2 #endif mcr p15, 0, \tmp1, c1, c0, 1 @ ACTLR isb dummy_dvm_op \tmp1, \tmp2 @ dummy dvm op for cortex_a15 dsb #ifdef CONFIG_HAVE_ARM_SCU cpu_id \tmp1 mov \tmp1, \tmp1, lsl #2 mov \tmp2, #0xf mov \tmp2, \tmp2, lsl \tmp1 mov32 \tmp1, TEGRA_ARM_PERIF_VIRT + 0xC str \tmp2, [\tmp1] @ invalidate SCU tags for CPU dsb #endif .endm #define DEBUG_CONTEXT_STACK 0 /* pops a debug check token from the stack */ .macro pop_stack_token tmp1, tmp2 #if DEBUG_CONTEXT_STACK mov32 \tmp1, 0xBAB1F00D ldmfd sp!, {\tmp2} cmp \tmp1, \tmp2 movne pc, #0 #endif .endm /* pushes a debug check token onto the stack */ .macro push_stack_token tmp1 #if DEBUG_CONTEXT_STACK mov32 \tmp1, 0xBAB1F00D stmfd sp!, {\tmp1} #endif .endm #else /* !defined(__ASSEMBLY__) */ #include #ifdef CONFIG_HOTPLUG_CPU void tegra20_hotplug_init(void); void tegra30_hotplug_init(void); #else static inline void tegra20_hotplug_init(void) {} static inline void tegra30_hotplug_init(void) {} #endif #define FLOW_CTRL_HALT_CPU(cpu) (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + \ ((cpu) ? (FLOW_CTRL_HALT_CPU1_EVENTS + 8 * ((cpu) - 1)) : \ FLOW_CTRL_HALT_CPU0_EVENTS)) #define FLOW_CTRL_CPU_CSR(cpu) (IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + \ ((cpu) ? (FLOW_CTRL_CPU1_CSR + 8 * ((cpu) - 1)) : \ FLOW_CTRL_CPU0_CSR)) static inline void flowctrl_writel(unsigned long val, void __iomem *addr) { writel(val, addr); #ifdef CONFIG_ARCH_TEGRA_2x_SOC wmb(); #endif (void)__raw_readl(addr); } void tegra_pen_lock(void); void tegra_pen_unlock(void); int tegra_sleep_cpu_finish(unsigned long v2p); void tegra_resume(void); void tegra_flush_l1_cache(void); void tegra_flush_cache(void); #ifdef CONFIG_ARCH_TEGRA_2x_SOC extern unsigned int tegra2_iram_start; extern unsigned int tegra2_iram_end; int tegra2_cpu_is_resettable_soon(void); void tegra2_cpu_reset(int cpu); void tegra2_cpu_set_resettable_soon(void); void tegra2_cpu_clear_resettable(void); int tegra2_sleep_core_finish(unsigned long int); void tegra2_sleep_wfi(unsigned long v2p); int tegra2_finish_sleep_cpu_secondary(unsigned long int); #else extern unsigned int tegra3_iram_start; extern unsigned int tegra3_iram_end; #ifdef CONFIG_TEGRA_LP1_LOW_COREVOLTAGE extern unsigned int lp1_register_pmuslave_addr; extern unsigned int lp1_register_i2c_base_addr; extern unsigned int lp1_register_core_lowvolt; extern unsigned int lp1_register_core_highvolt; #endif int tegra3_sleep_core_finish(unsigned long int); int tegra3_sleep_cpu_secondary_finish(unsigned long int); int tegra3_stop_mc_clk_finish(unsigned long int); #endif extern unsigned long tegra_resume_timestamps_start; extern unsigned long tegra_resume_timestamps_end; #ifndef CONFIG_ARCH_TEGRA_11x_SOC extern unsigned long tegra_resume_smc_entry_time; extern unsigned long tegra_resume_smc_exit_time; #endif extern unsigned long tegra_resume_entry_time; #if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_PM_SLEEP) extern unsigned long tegra_resume_l2_init; #endif static inline void *tegra_iram_start(void) { #ifdef CONFIG_ARCH_TEGRA_2x_SOC return &tegra2_iram_start; #else return &tegra3_iram_start; #endif } static inline void *tegra_iram_end(void) { #ifdef CONFIG_ARCH_TEGRA_2x_SOC return &tegra2_iram_end; #else return &tegra3_iram_end; #endif } #ifdef CONFIG_TEGRA_LP1_LOW_COREVOLTAGE static inline void *tegra_lp1_register_pmuslave_addr(void) { #ifdef CONFIG_ARCH_TEGRA_2x_SOC return NULL; #else return &lp1_register_pmuslave_addr; #endif } static inline void *tegra_lp1_register_i2c_base_addr(void) { #ifdef CONFIG_ARCH_TEGRA_2x_SOC return NULL; #else return &lp1_register_i2c_base_addr; #endif } static inline void *tegra_lp1_register_core_lowvolt(void) { #ifdef CONFIG_ARCH_TEGRA_2x_SOC return NULL; #else return &lp1_register_core_lowvolt; #endif } static inline void *tegra_lp1_register_core_highvolt(void) { #ifdef CONFIG_ARCH_TEGRA_2x_SOC return NULL; #else return &lp1_register_core_highvolt; #endif } #endif /* For CONFIG_TEGRA_LP1_LOW_COREVOLTAGE */ #endif #endif