include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / arch / arm / mach-omap2 / pm34xx.c
index 55567bf..ea0000b 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/err.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
 
 #include <plat/sram.h>
 #include <plat/clockdomain.h>
 #include "pm.h"
 #include "sdrc.h"
 
-#define SDRC_POWER_AUTOCOUNT_SHIFT 8
-#define SDRC_POWER_AUTOCOUNT_MASK (0xffff << SDRC_POWER_AUTOCOUNT_SHIFT)
-#define SDRC_POWER_CLKCTRL_SHIFT 4
-#define SDRC_POWER_CLKCTRL_MASK (0x3 << SDRC_POWER_CLKCTRL_SHIFT)
-#define SDRC_SELF_REFRESH_ON_AUTOCOUNT (0x2 << SDRC_POWER_CLKCTRL_SHIFT)
-
 /* Scratchpad offsets */
 #define OMAP343X_TABLE_ADDRESS_OFFSET     0x31
 #define OMAP343X_TABLE_VALUE_OFFSET       0x30
@@ -80,8 +76,7 @@ static int (*_omap_save_secure_sram)(u32 *addr);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-
-static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
+static struct powerdomain *cam_pwrdm;
 
 static inline void omap3_per_save_context(void)
 {
@@ -93,6 +88,35 @@ static inline void omap3_per_restore_context(void)
        omap_gpio_restore_context();
 }
 
+static void omap3_enable_io_chain(void)
+{
+       int timeout = 0;
+
+       if (omap_rev() >= OMAP3430_REV_ES3_1) {
+               prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN, WKUP_MOD, PM_WKEN);
+               /* Do a readback to assure write has been done */
+               prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+
+               while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+                        OMAP3430_ST_IO_CHAIN)) {
+                       timeout++;
+                       if (timeout > 1000) {
+                               printk(KERN_ERR "Wake up daisy chain "
+                                      "activation failed.\n");
+                               return;
+                       }
+                       prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN,
+                                            WKUP_MOD, PM_WKST);
+               }
+       }
+}
+
+static void omap3_disable_io_chain(void)
+{
+       if (omap_rev() >= OMAP3430_REV_ES3_1)
+               prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN, WKUP_MOD, PM_WKEN);
+}
+
 static void omap3_core_save_context(void)
 {
        u32 control_padconf_off;
@@ -102,9 +126,17 @@ static void omap3_core_save_context(void)
        control_padconf_off |= START_PADCONF_SAVE;
        omap_ctrl_writel(control_padconf_off, OMAP343X_CONTROL_PADCONF_OFF);
        /* wait for the save to complete */
-       while (!omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
-                       & PADCONF_SAVE_DONE)
-               ;
+       while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
+                       & PADCONF_SAVE_DONE))
+               udelay(1);
+
+       /*
+        * Force write last pad into memory, as this can fail in some
+        * cases according to erratas 1.157, 1.185
+        */
+       omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14),
+               OMAP343X_CONTROL_MEM_WKUP + 0x2a0);
+
        /* Save the Interrupt controller context */
        omap_intc_save_context();
        /* Save the GPMC context */
@@ -294,7 +326,7 @@ static void restore_table_entry(void)
        restore_control_register(control_reg_value);
 }
 
-static void omap_sram_idle(void)
+void omap_sram_idle(void)
 {
        /* Variable to tell what needs to be saved and restored
         * in omap_sram_idle*/
@@ -337,7 +369,7 @@ static void omap_sram_idle(void)
 
        /* NEON control */
        if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
-               set_pwrdm_state(neon_pwrdm, mpu_next_state);
+               pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
 
        /* PER */
        per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
@@ -355,6 +387,9 @@ static void omap_sram_idle(void)
                }
        }
 
+       if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
+               omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(0);
@@ -363,24 +398,22 @@ static void omap_sram_idle(void)
                        omap3_core_save_context();
                        omap3_prcm_save_context();
                }
