|
@@ -58,6 +58,7 @@
|
|
|
u32 enable_off_mode;
|
|
|
u32 sleep_while_idle;
|
|
|
u32 wakeup_timer_seconds;
|
|
|
+u32 wakeup_timer_milliseconds;
|
|
|
|
|
|
struct power_state {
|
|
|
struct powerdomain *pwrdm;
|
|
@@ -267,13 +268,16 @@ static int _prcm_int_handle_wakeup(void)
|
|
|
*/
|
|
|
static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
|
|
|
{
|
|
|
- u32 irqstatus_mpu;
|
|
|
+ u32 irqenable_mpu, irqstatus_mpu;
|
|
|
int c = 0;
|
|
|
|
|
|
- do {
|
|
|
- irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
|
|
|
- OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
|
+ irqenable_mpu = prm_read_mod_reg(OCP_MOD,
|
|
|
+ OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
|
+ irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
|
|
|
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
|
+ irqstatus_mpu &= irqenable_mpu;
|
|
|
|
|
|
+ do {
|
|
|
if (irqstatus_mpu & (OMAP3430_WKUP_ST | OMAP3430_IO_ST)) {
|
|
|
c = _prcm_int_handle_wakeup();
|
|
|
|
|
@@ -292,7 +296,11 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
|
|
|
prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
|
|
|
OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
|
|
|
|
- } while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET));
|
|
|
+ irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
|
|
|
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
|
+ irqstatus_mpu &= irqenable_mpu;
|
|
|
+
|
|
|
+ } while (irqstatus_mpu);
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
@@ -371,9 +379,16 @@ void omap_sram_idle(void)
|
|
|
if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
|
|
|
pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
|
|
|
|
|
|
- /* PER */
|
|
|
+ /* Enable IO-PAD and IO-CHAIN wakeups */
|
|
|
per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
|
|
|
core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
|
|
|
+ if (per_next_state < PWRDM_POWER_ON ||
|
|
|
+ core_next_state < PWRDM_POWER_ON) {
|
|
|
+ prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
|
|
|
+ omap3_enable_io_chain();
|
|
|
+ }
|
|
|
+
|
|
|
+ /* PER */
|
|
|
if (per_next_state < PWRDM_POWER_ON) {
|
|
|
omap_uart_prepare_idle(2);
|
|
|
omap2_gpio_prepare_for_idle(per_next_state);
|
|
@@ -398,10 +413,8 @@ void omap_sram_idle(void)
|
|
|
omap3_core_save_context();
|
|
|
omap3_prcm_save_context();
|
|
|
}
|
|
|
- /* 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();
|
|
|
|
|
|
/*
|
|
@@ -463,7 +476,8 @@ void omap_sram_idle(void)
|
|
|
}
|
|
|
|
|
|
/* Disable IO-PAD and IO-CHAIN wakeup */
|
|
|
- if (core_next_state < PWRDM_POWER_ON) {
|
|
|
+ if (per_next_state < PWRDM_POWER_ON ||
|
|
|
+ core_next_state < PWRDM_POWER_ON) {
|
|
|
prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
|
|
|
omap3_disable_io_chain();
|
|
|
}
|
|
@@ -548,20 +562,21 @@ out:
|
|
|
#ifdef CONFIG_SUSPEND
|
|
|
static suspend_state_t suspend_state;
|
|
|
|
|
|
-static void omap2_pm_wakeup_on_timer(u32 seconds)
|
|
|
+static void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
|
|
|
{
|
|
|
u32 tick_rate, cycles;
|
|
|
|
|
|
- if (!seconds)
|
|
|
+ if (!seconds && !milliseconds)
|
|
|
return;
|
|
|
|
|
|
tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
|
|
|
- cycles = tick_rate * seconds;
|
|
|
+ cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
|
|
|
omap_dm_timer_stop(gptimer_wakeup);
|
|
|
omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
|
|
|
|
|
|
- pr_info("PM: Resume timer in %d secs (%d ticks at %d ticks/sec.)\n",
|
|
|
- seconds, cycles, tick_rate);
|
|
|
+ pr_info("PM: Resume timer in %u.%03u secs"
|
|
|
+ " (%d ticks at %d ticks/sec.)\n",
|
|
|
+ seconds, milliseconds, cycles, tick_rate);
|
|
|
}
|
|
|
|
|
|
static int omap3_pm_prepare(void)
|
|
@@ -575,8 +590,9 @@ static int omap3_pm_suspend(void)
|
|
|
struct power_state *pwrst;
|
|
|
int state, ret = 0;
|
|
|
|
|
|
- if (wakeup_timer_seconds)
|
|
|
- omap2_pm_wakeup_on_timer(wakeup_timer_seconds);
|
|
|
+ if (wakeup_timer_seconds || wakeup_timer_milliseconds)
|
|
|
+ omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
|
|
|
+ wakeup_timer_milliseconds);
|
|
|
|
|
|
/* Read current next_pwrsts */
|
|
|
list_for_each_entry(pwrst, &pwrst_list, node)
|
|
@@ -1080,14 +1096,6 @@ static int __init omap3_pm_init(void)
|
|
|
omap3_idle_init();
|
|
|
|
|
|
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
|
|
|
- */
|
|
|
- clkdm_add_wkdep(per_clkdm, core_clkdm);
|
|
|
-
|
|
|
if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
|
|
|
omap3_secure_ram_storage =
|
|
|
kmalloc(0x803F, GFP_KERNEL);
|