]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/kernel-video.git/commitdiff
Merge branch 'am33xx-pm-linux-3.8.y' into pm-linux-3.8.y
authorTero Kristo <t-kristo@ti.com>
Wed, 13 Mar 2013 16:40:52 +0000 (18:40 +0200)
committerTero Kristo <t-kristo@ti.com>
Wed, 13 Mar 2013 16:40:52 +0000 (18:40 +0200)
Conflicts:
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/clockdomain.h
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/cpuidle_omap4plus.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/sram.c
drivers/memory/emif.c

Signed-off-by: Tero Kristo <t-kristo@ti.com>
26 files changed:
1  2 
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/clockdomain.h
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/cpuidle_omap4plus.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap-hotplug.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm33xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm_omap4plus.c
arch/arm/mach-omap2/powerdomain.h
arch/arm/mach-omap2/sram.c
arch/arm/mach-omap2/sram.h
arch/arm/mach-omap2/timer.c
drivers/memory/emif.c

Simple merge
index 8bae809892241990fd512962ff11f244f560373b,222e19649b37681eb7b2dd2948af34c2b9b1ab80..6f254780c1b31cfe98be9a53db1d2032451b7314
@@@ -80,8 -79,9 +80,9 @@@ omap4plus-common-pm                   =  omap-mpuss-low
  obj-$(CONFIG_ARCH_OMAP2)              += pm24xx.o
  obj-$(CONFIG_ARCH_OMAP2)              += sleep24xx.o
  obj-$(CONFIG_ARCH_OMAP3)              += pm34xx.o sleep34xx.o
 -obj-$(CONFIG_ARCH_OMAP4)              += pm44xx.o omap-mpuss-lowpower.o
 -obj-$(CONFIG_SOC_OMAP5)                       += omap-mpuss-lowpower.o
 +obj-$(CONFIG_ARCH_OMAP4)              += $(omap4plus-common-pm)
 +obj-$(CONFIG_SOC_OMAP5)                       += $(omap4plus-common-pm)
+ obj-$(CONFIG_SOC_AM33XX)              += pm33xx.o sleep33xx.o
  obj-$(CONFIG_PM_DEBUG)                        += pm-debug.o
  
  obj-$(CONFIG_POWER_AVS_OMAP)          += sr_device.o
Simple merge
index 4d7aeeb4305360e863ce1985fba462483663db9a,95e473beec6c8ccab82b1b4b1f3f5a4a5967034e..aa800679c80a2f3fa224665ca87b016c924a6fc6
@@@ -214,9 -216,9 +216,10 @@@ extern void __init omap243x_clockdomain
  extern void __init omap3xxx_clockdomains_init(void);
  extern void __init am33xx_clockdomains_init(void);
  extern void __init omap44xx_clockdomains_init(void);
- extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
- extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
 +extern void __init omap54xx_clockdomains_init(void);
+ extern void clkdm_add_autodeps(struct clockdomain *clkdm);
+ extern void clkdm_del_autodeps(struct clockdomain *clkdm);
  
  extern struct clkdm_ops omap2_clkdm_operations;
  extern struct clkdm_ops omap3_clkdm_operations;
index da19c42f7aa9f1712f3c9a04c69f99a14a3b1a0b,73cac5c884ee152933d7bf7ae2c95035aeac1683..d97648adb0eb0224c58fcdc83bb1ed8106cd1ffe
@@@ -106,9 -115,10 +115,10 @@@ void omap2430_init_late(void)
  void omap3430_init_late(void);
  void omap35xx_init_late(void);
  void omap3630_init_late(void);
+ void am33xx_init_late(void);
  void am35xx_init_late(void);
  void ti81xx_init_late(void);
 -void omap4430_init_late(void);
 +void omap5_init_late(void);
  int omap2_common_pm_late_init(void);
  
  #if defined(CONFIG_SOC_OMAP2420) || defined(CONFIG_SOC_OMAP2430)