-               /* Enable IO-PAD wakeup */
+               /* Enable IO-PAD and IO-CHAIN wakeups */
                prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+               omap3_enable_io_chain();
        }
+       omap3_intc_prepare_idle();
 
        /*
-        * Force SDRAM controller to self-refresh mode after timeout on
-        * autocount. This is needed on ES3.0 to avoid SDRAM controller
-        * hang-ups.
-        */
+       * On EMU/HS devices ROM code restores a SRDC value
+       * from scratchpad which has automatic self refresh on timeout
+       * of AUTO_CNT = 1 enabled. This takes care of errata 1.142.
+       * Hence store/restore the SDRC_POWER register here.
+       */
        if (omap_rev() >= OMAP3430_REV_ES3_0 &&
            omap_type() != OMAP2_DEVICE_TYPE_GP &&
-           core_next_state == PWRDM_POWER_OFF) {
+           core_next_state == PWRDM_POWER_OFF)
                sdrc_pwr = sdrc_read_reg(SDRC_POWER);
-               sdrc_write_reg((sdrc_pwr &
-                       ~(SDRC_POWER_AUTOCOUNT_MASK|SDRC_POWER_CLKCTRL_MASK)) |
-                       (1 << SDRC_POWER_AUTOCOUNT_SHIFT) |
-                       SDRC_SELF_REFRESH_ON_AUTOCOUNT, SDRC_POWER);
-       }
 
        /*
         * omap3_arm_context is the location where ARM registers
@@ -390,7 +423,7 @@ static void omap_sram_idle(void)
        _omap_sram_idle(omap3_arm_context, save_state);
        cpu_init();
 
-       /* Restore normal SDRAM settings */
+       /* Restore normal SDRC POWER settings */
        if (omap_rev() >= OMAP3430_REV_ES3_0 &&
            omap_type() != OMAP2_DEVICE_TYPE_GP &&
            core_next_state == PWRDM_POWER_OFF)
@@ -416,6 +449,7 @@ static void omap_sram_idle(void)
                                               OMAP3430_GR_MOD,
                                               OMAP3_PRM_VOLTCTRL_OFFSET);
        }
+       omap3_intc_resume_idle();
 
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
@@ -428,69 +462,30 @@ static void omap_sram_idle(void)
                        pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
        }
 
-       /* Disable IO-PAD wakeup */
-       if (core_next_state < PWRDM_POWER_ON)
+       /* Disable IO-PAD and IO-CHAIN wakeup */
+       if (core_next_state < PWRDM_POWER_ON) {
                prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+               omap3_disable_io_chain();
+       }
 
        pwrdm_post_transition();
 
+       omap2_clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
-/*
- * Check if functional clocks are enabled before entering
- * sleep. This function could be behind CONFIG_PM_DEBUG
- * when all drivers are configuring their sysconfig registers
- * properly and using their clocks properly.
- */
-static int omap3_fclks_active(void)
-{
-       u32 fck_core1 = 0, fck_core3 = 0, fck_sgx = 0, fck_dss = 0,
-               fck_cam = 0, fck_per = 0, fck_usbhost = 0;
-
-       fck_core1 = cm_read_mod_reg(CORE_MOD,
-                                   CM_FCLKEN1);
-       if (omap_rev() > OMAP3430_REV_ES1_0) {
-               fck_core3 = cm_read_mod_reg(CORE_MOD,
-                                           OMAP3430ES2_CM_FCLKEN3);
-               fck_sgx = cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
-                                         CM_FCLKEN);
-               fck_usbhost = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
-                                             CM_FCLKEN);
-       } else
-               fck_sgx = cm_read_mod_reg(GFX_MOD,
-                                         OMAP3430ES2_CM_FCLKEN3);
-       fck_dss = cm_read_mod_reg(OMAP3430_DSS_MOD,
-                                 CM_FCLKEN);
-       fck_cam = cm_read_mod_reg(OMAP3430_CAM_MOD,
-                                 CM_FCLKEN);
-       fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
-                                 CM_FCLKEN);
-
-       /* Ignore UART clocks.  These are handled by UART core (serial.c) */
-       fck_core1 &= ~(OMAP3430_EN_UART1 | OMAP3430_EN_UART2);
-       fck_per &= ~OMAP3430_EN_UART3;
-
-       if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
-           fck_cam | fck_per | fck_usbhost)
-               return 1;
-       return 0;
-}
-
-static int omap3_can_sleep(void)
+int omap3_can_sleep(void)
 {
        if (!sleep_while_idle)
                return 0;
        if (!omap_uart_can_sleep())
                return 0;
-       if (omap3_fclks_active())
-               return 0;
        return 1;
 }
 
 /* This sets pwrdm state (other than mpu & core. Currently only ON &
  * RET are supported. Function is assuming that clkdm doesn't have
  * hw_sup mode enabled. */
