/*
- * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2010-2013, 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,
#include "iomap.h"
+#ifndef CONFIG_TEGRA_USE_SECURE_KERNEL
+/* FIXME: The code associated with this should be removed if our change to
+ save the diagnostic regsiter in the CPU context is accepted. */
+#define USE_TEGRA_DIAG_REG_SAVE 1
+#else
+#define USE_TEGRA_DIAG_REG_SAVE 0
+#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)
-/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock in idle */
+#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
+ 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
.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
+ dsb
+#ifdef CONFIG_HAVE_ARM_SCU
cpu_id \tmp1
mov \tmp1, \tmp1, lsl #2
mov \tmp2, #0xf
mov32 \tmp1, TEGRA_ARM_PERIF_VIRT + 0xC
str \tmp2, [\tmp1] @ invalidate SCU tags for CPU
dsb
+#endif
.endm
-#else
+
+#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 <linux/io.h>
#ifdef CONFIG_HOTPLUG_CPU
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);
-void tegra_cpu_wfi(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 void tegra2_iram_start;
-extern void tegra2_iram_end;
-extern void tegra2_lp1_reset;
+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_sleep_core(unsigned long v2p);
-void tegra2_sleep_reset(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
+
+#ifdef CONFIG_TEGRA_USE_SECURE_KERNEL
+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;
+#endif
+#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
}
{
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
return &tegra2_iram_end;
+#else
+ return &tegra3_iram_end;
#endif
}
-static inline void *tegra_lp1_reset(void)
+#ifdef CONFIG_TEGRA_LP1_LOW_COREVOLTAGE
+static inline void *tegra_lp1_register_pmuslave_addr(void)
{
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- return &tegra2_lp1_reset;
+ return NULL;
+#else
+ return &lp1_register_pmuslave_addr;
#endif
}
-static inline void tegra_sleep_core(unsigned long v2p)
+static inline void *tegra_lp1_register_i2c_base_addr(void)
{
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- tegra2_sleep_core(v2p);
+ return NULL;
+#else
+ return &lp1_register_i2c_base_addr;
#endif
}
-void tegra_sleep_cpu(unsigned long v2p);
-void tegra_resume(void);
-void tegra_secondary_resume(void);
-
+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