@@@ -238,13 -248,13 +248,12 @@@ extern void omap5_secondary_startup(voi
  
  #if defined(CONFIG_SMP) && defined(CONFIG_PM)
  extern int omap4_mpuss_init(void);
- extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
+ extern int omap4_mpuss_enter_lowpower(unsigned int cpu, u8 fpwrst);
  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 int omap4_mpuss_hotplug_cpu(unsigned int cpu, u8 fpwrst);
 -extern u32 omap4_mpuss_read_prev_context_state(void);
  #else
- static inline int omap4_enter_lowpower(unsigned int cpu,
-                                       unsigned int power_state)
+ static inline int omap4_mpuss_enter_lowpower(unsigned int cpu, u8 fpwrst)
  {
        cpu_do_idle();
        return 0;
Simple merge
index f61b28c21dc841757de8183bc99abcf8299b6b1f,a8e6263774353a84ca2c288f768846bb3986e4f6..41652015fda9e03d0ad8da61272a5219b37d291d
@@@ -80,11 -106,9 +106,7 @@@ static int __omap3_enter_idle(struct cp
                                int index)
  {
        struct omap3_idle_statedata *cx = &omap3_idle_data[index];
-       u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
-       pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-       pwrdm_set_next_pwrst(core_pd, core_state);
  
 -      local_fiq_disable();
 -
        if (omap_irq_pending() || need_resched())
                goto return_sleep_time;
  
                cpu_pm_exit();
  
        /* Re-allow idle for C1 */
-       if (index == 0) {
+       if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE)
                clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
-               clkdm_allow_idle(core_pd->pwrdm_clkdms[0]);
-       }
  
  return_sleep_time:
 -      local_fiq_enable();
--
        return index;
  }
  
index 8681fa6b8a5b9861904755c7b52eecf2fabed8d6,2cb53325363b81c8259aa22797a0485ca0e66f31..9ebeed6923c2258f0b2f62927f63d8e5a7127e55
  #include "pm.h"
  #include "prm.h"
  #include "clockdomain.h"
 +#include "soc.h"
  
  /* Machine specific information */
 -struct omap4_idle_statedata {
 +struct idle_statedata {
-       u32 cpu_state;
-       u32 mpu_logic_state;
-       u32 mpu_state;
+       u8 cpu_pwrst;
+       u8 mpu_pwrst;
 +      u32 mpu_state_vote;
  };
  
 -static struct omap4_idle_statedata omap4_idle_data[] = {
 +static struct idle_statedata omap4_idle_data[] = {
        {
-               .cpu_state = PWRDM_POWER_ON,
-               .mpu_state = PWRDM_POWER_ON,
-               .mpu_logic_state = PWRDM_POWER_RET,
+               .cpu_pwrst = PWRDM_FUNC_PWRST_ON,
+               .mpu_pwrst = PWRDM_FUNC_PWRST_ON,
        },
        {
-               .cpu_state = PWRDM_POWER_OFF,
-               .mpu_state = PWRDM_POWER_RET,
-               .mpu_logic_state = PWRDM_POWER_RET,
+               .cpu_pwrst = PWRDM_FUNC_PWRST_OFF,
+               .mpu_pwrst = PWRDM_FUNC_PWRST_CSWR,
        },
        {
-               .cpu_state = PWRDM_POWER_OFF,
-               .mpu_state = PWRDM_POWER_RET,
-               .mpu_logic_state = PWRDM_POWER_OFF,
+               .cpu_pwrst = PWRDM_FUNC_PWRST_OFF,
+               .mpu_pwrst = PWRDM_FUNC_PWRST_OSWR,
        },
  };
  
-               .cpu_state = PWRDM_POWER_ON,
-               .mpu_state = PWRDM_POWER_ON,
-               .mpu_logic_state = PWRDM_POWER_RET,
 +static struct idle_statedata omap5_idle_data[] = {
 +      {
-               .cpu_state = PWRDM_POWER_RET,
-               .mpu_state = PWRDM_POWER_RET,
-               .mpu_logic_state = PWRDM_POWER_RET,
++              .cpu_pwrst = PWRDM_FUNC_PWRST_ON,
++              .mpu_pwrst = PWRDM_FUNC_PWRST_ON,
 +      },
 +      {
-               .cpu_state = PWRDM_POWER_OFF,
-               .mpu_state = PWRDM_POWER_RET,
-               .mpu_logic_state = PWRDM_POWER_OFF,
++              .cpu_pwrst = PWRDM_FUNC_PWRST_CSWR,
++              .mpu_pwrst = PWRDM_FUNC_PWRST_CSWR,
 +      },
 +      {
++              .cpu_pwrst = PWRDM_FUNC_PWRST_OFF,
++              .mpu_pwrst = PWRDM_FUNC_PWRST_OSWR,
 +      },
 +};
 +
  static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS];
  static struct clockdomain *cpu_clkdm[NR_CPUS];
  
@@@ -135,8 -114,7 +128,7 @@@ static int omap_enter_idle_coupled(stru
        cpu_pm_enter();
  
        if (dev->cpu == 0) {
-               pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
-               omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
 -              WARN_ON(pwrdm_set_fpwrst(mpu_pd, cx->mpu_pwrst));
++              WARN_ON(pwrdm_set_next_fpwrst(mpu_pd, cx->mpu_pwrst));
  
                /*
                 * Call idle CPU cluster PM enter notifier chain
  
        /* Wakeup CPU1 only if it is not offlined */
        if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {
-               omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON);
 +              /* Restore MPU PD state post idle */
++              pwrdm_set_next_fpwrst(mpu_pd, PWRDM_FUNC_PWRST_ON);
                clkdm_wakeup(cpu_clkdm[1]);
-               omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON);
++              pwrdm_set_next_fpwrst(cpu_pd[1], PWRDM_FUNC_PWRST_ON);
                clkdm_allow_idle(cpu_clkdm[1]);
        }
  
         * Call idle CPU cluster PM exit notifier chain
         * to restore GIC and wakeupgen context.
         */
-       if ((cx->mpu_state == PWRDM_POWER_RET) &&
-               (cx->mpu_logic_state == PWRDM_POWER_OFF))
 -      if (omap4_mpuss_read_prev_context_state())
++      if (cx->mpu_pwrst == PWRDM_FUNC_PWRST_OSWR)
                cpu_cluster_pm_exit();
  
        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
@@@ -179,36 -152,7 +169,36 @@@ fail
        cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
        cpu_done[dev->cpu] = false;
  
 -      local_fiq_enable();
 +      return index;
 +}
 +
 +static int omap_enter_idle_smp(struct cpuidle_device *dev,
 +                      struct cpuidle_driver *drv,
 +                      int index)
 +{
 +      struct idle_statedata *cx = state_ptr + index;
 +      int cpu_id = smp_processor_id();
 +      unsigned long flag;
 +
 +      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
 +
 +      raw_spin_lock_irqsave(&mpu_lock, flag);
 +      cx->mpu_state_vote++;
-       if (cx->mpu_state_vote == num_online_cpus()) {
-               pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
-               omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
-       }
++      if (cx->mpu_state_vote == num_online_cpus())
++              pwrdm_set_next_fpwrst(mpu_pd, cx->mpu_pwrst);
++
 +      raw_spin_unlock_irqrestore(&mpu_lock, flag);
 +
-       omap4_enter_lowpower(dev->cpu, cx->cpu_state);
++      omap4_mpuss_enter_lowpower(dev->cpu, cx->cpu_pwrst);
 +
 +      raw_spin_lock_irqsave(&mpu_lock, flag);
 +      if (cx->mpu_state_vote == num_online_cpus())
-               omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON);
++              pwrdm_set_next_fpwrst(mpu_pd, PWRDM_FUNC_PWRST_ON);
++
 +      cx->mpu_state_vote--;
 +      raw_spin_unlock_irqrestore(&mpu_lock, flag);
 +
 +      clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
  
        return index;
  }