-static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
+int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 {
        u32 cur_state;
        int sleep_switch = 0;
@@ -540,7 +535,7 @@ static void omap3_pm_idle(void)
        if (!omap3_can_sleep())
                goto out;
 
-       if (omap_irq_pending())
+       if (omap_irq_pending() || need_resched())
                goto out;
 
        omap_sram_idle();
@@ -595,6 +590,8 @@ static int omap3_pm_suspend(void)
        }
 
        omap_uart_prepare_suspend();
+       omap3_intc_suspend();
+
        omap_sram_idle();
 
 restore:
@@ -689,10 +686,10 @@ static void __init omap3_iva_idle(void)
        prm_write_mod_reg(OMAP3430_RST1_IVA2 |
                          OMAP3430_RST2_IVA2 |
                          OMAP3430_RST3_IVA2,
-                         OMAP3430_IVA2_MOD, RM_RSTCTRL);
+                         OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
        /* Enable IVA2 clock */
-       cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2,
+       cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
                         OMAP3430_IVA2_MOD, CM_FCLKEN);
 
        /* Set IVA2 boot mode to 'idle' */
@@ -700,7 +697,7 @@ static void __init omap3_iva_idle(void)
                         OMAP343X_CONTROL_IVA2_BOOTMOD);
 
        /* Un-reset IVA2 */
-       prm_write_mod_reg(0, OMAP3430_IVA2_MOD, RM_RSTCTRL);
+       prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
        /* Disable IVA2 clock */
        cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
@@ -709,7 +706,7 @@ static void __init omap3_iva_idle(void)
        prm_write_mod_reg(OMAP3430_RST1_IVA2 |
                          OMAP3430_RST2_IVA2 |
                          OMAP3430_RST3_IVA2,
-                         OMAP3430_IVA2_MOD, RM_RSTCTRL);
+                         OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 }
 
 static void __init omap3_d2d_idle(void)
@@ -732,8 +729,8 @@ static void __init omap3_d2d_idle(void)
        /* reset modem */
        prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON |
                          OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST,
-                         CORE_MOD, RM_RSTCTRL);
-       prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL);
+                         CORE_MOD, OMAP2_RM_RSTCTRL);
+       prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
 }
 
 static void __init prcm_setup_regs(void)
@@ -852,6 +849,8 @@ static void __init prcm_setup_regs(void)
                        CM_AUTOIDLE);
        }
 
+       omap_ctrl_writel(OMAP3430_AUTOIDLE, OMAP2_CONTROL_SYSCONFIG);
+
        /*
         * Set all plls to autoidle. This is needed until autoidle is
         * enabled by clockfw
@@ -892,15 +891,23 @@ static void __init prcm_setup_regs(void)
        prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN,
                          OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
+       /* Enable PM_WKEN to support DSS LPR */
+       prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS,
+                               OMAP3430_DSS_MOD, PM_WKEN);
+
        /* Enable wakeups in PER */
        prm_write_mod_reg(OMAP3430_EN_GPIO2 | OMAP3430_EN_GPIO3 |
                          OMAP3430_EN_GPIO4 | OMAP3430_EN_GPIO5 |
-                         OMAP3430_EN_GPIO6 | OMAP3430_EN_UART3,
+                         OMAP3430_EN_GPIO6 | OMAP3430_EN_UART3 |
+                         OMAP3430_EN_MCBSP2 | OMAP3430_EN_MCBSP3 |
+                         OMAP3430_EN_MCBSP4,
                          OMAP3430_PER_MOD, PM_WKEN);
        /* and allow them to wake up MPU */
        prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2 | OMAP3430_EN_GPIO3 |
                          OMAP3430_GRPSEL_GPIO4 | OMAP3430_EN_GPIO5 |
