ARM: tegra: power: implement LP1 suspend/resume for Tegra3
[linux-3.10.git] / arch / arm / mach-tegra / sleep.h
index 4ffae54..3f103c5 100644 (file)
 
 #include "iomap.h"
 
+#ifdef CONFIG_CACHE_L2X0
+#define USE_TEGRA_CPU_SUSPEND  1
+#else
+#define USE_TEGRA_CPU_SUSPEND  0
+#endif
+/* FIXME: The core 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
+
+#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 Tegra2 idle */
+#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
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+#define CPU_RESETTABLE                 2
+#define CPU_RESETTABLE_SOON            1
+#define CPU_NOT_RESETTABLE             0
+#endif
+
 #define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
                                        + IO_CPU_VIRT)
 #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)
-#define TEGRA_PMC_VIRT (TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
 
-/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */
-#define PMC_SCRATCH37  0x130
-#define PMC_SCRATCH38  0x134
-#define PMC_SCRATCH39  0x138
-#define PMC_SCRATCH41  0x140
+#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
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-#define CPU_RESETTABLE         2
-#define CPU_RESETTABLE_SOON    1
-#define CPU_NOT_RESETTABLE     0
-#endif
+/* 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
 
-#ifdef __ASSEMBLY__
 /* returns the offset of the flow controller halt register for a cpu */
 .macro cpu_to_halt_reg rd, rcpu
        cmp     \rcpu, #0
        dsb
 .endm
 
-/* Macro to resume & re-enable L2 cache */
-#ifndef L2X0_CTRL_EN
-#define L2X0_CTRL_EN   1
+#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
 
-#ifdef CONFIG_CACHE_L2X0
-.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
-       adr     \tmp1, \phys_l2x0_saved_regs
-       ldr     \tmp1, [\tmp1]
-       ldr     \tmp2, [\tmp1, #L2X0_R_PHY_BASE]
-       ldr     \tmp3, [\tmp2, #L2X0_CTRL]
-       tst     \tmp3, #L2X0_CTRL_EN
-       bne     exit_l2_resume
-       ldr     \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY]
-       str     \tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL]
-       ldr     \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY]
-       str     \tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL]
-       ldr     \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL]
-       str     \tmp3, [\tmp2, #L2X0_PREFETCH_CTRL]
-       ldr     \tmp3, [\tmp1, #L2X0_R_PWR_CTRL]
-       str     \tmp3, [\tmp2, #L2X0_POWER_CTRL]
-       ldr     \tmp3, [\tmp1, #L2X0_R_AUX_CTRL]
-       str     \tmp3, [\tmp2, #L2X0_AUX_CTRL]
-       mov     \tmp3, #L2X0_CTRL_EN
-       str     \tmp3, [\tmp2, #L2X0_CTRL]
-exit_l2_resume:
+/* 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 /* CONFIG_CACHE_L2X0 */
-.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
+
+.macro push_ctx_regs, tmp1
+       push_stack_token \tmp1          @ debug check word
+       stmfd   sp!, {r4 - r11, lr}
+#if USE_TEGRA_DIAG_REG_SAVE
+       mrc     p15, 0, r4, c15, c0, 1  @ read diagnostic register
+       stmfd   sp!, {r4}
+#endif
+.endm
+
+.macro pop_ctx_regs, tmp1, tmp2
+#if USE_TEGRA_DIAG_REG_SAVE
+       ldmfd   sp!, {r4}
+       mcr     p15, 0, r4, c15, c0, 1  @ write diagnostic register
+#endif
+       ldmfd   sp!, {r4 - r11, lr}
+       pop_stack_token \tmp1, \tmp2    @ debug stack debug token
 .endm
-#endif /* CONFIG_CACHE_L2X0 */
+
 #else
-void tegra_pen_lock(void);
-void tegra_pen_unlock(void);
-void tegra_resume(void);
-int tegra_sleep_cpu_finish(unsigned long);
-void tegra_disable_clean_inv_dcache(void);
 
 #ifdef CONFIG_HOTPLUG_CPU
 void tegra20_hotplug_init(void);
@@ -131,19 +173,56 @@ static inline void tegra20_hotplug_init(void) {}
 static inline void tegra30_hotplug_init(void) {}
 #endif
 
-void tegra20_cpu_shutdown(int cpu);
-int tegra20_cpu_is_resettable_soon(void);
-void tegra20_cpu_clear_resettable(void);
+void tegra_pen_lock(void);
+void tegra_pen_unlock(void);
+void tegra_cpu_wfi(void);
+
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
-void tegra20_cpu_set_resettable_soon(void);
+extern void tegra2_iram_start;
+extern void 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);
+void tegra2_sleep_core(unsigned long v2p);
+void tegra2_sleep_wfi(unsigned long v2p);
 #else
-static inline void tegra20_cpu_set_resettable_soon(void) {}
+extern void tegra3_iram_start;
+extern void tegra3_iram_end;
+void tegra3_sleep_core(unsigned long v2p);
+void tegra3_sleep_cpu_secondary(unsigned long v2p);
 #endif
 
-int tegra20_sleep_cpu_secondary_finish(unsigned long);
-void tegra20_tear_down_cpu(void);
-int tegra30_sleep_cpu_secondary_finish(unsigned long);
-void tegra30_tear_down_cpu(void);
+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
+}
+
+static inline void tegra_sleep_core(unsigned long v2p)
+{
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+       tegra2_sleep_core(v2p);
+#else
+       tegra3_sleep_core(v2p);
 #endif
+}
+
+void tegra_sleep_cpu(unsigned long v2p);
+void tegra_resume(void);
+
+#endif
+
 #endif