Simple merge
Simple merge
index 0ccb76eaf2041c9fb75f51b4ef336014a982b58b,9acd52a79d14459efd0de5c1ff0fb5b7de94b1a0..eb1b6e00050b90f48a6d4fb7390acc9183bc80f6
@@@ -72,41 -71,9 +72,41 @@@ struct omap4_cpu_pm_info 
        void (*secondary_startup)(void);
  };
  
-       void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state);
 +struct cpu_pm_ops {
 +      int (*finish_suspend)(unsigned long cpu_state);
 +      void (*resume)(void);
++      void (*scu_prepare)(unsigned int cpu_id, u8 cpu_state);
 +      void (*hotplug_restart)(void);
 +};
 +
 +extern int omap4_finish_suspend(unsigned long cpu_state);
 +extern void omap4_cpu_resume(void);
 +extern int omap5_finish_suspend(unsigned long cpu_state);
 +extern void omap5_cpu_resume(void);
 +
  static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
  static struct powerdomain *mpuss_pd;
  static void __iomem *sar_base;
- void dummy_scu_prepare(unsigned int cpu_id, unsigned int cpu_state)
 +static u32 cpu_context_offset, cpu_cswr_supported;
 +
 +static int default_finish_suspend(unsigned long cpu_state)
 +{
 +      omap_do_wfi();
 +      return 0;
 +}
 +
 +static void dummy_cpu_resume(void)
 +{}
 +
