Merge branch 'next/cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[pandora-kernel.git] / arch / arm / mach-omap2 / pm34xx.c
index 96a7624..7255d9b 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/console.h>
 #include <trace/events/power.h>
 
+#include <asm/suspend.h>
+
 #include <plat/sram.h>
 #include "clockdomain.h"
 #include "powerdomain.h"
@@ -40,8 +42,6 @@
 #include <plat/gpmc.h>
 #include <plat/dma.h>
 
-#include <asm/tlbflush.h>
-
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
@@ -64,11 +64,6 @@ static inline bool is_suspending(void)
 }
 #endif
 
-/* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET     0xc4
-#define OMAP343X_TABLE_VALUE_OFFSET       0xc0
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
-
 /* pm34xx errata defined in pm.h */
 u16 pm34xx_errata;
 
@@ -83,9 +78,8 @@ struct power_state {
 
 static LIST_HEAD(pwrst_list);
 
-static void (*_omap_sram_idle)(u32 *addr, int save_state);
-
 static int (*_omap_save_secure_sram)(u32 *addr);
+void (*omap3_do_wfi_sram)(void);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -312,28 +306,25 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-/* Function to restore the table entry that was modified for enabling MMU */
-static void restore_table_entry(void)
+static void omap34xx_save_context(u32 *save)
 {
-       void __iomem *scratchpad_address;
-       u32 previous_value, control_reg_value;
-       u32 *address;
+       u32 val;
 
-       scratchpad_address = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD);
+       /* Read Auxiliary Control Register */
+       asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (val));
+       *save++ = 1;
+       *save++ = val;
 
-       /* Get address of entry that was modified */
-       address = (u32 *)__raw_readl(scratchpad_address +
-                                    OMAP343X_TABLE_ADDRESS_OFFSET);
-       /* Get the previous value which needs to be restored */
-       previous_value = __raw_readl(scratchpad_address +
-                                    OMAP343X_TABLE_VALUE_OFFSET);
-       address = __va(address);
-       *address = previous_value;
-       flush_tlb_all();
-       control_reg_value = __raw_readl(scratchpad_address
-                                       + OMAP343X_CONTROL_REG_VALUE_OFFSET);
-       /* This will enable caches and prediction */
-       set_cr(control_reg_value);
+       /* Read L2 AUX ctrl register */
+       asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+       *save++ = 1;
+       *save++ = val;
+}
+
+static int omap34xx_do_sram_idle(unsigned long save_state)
+{
+       omap34xx_cpu_suspend(save_state);
+       return 0;
 }
 
 void omap_sram_idle(void)
@@ -352,9 +343,6 @@ void omap_sram_idle(void)
        int core_prev_state, per_prev_state;
        u32 sdrc_pwr = 0;
 
-       if (!_omap_sram_idle)
-               return;
-
        pwrdm_clear_all_prev_pwrst(mpu_pwrdm);
        pwrdm_clear_all_prev_pwrst(neon_pwrdm);
        pwrdm_clear_all_prev_pwrst(core_pwrdm);
@@ -432,12 +420,16 @@ void omap_sram_idle(void)
                sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
        /*
-        * omap3_arm_context is the location where ARM registers
-        * get saved. The restore path then reads from this
-        * location and restores them back.
+        * omap3_arm_context is the location where some ARM context
+        * get saved. The rest is placed on the stack, and restored
+        * from there before resuming.
         */
-       _omap_sram_idle(omap3_arm_context, save_state);
-       cpu_init();
+       if (save_state)
+               omap34xx_save_context(omap3_arm_context);
+       if (save_state == 1 || save_state == 3)
+               cpu_suspend(save_state, omap34xx_do_sram_idle);
+       else
+               omap34xx_do_sram_idle(save_state);
 
        /* Restore normal SDRC POWER settings */
        if (omap_rev() >= OMAP3430_REV_ES3_0 &&
@@ -445,10 +437,6 @@ void omap_sram_idle(void)
            core_next_state == PWRDM_POWER_OFF)
                sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
-       /* Restore table entry modified during MMU restoration */
-       if (pwrdm_read_prev_pwrst(mpu_pwrdm) == PWRDM_POWER_OFF)
-               restore_table_entry();
-
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
                core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
@@ -846,10 +834,17 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
        return 0;
 }
 
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
 void omap_push_sram_idle(void)
 {
-       _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
-                                       omap34xx_cpu_suspend_sz);
+       omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
+
        if (omap_type() != OMAP2_DEVICE_TYPE_GP)
                _omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
                                save_secure_ram_context_sz);
@@ -914,7 +909,6 @@ static int __init omap3_pm_init(void)
        per_clkdm = clkdm_lookup("per_clkdm");
        core_clkdm = clkdm_lookup("core_clkdm");
 
-       omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
        suspend_set_ops(&omap_pm_ops);
 #endif /* CONFIG_SUSPEND */