]> git.kernelconcepts.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

1  2 
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/pm44xx.c

index d555cf2459e14184f98d2e07590e476970e4df16,1a568482a107a39e04db96e08110a9379a8fec42..7d95bb053b93c07db84375a11d246c6ed1bab216
@@@ -82,7 -82,8 +82,7 @@@ extern void omap2_init_common_infrastru
  extern void omap2_sync32k_timer_init(void);
  extern void omap3_sync32k_timer_init(void);
  extern void omap3_secure_sync32k_timer_init(void);
 -extern void omap3_gp_gptimer_timer_init(void);
 -extern void omap3_am33xx_gptimer_timer_init(void);
 +extern void omap3_gptimer_timer_init(void);
  extern void omap4_local_timer_init(void);
  extern void omap5_realtime_timer_init(void);
  
@@@ -109,14 -110,6 +109,14 @@@ void am35xx_init_late(void)
  void ti81xx_init_late(void);
  int omap2_common_pm_late_init(void);
  
 +#ifdef CONFIG_SOC_BUS
 +void omap_soc_device_init(void);
 +#else
 +static inline void omap_soc_device_init(void)
 +{
 +}
 +#endif
 +
  #if defined(CONFIG_SOC_OMAP2420) || defined(CONFIG_SOC_OMAP2430)
  void omap2xxx_restart(char mode, const char *cmd);
  #else
@@@ -237,8 -230,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);
@@@ -256,6 -249,7 +256,6 @@@ extern int omap4_enter_lowpower(unsigne
  extern int omap4_finish_suspend(unsigned long cpu_state);
  extern void omap4_cpu_resume(void);
  extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
 -extern u32 omap4_mpuss_read_prev_context_state(void);
  #else
  static inline int omap4_enter_lowpower(unsigned int cpu,
                                        unsigned int power_state)
@@@ -283,6 -277,10 +283,6 @@@ static inline int omap4_finish_suspend(
  static inline void omap4_cpu_resume(void)
  {}
  
 -static inline u32 omap4_mpuss_read_prev_context_state(void)
 -{
 -      return 0;
 -}
  #endif
  
  struct omap_sdrc_params;
@@@ -295,8 -293,5 +295,8 @@@ extern void omap_reserve(void)
  struct omap_hwmod;
  extern int omap_dss_reset(struct omap_hwmod *);
  
 +/* SoC specific clock initializer */
 +extern int (*omap_clk_init)(void);
 +
  #endif /* __ASSEMBLER__ */
  #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
index e80327b6c81f68520206e10058e7e4c18cc496ae,d4322aa3192e3869f5ea2b82f0bb9cf169ad0927..f993a41887010f726e7bee233f3bb80754cc4a47
@@@ -71,10 -71,43 +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.
@@@ -139,6 -172,20 +172,6 @@@ static inline void cpu_clear_prev_logic
        }
  }
  
 -/**
 - * omap4_mpuss_read_prev_context_state:
 - * Function returns the MPUSS previous context state
 - */
 -u32 omap4_mpuss_read_prev_context_state(void)
 -{
 -      u32 reg;
 -
 -      reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
 -              OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
 -      reg &= OMAP4430_LOSTCONTEXT_DFF_MASK;
 -      return reg;
 -}
 -
  /*
   * Store the CPU cluster state for L2X0 low power operations.
   */
@@@ -158,11 -205,12 +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 -273,17 +259,17 @@@ int omap4_enter_lowpower(unsigned int c
  
        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 -319,14 +305,14 @@@ int __cpuinit omap4_hotplug_cpu(unsigne
        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 -370,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) {
  
        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,5b201653ca32f7dabced0fb34bb459a85404e9bd..98a11463a843afdaca3ef99680e0a7c785d5fc33
@@@ -65,6 -65,13 +65,6 @@@ static void __cpuinit omap4_secondary_i
                omap_secure_dispatcher(OMAP4_PPA_CPU_ACTRL_SMP_INDEX,
                                                        4, 0, 0, 0, 0, 0);
  
 -      /*
 -       * If any interrupts are already enabled for the primary
 -       * core (e.g. timer irq), then they will not have been enabled
 -       * for us: do so
 -       */
 -      gic_secondary_init(0);
 -
        /*
         * Synchronise with the boot thread.
         */
@@@ -76,7 -83,6 +76,7 @@@ static int __cpuinit omap4_boot_seconda
  {
        static struct clockdomain *cpu1_clkdm;
        static bool booted;
 +      static struct powerdomain *cpu1_pwrdm;
        void __iomem *base = omap_get_wakeupgen_base();
  
        /*
@@@ -87,7 -93,7 +87,7 @@@
  
        /*
         * 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
         */
        else
                __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0);
  
 -      if (!cpu1_clkdm)
 +      if (!cpu1_clkdm && !cpu1_pwrdm) {
                cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
 +              cpu1_pwrdm = pwrdm_lookup("cpu1_pwrdm");
 +      }
  
        /*
         * The SGI(Software Generated Interrupts) are not wakeup capable
         * Section :
         *      4.3.4.2 Power States of CPU0 and CPU1
         */
 -      if (booted) {
 +      if (booted && cpu1_pwrdm && cpu1_clkdm) {
                /*
                 * GIC distributor control register has changed between
                 * CortexA9 r1pX and r2pX. The Control Register secure
                        gic_dist_disable();
                }
  
 +              /*
 +               * Ensure that CPU power state is set to ON to avoid CPU
 +               * powerdomain transition on wfi
 +               */
                clkdm_wakeup(cpu1_clkdm);
 +              omap_set_pwrdm_state(cpu1_pwrdm, PWRDM_POWER_ON);
                clkdm_allow_idle(cpu1_clkdm);
  
                if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
@@@ -174,7 -173,7 +174,7 @@@ static void __init omap4_smp_init_cpus(
        unsigned int i = 0, ncores = 1, cpu_id;
  
        /* Use ARM cpuid check here, as SoC detection will not work so early */
 -      cpu_id = read_cpuid(CPUID_ID) & CPU_MASK;
 +      cpu_id = read_cpuid_id() & CPU_MASK;
        if (cpu_id == CPU_CORTEX_A9) {
                /*
                 * Currently we can't call ioremap here because
  
  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();
  
        /*
                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,228deca8fb938a65a9bddce28c1b23992e4a8b21..82f0698933d85a5715282378736de84fa16ebad6
@@@ -1,7 -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>
   *
@@@ -126,8 -126,8 +126,8 @@@ static int __init pwrdms_setup(struct p
   * omap_default_idle - OMAP4 default ilde routine.'
   *
   * Implements OMAP4 memory, IO ordering requirements which can't be addressed
 - * with default cpu_do_idle() hook. Used by all CPUs with !CONFIG_CPUIDLE and
 - * by secondary CPU with CONFIG_CPUIDLE.
 + * with default cpu_do_idle() hook. Used by all CPUs with !CONFIG_CPU_IDLE and
 + * by secondary CPU with CONFIG_CPU_IDLE.
   */
  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");
        ret = pwrdm_for_each(pwrdms_setup, NULL);
        if (ret) {
                pr_err("Failed to setup powerdomains\n");
-               goto err2;
+               return ret;
        }
  
        /*
         * 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");
        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);
        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");
        /* 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;