++void dummy_scu_prepare(unsigned int cpu_id, u8 cpu_state)
 +{}
 +
 +struct cpu_pm_ops omap_pm_ops = {
 +      .finish_suspend         = default_finish_suspend,
 +      .resume                 = dummy_cpu_resume,
 +      .scu_prepare            = dummy_scu_prepare,
 +      .hotplug_restart        = dummy_cpu_resume,
 +};
  
  /*
   * Program the wakeup routine address for the CPU0 and CPU1
@@@ -256,19 -219,16 +239,20 @@@ int omap4_mpuss_enter_lowpower(unsigne
        if (omap_rev() == OMAP4430_REV_ES1_0)
                return -ENXIO;
  
-       switch (power_state) {
-       case PWRDM_POWER_ON:
-       case PWRDM_POWER_INACTIVE:
+       switch (fpwrst) {
+       case PWRDM_FUNC_PWRST_ON:
+       case PWRDM_FUNC_PWRST_INACTIVE:
                save_state = 0;
                break;
-       case PWRDM_POWER_OFF:
+       case PWRDM_FUNC_PWRST_OFF:
                save_state = 1;
                break;
-       case PWRDM_POWER_RET:
+       case PWRDM_FUNC_PWRST_CSWR:
+       case PWRDM_FUNC_PWRST_OSWR:
 +              if (cpu_cswr_supported) {
 +                      save_state = 0;
 +                      break;
 +              }
        default:
                /*
                 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
                save_state = 2;
  
        cpu_clear_prev_logic_pwrst(cpu);
-       set_cpu_next_pwrst(cpu, power_state);
+       WARN_ON(pwrdm_set_next_fpwrst(pm_info->pwrdm, fpwrst));
 -      set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
 -      scu_pwrst_prepare(cpu, fpwrst);
 +      set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume));
-       omap_pm_ops.scu_prepare(cpu, power_state);
++      omap_pm_ops.scu_prepare(cpu, fpwrst);
        l2x0_pwrst_prepare(cpu, save_state);
  
        /*
         * domain transition
         */
        wakeup_cpu = smp_processor_id();
-       set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 -      WARN_ON(pwrdm_set_next_fpwrst(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON));
  
        pwrdm_post_transition(NULL);
  
++      WARN_ON(pwrdm_set_next_fpwrst(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON));
++
        return 0;
  }
  
@@@ -332,22 -289,22 +317,22 @@@ int __cpuinit omap4_mpuss_hotplug_cpu(u
        if (omap_rev() == OMAP4430_REV_ES1_0)
                return -ENXIO;
  
-       if (power_state == PWRDM_POWER_OFF)
+       if (fpwrst == PWRDM_FUNC_PWRST_OFF || fpwrst == PWRDM_FUNC_PWRST_OSWR)
                cpu_state = 1;
  
-       clear_cpu_prev_pwrst(cpu);
-       set_cpu_next_pwrst(cpu, power_state);
+       pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
+       WARN_ON(pwrdm_set_next_fpwrst(pm_info->pwrdm, fpwrst));
 -      set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
 -      scu_pwrst_prepare(cpu, fpwrst);
 +      set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart));
-       omap_pm_ops.scu_prepare(cpu, power_state);
++      omap_pm_ops.scu_prepare(cpu, fpwrst);
  
        /*
         * CPU never retuns back if targeted power state is OFF mode.
         * CPU ONLINE follows normal CPU ONLINE ptah via
         * omap_secondary_startup().
         */
 -      omap4_finish_suspend(cpu_state);
 +      omap_pm_ops.finish_suspend(cpu_state);
  
-       set_cpu_next_pwrst(cpu, PWRDM_POWER_ON);
+       WARN_ON(pwrdm_set_next_fpwrst(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON));
        return 0;
  }
  