-                         OMAP3430_GRPSEL_GPIO6 | OMAP3430_EN_UART3,
+                         OMAP3430_GRPSEL_GPIO6 | OMAP3430_EN_UART3 |
+                         OMAP3430_EN_MCBSP2 | OMAP3430_EN_MCBSP3 |
+                         OMAP3430_EN_MCBSP4,
                          OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
 
        /* Don't attach IVA interrupts */
@@ -910,31 +917,13 @@ static void __init prcm_setup_regs(void)
        prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
 
        /* Clear any pending 'reset' flags */
-       prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
-
-       /* Clear any pending PRCM interrupts */
-       prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-
-       /* Don't attach IVA interrupts */
-       prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-       prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
-       prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-       prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
-
-       /* Clear any pending 'reset' flags */
-       prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
-       prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
+       prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
+       prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
 
        /* Clear any pending PRCM interrupts */
        prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
@@ -953,6 +942,10 @@ void omap3_pm_off_mode_enable(int enable)
        else
                state = PWRDM_POWER_RET;
 
+#ifdef CONFIG_CPU_IDLE
+       omap3_cpuidle_update_states();
+#endif
+
        list_for_each_entry(pwrst, &pwrst_list, node) {
                pwrst->next_state = state;
                set_pwrdm_state(pwrst->pwrdm, state);
@@ -1010,6 +1003,9 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
  */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
+       clkdm_clear_all_wkdeps(clkdm);
+       clkdm_clear_all_sleepdeps(clkdm);
+
        if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
                omap2_clkdm_allow_idle(clkdm);
        else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
@@ -1030,6 +1026,7 @@ void omap_push_sram_idle(void)
 static int __init omap3_pm_init(void)
 {
        struct power_state *pwrst, *tmp;
+       struct clockdomain *neon_clkdm, *per_clkdm, *mpu_clkdm, *core_clkdm;
        int ret;
 
        if (!cpu_is_omap34xx())
@@ -1067,6 +1064,12 @@ static int __init omap3_pm_init(void)
        neon_pwrdm = pwrdm_lookup("neon_pwrdm");
        per_pwrdm = pwrdm_lookup("per_pwrdm");
        core_pwrdm = pwrdm_lookup("core_pwrdm");
+       cam_pwrdm = pwrdm_lookup("cam_pwrdm");
+
+       neon_clkdm = clkdm_lookup("neon_clkdm");
+       mpu_clkdm = clkdm_lookup("mpu_clkdm");
+       per_clkdm = clkdm_lookup("per_clkdm");
+       core_clkdm = clkdm_lookup("core_clkdm");
 
        omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
@@ -1074,15 +1077,16 @@ static int __init omap3_pm_init(void)
 #endif /* CONFIG_SUSPEND */
 
        pm_idle = omap3_pm_idle;
+       omap3_idle_init();
 
-       pwrdm_add_wkdep(neon_pwrdm, mpu_pwrdm);
+       clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
        /*
         * REVISIT: This wkdep is only necessary when GPIO2-6 are enabled for
         * IO-pad wakeup.  Otherwise it will unnecessarily waste power
         * waking up PER with every CORE wakeup - see
         * http://marc.info/?l=linux-omap&m=121852150710062&w=2
        */
-       pwrdm_add_wkdep(per_pwrdm, core_pwrdm);
+       clkdm_add_wkdep(per_clkdm, core_clkdm);
 
        if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
                omap3_secure_ram_storage =