Merge tag 'omap-pm-v3.10/cleanup/pm' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / arch / arm / mach-omap2 / omap-mpuss-lowpower.c
index e80327b6c81f68520206e10058e7e4c18cc496ae..f993a41887010f726e7bee233f3bb80754cc4a47 100644 (file)
@@ -71,10 +71,43 @@ struct omap4_cpu_pm_info {
        void (*secondary_startup)(void);
 };
 
+/**
+ * struct cpu_pm_ops - CPU pm operations
+ * @finish_suspend:    CPU suspend finisher function pointer
+ * @resume:            CPU resume function pointer
+ * @scu_prepare:       CPU Snoop Control program function pointer
+ *
+ * Structure holds functions pointer for CPU low power operations like
+ * suspend, resume and scu programming.
+ */
+struct cpu_pm_ops {
+       int (*finish_suspend)(unsigned long cpu_state);
+       void (*resume)(void);
+       void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state);
+};
+
 static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
 static struct powerdomain *mpuss_pd;
 static void __iomem *sar_base;
 
+static int default_finish_suspend(unsigned long cpu_state)
+{
+       omap_do_wfi();
+       return 0;
+}
+
+static void dummy_cpu_resume(void)
+{}
+
+static void dummy_scu_prepare(unsigned int cpu_id, unsigned int cpu_state)
+{}
+
+struct cpu_pm_ops omap_pm_ops = {
+       .finish_suspend         = default_finish_suspend,
+       .resume                 = dummy_cpu_resume,
+       .scu_prepare            = dummy_scu_prepare,
+};
+
 /*
  * Program the wakeup routine address for the CPU0 and CPU1
  * used for OFF or DORMANT wakeup.
@@ -158,11 +191,12 @@ static void save_l2x0_context(void)
 {
        u32 val;
        void __iomem *l2x0_base = omap4_get_l2cache_base();
-
-       val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
-       __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
-       val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
-       __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
+       if (l2x0_base) {
+               val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
+               __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
+               val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
+               __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
+       }
 }
 #else
 static void save_l2x0_context(void)
@@ -225,14 +259,17 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 
        cpu_clear_prev_logic_pwrst(cpu);
        pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
-       set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
-       scu_pwrst_prepare(cpu, power_state);
+       set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume));
+       omap_pm_ops.scu_prepare(cpu, power_state);
        l2x0_pwrst_prepare(cpu, save_state);
 
        /*
         * Call low level function  with targeted low power state.
         */
-       cpu_suspend(save_state, omap4_finish_suspend);
+       if (save_state)
+               cpu_suspend(save_state, omap_pm_ops.finish_suspend);
+       else
+               omap_pm_ops.finish_suspend(save_state);
 
        /*
         * Restore the CPUx power state to ON otherwise CPUx
@@ -268,14 +305,14 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
        pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
        pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
        set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
-       scu_pwrst_prepare(cpu, power_state);
+       omap_pm_ops.scu_prepare(cpu, power_state);
 
        /*
         * CPU never retuns back if targeted power state is OFF mode.
         * CPU ONLINE follows normal CPU ONLINE ptah via
-        * omap_secondary_startup().
+        * omap4_secondary_startup().
         */
-       omap4_finish_suspend(cpu_state);
+       omap_pm_ops.finish_suspend(cpu_state);
 
        pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
        return 0;
@@ -319,9 +356,9 @@ int __init omap4_mpuss_init(void)
        pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
        pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
        if (cpu_is_omap446x())
-               pm_info->secondary_startup = omap_secondary_startup_4460;
+               pm_info->secondary_startup = omap4460_secondary_startup;
        else
-               pm_info->secondary_startup = omap_secondary_startup;
+               pm_info->secondary_startup = omap4_secondary_startup;
 
        pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
        if (!pm_info->pwrdm) {
@@ -352,6 +389,12 @@ int __init omap4_mpuss_init(void)
 
        save_l2x0_context();
 
+       if (cpu_is_omap44xx()) {
+               omap_pm_ops.finish_suspend = omap4_finish_suspend;
+               omap_pm_ops.resume = omap4_cpu_resume;
+               omap_pm_ops.scu_prepare = scu_pwrst_prepare;
+       }
+
        return 0;
 }