@@@ -401,16 -339,16 +386,16 @@@ int __init omap4_mpuss_init(void
        cpu_clear_prev_logic_pwrst(0);
  
        /* Initialise CPU0 power domain state to ON */
-       pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
+       WARN_ON(pwrdm_set_next_fpwrst(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON));
  
 +      if (cpu_is_omap44xx())
 +              cpu_wakeup_addr = CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
 +      else if (soc_is_omap54xx())
 +              cpu_wakeup_addr = OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
        pm_info = &per_cpu(omap4_pm_info, 0x1);
        pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
 -      pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
 +      pm_info->wkup_sar_addr = sar_base + cpu_wakeup_addr;
        pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
 -      if (cpu_is_omap446x())
 -              pm_info->secondary_startup = omap_secondary_startup_4460;
 -      else
 -              pm_info->secondary_startup = omap_secondary_startup;
  
        pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
        if (!pm_info->pwrdm) {
index ba63b14ca12ca40c450a587d90a31dd13457f41a,cd42d921940dcdb1dd91de67bb56b0350e2b442a..ef0bcce60580979459a444b6d2faca0684852a0f
@@@ -140,12 -141,7 +140,12 @@@ static int __cpuinit omap4_boot_seconda
                        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);
++              pwrdm_set_next_fpwrst(cpu1_pwrdm, PWRDM_FUNC_PWRST_ON);
                clkdm_allow_idle(cpu1_clkdm);
  
                if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
Simple merge
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,ae1bdb2496adfd37178664a6e96be8ea85949007..93f970f7cb40969bd8a021851785b16f2e4ba2bf
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,469 +1,469 @@@
 -              mailbox_msg_rx_flush(wkup_m3->mbox);
+ /*
+  * AM33XX Power Management Routines
+  *
+  * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+  * Vaibhav Bedia <vaibhav.bedia@ti.com>
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License as
+  * published by the Free Software Foundation version 2.
+  *
+  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+  * kind, whether express or implied; without even the implied warranty
+  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  */
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/err.h>
+ #include <linux/firmware.h>
+ #include <linux/io.h>
+ #include <linux/platform_device.h>
+ #include <linux/sched.h>
+ #include <linux/suspend.h>
+ #include <linux/completion.h>
+ #include <linux/module.h>
+ #include <linux/mailbox.h>
+ #include <linux/interrupt.h>
+ #include <asm/suspend.h>
+ #include <asm/proc-fns.h>
+ #include <asm/sizes.h>
+ #include <asm/fncpy.h>
+ #include <asm/system_misc.h>
+ #include "pm.h"
+ #include "cm33xx.h"
+ #include "pm33xx.h"
+ #include "control.h"
+ #include "clockdomain.h"
+ #include "powerdomain.h"
+ #include "omap_hwmod.h"
+ #include "omap_device.h"
+ #include "soc.h"
+ #include "sram.h"
+ void (*am33xx_do_wfi_sram)(void);
+ static void __iomem *am33xx_emif_base;
+ static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm;
+ static struct clockdomain *gfx_l4ls_clkdm;
+ static struct omap_hwmod *usb_oh, *cpsw_oh, *tptc0_oh, *tptc1_oh, *tptc2_oh;
+ static struct wkup_m3_context *wkup_m3;
+ static DECLARE_COMPLETION(wkup_m3_sync);
+ #ifdef CONFIG_SUSPEND
+ static int am33xx_do_sram_idle(long unsigned int unused)
+ {
+       am33xx_do_wfi_sram();
+       return 0;
+ }
+ static int am33xx_pm_suspend(void)
+ {
+       int status, ret = 0;
+       /*
+        * By default the following IPs do not have MSTANDBY asserted
+        * which is necessary for PER domain transition. If the drivers
+        * are not compiled into the kernel HWMOD code will not change the
+        * state of the IPs if the IP was not never enabled. To ensure
+        * that there no issues with or without the drivers being compiled
+        * in the kernel, we forcefully put these IPs to idle.
+        */
+       omap_hwmod_enable(usb_oh);
+       omap_hwmod_enable(tptc0_oh);
+       omap_hwmod_enable(tptc1_oh);
+       omap_hwmod_enable(tptc2_oh);
+       omap_hwmod_enable(cpsw_oh);
+       omap_hwmod_idle(usb_oh);
+       omap_hwmod_idle(tptc0_oh);
+       omap_hwmod_idle(tptc1_oh);
+       omap_hwmod_idle(tptc2_oh);
+       omap_hwmod_idle(cpsw_oh);
+       /* Try to put GFX to sleep */
+       pwrdm_set_next_fpwrst(gfx_pwrdm, PWRDM_FUNC_PWRST_OFF);
+       ret = cpu_suspend(0, am33xx_do_sram_idle);
+       status = pwrdm_read_fpwrst(gfx_pwrdm);
+       if (status != PWRDM_FUNC_PWRST_OFF)
+               pr_err("GFX domain did not transition\n");
+       else
+               pr_info("GFX domain entered low power state\n");
+       /*
+        * GFX_L4LS clock domain needs to be woken up to
+        * ensure thet L4LS clock domain does not get stuck in transition
+        * If that happens L3 module does not get disabled, thereby leading
+        * to PER power domain transition failing
+        *
+        * The clock framework should take care of ensuring
+        * that the clock domain is in the right state when
+        * GFX driver is active.
+        */
+       clkdm_wakeup(gfx_l4ls_clkdm);
+       clkdm_sleep(gfx_l4ls_clkdm);
+       if (ret) {
+               pr_err("Kernel suspend failure\n");
+       } else {
+               status = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
+               status &= IPC_RESP_MASK;
+               status >>= __ffs(IPC_RESP_MASK);
+               switch (status) {
+               case 0:
+                       pr_info("Successfully put all powerdomains to target state\n");
+                       /*
+                        * XXX: Leads to loss of logic state in PER power domain
+                        * Use SOC specific ops for this?
+                        */
+                       break;
+               case 1:
+                       pr_err("Could not transition all powerdomains to target state\n");
+                       ret = -1;
+                       break;
+               default:
+                       pr_err("Something went wrong :(\nStatus = %d\n",
+                               status);
+                       ret = -1;
+               }
+       }
+       return ret;
+ }
+ static int am33xx_pm_enter(suspend_state_t suspend_state)
+ {
+       int ret = 0;
+       switch (suspend_state) {
+       case PM_SUSPEND_STANDBY:
+       case PM_SUSPEND_MEM:
+               ret = am33xx_pm_suspend();
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+ }
+ static int am33xx_pm_begin(suspend_state_t state)
+ {
+       int ret = 0;
+       struct mailbox_msg dummy_msg;
+       disable_hlt();
+       MAILBOX_FILL_MSG(dummy_msg, 0, 0xABCDABCD, 0);
+       wkup_m3->ipc_data.sleep_mode = IPC_CMD_DS0;
+       wkup_m3->ipc_data.param1  = DS_IPC_DEFAULT;
+       wkup_m3->ipc_data.param2  = DS_IPC_DEFAULT;
+       am33xx_wkup_m3_ipc_cmd(&wkup_m3->ipc_data);
+       wkup_m3->state = M3_STATE_MSG_FOR_LP;
+       mailbox_enable_irq(wkup_m3->mbox, IRQ_RX);
+       ret = mailbox_msg_send(wkup_m3->mbox, &dummy_msg);
+       if (ret) {
+               pr_err("A8<->CM3 MSG for LP failed\n");
+               am33xx_m3_state_machine_reset();
+               ret = -1;
+       }
+       /* Give some time to M3 to respond. 500msec is a random value here */
+       if (!wait_for_completion_timeout(&wkup_m3_sync,
+                                       msecs_to_jiffies(500))) {
+               pr_err("A8<->CM3 sync failure\n");
+               am33xx_m3_state_machine_reset();
+               ret = -1;
+       } else {
+               pr_debug("Message sent for entering DeepSleep mode\n");
+               mailbox_disable_irq(wkup_m3->mbox, IRQ_RX);
+       }
+       return ret;
+ }
+ static void am33xx_pm_end(void)
+ {
+       mailbox_enable_irq(wkup_m3->mbox, IRQ_RX);
+       am33xx_m3_state_machine_reset();
+       enable_hlt();
+       return;
+ }
+ static const struct platform_suspend_ops am33xx_pm_ops = {
+       .begin          = am33xx_pm_begin,
+       .end            = am33xx_pm_end,
+       .enter          = am33xx_pm_enter,
+       .valid          = suspend_valid_only_mem,
+ };
+ static void am33xx_m3_state_machine_reset(void)
+ {
+       int ret = 0;
+       struct mailbox_msg dummy_msg;
+       MAILBOX_FILL_MSG(dummy_msg, 0, 0xABCDABCD, 0);
+       wkup_m3->ipc_data.sleep_mode    = IPC_CMD_RESET;
+       wkup_m3->ipc_data.param1        = DS_IPC_DEFAULT;
+       wkup_m3->ipc_data.param2        = DS_IPC_DEFAULT;
+       am33xx_wkup_m3_ipc_cmd(&wkup_m3->ipc_data);
+       wkup_m3->state = M3_STATE_MSG_FOR_RESET;
+       ret = mailbox_msg_send(wkup_m3->mbox, &dummy_msg);
+       if (!ret) {
+               pr_debug("Message sent for resetting M3 state machine\n");
+               /* Give some to M3 to respond. 500msec is a random value here */
+               if (!wait_for_completion_timeout(&wkup_m3_sync,
+                                               msecs_to_jiffies(500)))
+                       pr_err("A8<->CM3 sync failure\n");
+       } else {
+               pr_err("Could not reset M3 state machine!!!\n");
+               wkup_m3->state = M3_STATE_UNKNOWN;
+       }
+ }
+ #endif /* CONFIG_SUSPEND */
+ /*
+  * Dummy notifier for the mailbox
+  * XXX: Get rid of this requirement once the MBX driver has been finalized
+  */
+ static int wkup_mbox_msg(struct notifier_block *self, unsigned long len,
+               void *msg)
+ {
+       return 0;
+ }
+ static struct notifier_block wkup_mbox_notifier = {
+       .notifier_call = wkup_mbox_msg,
+ };
+ static irqreturn_t wkup_m3_txev_handler(int irq, void *unused)
+ {
+       am33xx_txev_eoi();
+       switch (wkup_m3->state) {
+       case M3_STATE_RESET:
+               wkup_m3->state = M3_STATE_INITED;
+               break;
+       case M3_STATE_MSG_FOR_RESET:
+               wkup_m3->state = M3_STATE_INITED;
 -              mailbox_msg_rx_flush(wkup_m3->mbox);
++              mailbox_empty_tx(wkup_m3->mbox);
+               complete(&wkup_m3_sync);
+               break;
+       case M3_STATE_MSG_FOR_LP:
 -              mailbox_msg_rx_flush(wkup_m3->mbox);
++              mailbox_empty_tx(wkup_m3->mbox);
+               complete(&wkup_m3_sync);
+               break;
+       case M3_STATE_UNKNOWN:
+               pr_err("IRQ %d with WKUP_M3 in unknown state\n", irq);
++              mailbox_empty_tx(wkup_m3->mbox);
+               return IRQ_NONE;
+       }
+       am33xx_txev_enable();
+       return IRQ_HANDLED;
+ }
+ static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context)
+ {
+       struct wkup_m3_context *wkup_m3_context = context;
+       struct platform_device *pdev = to_platform_device(wkup_m3_context->dev);
+       int ret = 0;
+       /* no firmware found */
+       if (!fw) {
+               dev_err(wkup_m3_context->dev, "request_firmware failed\n");
+               goto err;
+       }
+       memcpy((void *)wkup_m3_context->code, fw->data, fw->size);
+       pr_info("Copied the M3 firmware to UMEM\n");
+       wkup_m3->state = M3_STATE_RESET;
+       ret = omap_device_deassert_hardreset(pdev, "wkup_m3");
+       if (ret) {
+               pr_err("Could not deassert the reset for WKUP_M3\n");
+               goto err;
+       } else {
+ #ifdef CONFIG_SUSPEND
+               suspend_set_ops(&am33xx_pm_ops);
+               /*
+                * Physical resume address to be used by ROM code
+                */
+               wkup_m3->ipc_data.resume_addr = (AM33XX_OCMC_END -
+                               am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
+ #endif
+               return;
+       }
+ err:
+       mailbox_put(wkup_m3_context->mbox, &wkup_mbox_notifier);
+ }
+ static int wkup_m3_init(void)
+ {
+       int irq, ret = 0;
+       struct resource *mem;
+       struct platform_device *pdev = to_platform_device(wkup_m3->dev);
+       omap_device_enable_hwmods(to_omap_device(pdev));
+       /* Reserve the MBOX for sending messages to M3 */
+       wkup_m3->mbox = mailbox_get("wkup_m3", &wkup_mbox_notifier);
+       if (IS_ERR(wkup_m3->mbox)) {
+               pr_err("Could not reserve mailbox for A8->M3 IPC\n");
+               ret = -ENODEV;
+               goto exit;
+       }
+       irq = platform_get_irq(pdev, 0);
+       if (!irq) {
+               dev_err(wkup_m3->dev, "no irq resource\n");
+               ret = -ENXIO;
+               goto err;
+       }
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(wkup_m3->dev, "no memory resource\n");
+               ret = -ENXIO;
+               goto err;
+       }
+       wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
+       if (!wkup_m3->code) {
+               dev_err(wkup_m3->dev, "could not ioremap\n");
+               ret = -EADDRNOTAVAIL;
+               goto err;
+       }
+       ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
+                 IRQF_DISABLED, "wkup_m3_txev", NULL);
+       if (ret) {
+               dev_err(wkup_m3->dev, "request_irq failed\n");
+               goto err;
+       } else {
+               am33xx_txev_enable();
+       }
+       pr_info("Trying to load am335x-pm-firmware.bin");
+       /* We don't want to delay boot */
+       request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin",
+                               wkup_m3->dev, GFP_KERNEL, wkup_m3,
+                               am33xx_pm_firmware_cb);
+       return 0;
+ err:
+       mailbox_put(wkup_m3->mbox, &wkup_mbox_notifier);
+ exit:
+       return ret;
+ }
+ /*
+  * Push the minimal suspend-resume code to SRAM
+  */
+ void am33xx_push_sram_idle(void)
+ {
+       am33xx_do_wfi_sram = (void *)omap_sram_push
+                                       (am33xx_do_wfi, am33xx_do_wfi_sz);
+ }
+ static int __init am33xx_map_emif(void)
+ {
+       am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K);
+       if (!am33xx_emif_base)
+               return -ENOMEM;
+       return 0;
+ }
+ void __iomem *am33xx_get_emif_base(void)
+ {
+       return am33xx_emif_base;
+ }
+ int __init am33xx_pm_init(void)
+ {
+       int ret;
+       if (!soc_is_am33xx())
+               return -ENODEV;
+       pr_info("Power Management for AM33XX family\n");
+       /*
+        * By default the following IPs do not have MSTANDBY asserted
+        * which is necessary for PER domain transition. If the drivers
+        * are not compiled into the kernel HWMOD code will not change the
+        * state of the IPs if the IP was not never enabled
+        */
+       usb_oh          = omap_hwmod_lookup("usb_otg_hs");
+       tptc0_oh        = omap_hwmod_lookup("tptc0");
+       tptc1_oh        = omap_hwmod_lookup("tptc1");
+       tptc2_oh        = omap_hwmod_lookup("tptc2");
+       cpsw_oh         = omap_hwmod_lookup("cpgmac0");
+       gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
+       per_pwrdm = pwrdm_lookup("per_pwrdm");
+       gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
+       if ((!usb_oh) || (!tptc0_oh) || (!tptc1_oh) || (!tptc2_oh) ||
+               (!cpsw_oh) || (!gfx_pwrdm) || (!per_pwrdm) ||
+               (!gfx_l4ls_clkdm)) {
+               ret = -ENODEV;
+               goto err;
+       }
+       wkup_m3 = kzalloc(sizeof(struct wkup_m3_context), GFP_KERNEL);
+       if (!wkup_m3) {
+               pr_err("Memory allocation failed\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+       ret = am33xx_map_emif();
+       if (ret) {
+               pr_err("Could not ioremap EMIF\n");
+               goto err;
+       }
+       (void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
+       /* CEFUSE domain can be turned off post bootup */
+       cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
+       if (cefuse_pwrdm)
+               pwrdm_set_next_fpwrst(cefuse_pwrdm, PWRDM_FUNC_PWRST_OFF);
+       else
+               pr_err("Failed to get cefuse_pwrdm\n");
+       wkup_m3->dev = omap_device_get_by_hwmod_name("wkup_m3");
+       ret = wkup_m3_init();
+       if (ret)
+               pr_err("Could not initialise firmware loading\n");
+ err:
+       return ret;
+ }
Simple merge
Simple merge
Simple merge
index e7671c724b405efc9c7904b44d81d8ff1f905e4b,7951e0dec80abd4c9f92785b15743c28e2636788..6c50e4c7fca3b521a03af718c884663283a6b20e
@@@ -146,9 -145,13 +146,11 @@@ static void __init omap2_map_sram(void
  {
        int cached = 1;
  
-       omap_sram_size -= OMAP4_ERRATA_I688_SIZE;
-       if (cpu_is_omap34xx()) {
+ #ifdef CONFIG_OMAP4_ERRATA_I688
 -      if (cpu_is_omap44xx()) {
 -              omap_sram_start += PAGE_SIZE;
 -              omap_sram_size -= SZ_16K;
 -      }
++      if (cpu_is_omap44xx() || soc_is_omap54xx())
++              omap_sram_size -= OMAP4_ERRATA_I688_SIZE;
+ #endif
+       if (cpu_is_omap34xx() || soc_is_am33xx()) {
                /*
                 * SRAM must be marked as non-cached on OMAP3 since the
                 * CORE DPLL M2 divider change code (in SRAM) runs with the
Simple merge
Simple merge
index b5138c84e9b1a237f7848cbe78312b83f8f5455a,a3d893d62934690b8030d63a1f6a151d246eaa00..0cc2ec8149ec2d4897664a1587cdeb8fac6e465b
@@@ -24,9 -24,8 +24,9 @@@
  #include <linux/module.h>
  #include <linux/list.h>
  #include <linux/spinlock.h>
 +#include <linux/pm.h>
+ #include <linux/ti_emif.h>
  #include <memory/jedec_ddr.h>
- #include "emif.h"
  #include "of_memory.h"
  
  /**