ARM: tegra: power: implement LP1 suspend/resume for Tegra3
[linux-3.10.git] / arch / arm / mach-tegra / sleep.h
index f2123b3..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 idle */
+/* 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 */
 /* 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
-
-#define FLOW_CTRL_WAITEVENT            (2 << 29)
-#define FLOW_CTRL_STOP_UNTIL_IRQ       (4 << 29)
-#define FLOW_CTRL_JTAG_RESUME          (1 << 28)
-#define FLOW_CTRL_IRQ_RESUME           (1 << 10)
-#define FLOW_CTRL_FIQ_RESUME           (1 << 8)
+#endif
 
 #define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
                                        + IO_CPU_VIRT)
                                        + 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
        str     \tmp2, [\tmp1]                  @ invalidate SCU tags for CPU
        dsb
 .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
+
+.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
+
 #else
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -101,24 +173,55 @@ static inline void tegra20_hotplug_init(void) {}
 static inline void tegra30_hotplug_init(void) {}
 #endif
 
-/* assembly routines implemented in sleep.S */
 void tegra_pen_lock(void);
 void tegra_pen_unlock(void);
 void tegra_cpu_wfi(void);
-void tegra_cpu_set_resettable_soon(void);
-int tegra_cpu_is_resettable_soon(void);
 
-extern void tegra_lp1_reset;
-extern void tegra_iram_start;
-extern void tegra_iram_end;
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+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
+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
+
+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
+}
 
-void tegra_lp2_in_idle(bool enable);
+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_wfi(unsigned long v2p);
 void tegra_sleep_cpu(unsigned long v2p);
-void tegra_sleep_core(unsigned long v2p);
 void tegra_resume(void);
-void tegra_secondary_resume(void);
 
 #endif