]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'omap-pm-v3.10/cleanup/pm' of git://git.kernel.org/pub/scm/linux/kernel...
authorTony Lindgren <tony@atomide.com>
Thu, 16 May 2013 15:27:49 +0000 (08:27 -0700)
committerTony Lindgren <tony@atomide.com>
Thu, 16 May 2013 15:27:49 +0000 (08:27 -0700)
OMAP PM cleanups for v3.10

arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/omap-headsmp.S
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/pm44xx.c

index d555cf2459e14184f98d2e07590e476970e4df16..7d95bb053b93c07db84375a11d246c6ed1bab216 100644 (file)
@@ -237,8 +237,8 @@ extern void omap_do_wfi(void);
 
 #ifdef CONFIG_SMP
 /* Needed for secondary core boot */
-extern void omap_secondary_startup(void);
-extern void omap_secondary_startup_4460(void);
+extern void omap4_secondary_startup(void);
+extern void omap4460_secondary_startup(void);
 extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
 extern void omap_auxcoreboot_addr(u32 cpu_addr);
 extern u32 omap_read_auxcoreboot0(void);
index 0ea09faf327b2faa48d1889d63cc49246ee9eb37..4ea308114165689e1638eca94f1099d436cce803 100644 (file)
@@ -49,7 +49,7 @@ END(omap5_secondary_startup)
  * The primary core will update this flag using a hardware
  * register AuxCoreBoot0.
  */
-ENTRY(omap_secondary_startup)
+ENTRY(omap4_secondary_startup)
 hold:  ldr     r12,=0x103
        dsb
        smc     #0                      @ read from AuxCoreBoot0
@@ -64,9 +64,9 @@ hold: ldr     r12,=0x103
         * should now contain the SVC stack for this core
         */
        b       secondary_startup
-ENDPROC(omap_secondary_startup)
+ENDPROC(omap4_secondary_startup)
 
-ENTRY(omap_secondary_startup_4460)
+ENTRY(omap4460_secondary_startup)
 hold_2:        ldr     r12,=0x103
        dsb
        smc     #0                      @ read from AuxCoreBoot0
@@ -101,4 +101,4 @@ hold_2:     ldr     r12,=0x103
         * should now contain the SVC stack for this core
         */
        b       secondary_startup
-ENDPROC(omap_secondary_startup_4460)
+ENDPROC(omap4460_secondary_startup)
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;
 }
 
index 2a551f997aea526a5ac8367271f62e953d4d8609..98a11463a843afdaca3ef99680e0a7c785d5fc33 100644 (file)
@@ -87,7 +87,7 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
 
        /*
         * Update the AuxCoreBoot0 with boot state for secondary core.
-        * omap_secondary_startup() routine will hold the secondary core till
+        * omap4_secondary_startup() routine will hold the secondary core till
         * the AuxCoreBoot1 register is updated with cpu state
         * A barrier is added to ensure that write buffer is drained
         */
@@ -200,7 +200,7 @@ static void __init omap4_smp_init_cpus(void)
 
 static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
 {
-       void *startup_addr = omap_secondary_startup;
+       void *startup_addr = omap4_secondary_startup;
        void __iomem *base = omap_get_wakeupgen_base();
 
        /*
@@ -211,7 +211,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
                scu_enable(scu_base);
 
        if (cpu_is_omap446x()) {
-               startup_addr = omap_secondary_startup_4460;
+               startup_addr = omap4460_secondary_startup;
                pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
        }
 
index a251f87fa2a2d08145d5e403e43705f988fa0c9a..82f0698933d85a5715282378736de84fa16ebad6 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * OMAP4 Power Management Routines
+ * OMAP4+ Power Management Routines
  *
- * Copyright (C) 2010-2011 Texas Instruments, Inc.
+ * Copyright (C) 2010-2013 Texas Instruments, Inc.
  * Rajendra Nayak <rnayak@ti.com>
  * Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
@@ -135,16 +135,16 @@ static void omap_default_idle(void)
 }
 
 /**
- * omap4_pm_init - Init routine for OMAP4 PM
+ * omap4_init_static_deps - Add OMAP4 static dependencies
  *
- * Initializes all powerdomain and clockdomain target states
- * and all PRCM settings.
+ * Add needed static clockdomain dependencies on OMAP4 devices.
+ * Return: 0 on success or 'err' on failures
  */
-int __init omap4_pm_init(void)
+static inline int omap4_init_static_deps(void)
 {
-       int ret;
        struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm;
        struct clockdomain *ducati_clkdm, *l3_2_clkdm;
+       int ret = 0;
 
        if (omap_rev() == OMAP4430_REV_ES1_0) {
                WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
@@ -163,7 +163,7 @@ int __init omap4_pm_init(void)
        ret = pwrdm_for_each(pwrdms_setup, NULL);
        if (ret) {
                pr_err("Failed to setup powerdomains\n");
-               goto err2;
+               return ret;
        }
 
        /*
@@ -171,6 +171,10 @@ int __init omap4_pm_init(void)
         * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
         * expected. The hardware recommendation is to enable static
         * dependencies for these to avoid system lock ups or random crashes.
+        * The L4 wakeup depedency is added to workaround the OCP sync hardware
+        * BUG with 32K synctimer which lead to incorrect timer value read
+        * from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which
+        * are part of L4 wakeup clockdomain.
         */
        mpuss_clkdm = clkdm_lookup("mpuss_clkdm");
        emif_clkdm = clkdm_lookup("l3_emif_clkdm");
@@ -179,7 +183,7 @@ int __init omap4_pm_init(void)
        ducati_clkdm = clkdm_lookup("ducati_clkdm");
        if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
                (!l3_2_clkdm) || (!ducati_clkdm))
-               goto err2;
+               return -EINVAL;
 
        ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
        ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
@@ -188,9 +192,42 @@ int __init omap4_pm_init(void)
        ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
        if (ret) {
                pr_err("Failed to add MPUSS -> L3/EMIF/L4PER, DUCATI -> L3 wakeup dependency\n");
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+/**
+ * omap4_pm_init - Init routine for OMAP4+ devices
+ *
+ * Initializes all powerdomain and clockdomain target states
+ * and all PRCM settings.
+ * Return: Returns the error code returned by called functions.
+ */
+int __init omap4_pm_init(void)
+{
+       int ret = 0;
+
+       if (omap_rev() == OMAP4430_REV_ES1_0) {
+               WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
+               return -ENODEV;
+       }
+
+       pr_info("Power Management for TI OMAP4+ devices.\n");
+
+       ret = pwrdm_for_each(pwrdms_setup, NULL);
+       if (ret) {
+               pr_err("Failed to setup powerdomains.\n");
                goto err2;
        }
 
+       if (cpu_is_omap44xx()) {
+               ret = omap4_init_static_deps();
+               if (ret)
+                       goto err2;
+       }
+
        ret = omap4_mpuss_init();
        if (ret) {
                pr_err("Failed to initialise OMAP4 MPUSS\n");
@@ -206,7 +243,8 @@ int __init omap4_pm_init(void)
        /* Overwrite the default cpu_do_idle() */
        arm_pm_idle = omap_default_idle;
 
-       omap4_idle_init();
+       if (cpu_is_omap44xx())
+               omap4_idle_init();
 
 err2:
        return ret;