diff options
author | Colin Cross <ccross@android.com> | 2011-11-01 18:41:21 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2011-11-03 14:13:42 -0700 |
commit | 4167a91d2db65b09b74a405cafa3df2f17d55bd4 (patch) | |
tree | fe06864b85eb2272f1fcdf276839a6f37761c109 | |
parent | b689df91926d2149e75eca3579d0a9085078fee4 (diff) | |
download | kernel_samsung_tuna-4167a91d2db65b09b74a405cafa3df2f17d55bd4.zip kernel_samsung_tuna-4167a91d2db65b09b74a405cafa3df2f17d55bd4.tar.gz kernel_samsung_tuna-4167a91d2db65b09b74a405cafa3df2f17d55bd4.tar.bz2 |
ARM: omap2+: gpio: simplify updating gpios in off vs. retention
Call the same function to set up the gpio controllers for off
mode and retention, and get rid of the external apis to set
edge wakeups.
Calling both omap2_gpio_prepare_for_idle and
omap2_gpio_set_edge_wakeup, as was done when entering off mode,
was never safe because both functions save their context in the
same location.
Change-Id: I159bdc1863aec9827d7fb1ec0525afd632be6fa6
Signed-off-by: Colin Cross <ccross@android.com>
-rw-r--r-- | arch/arm/mach-omap2/pm24xx.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm44xx.c | 15 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/gpio.h | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 114 |
5 files changed, 60 insertions, 77 deletions
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index fb999bc..faa8463 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -148,7 +148,7 @@ no_sleep: tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC; omap2_pm_dump(0, 1, tmp); } - omap2_gpio_resume_after_idle(); + omap2_gpio_resume_after_idle(0); clk_enable(osc_ck); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 321a7e6..535480f 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -449,7 +449,7 @@ void omap_sram_idle(void) /* PER */ if (per_next_state < PWRDM_POWER_ON) { per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); - omap2_gpio_resume_after_idle(); + omap2_gpio_resume_after_idle(per_going_off); } /* Disable IO-PAD and IO-CHAIN wakeup */ diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 6c0bd35..cb40890 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -129,6 +129,8 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) core_next_state = pwrdm_read_next_pwrst(core_pwrdm); mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); + omap2_gpio_prepare_for_idle(omap4_device_next_state_off()); + if (mpu_next_state < PWRDM_POWER_INACTIVE) { if (omap_dvfs_is_scaling(mpu_voltdm)) { mpu_next_state = PWRDM_POWER_INACTIVE; @@ -165,10 +167,7 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) } } - omap2_gpio_set_edge_wakeup(); - if (omap4_device_next_state_off()) { - omap2_gpio_prepare_for_idle(true); omap_gpmc_save_context(); omap_dma_global_context_save(); } @@ -223,26 +222,20 @@ abort_device_off: } if (omap4_device_next_state_off()) { - /* - * GPIO: since we have put_synced clks, we need to resume - * even if OFF was not really achieved - */ - omap2_gpio_resume_after_idle(); - /* Disable the extension of Non-EMIF I/O isolation */ omap4_prminst_rmw_inst_reg_bits(OMAP4430_ISOOVR_EXTEND_MASK, 0, OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET); } - omap2_gpio_restore_edge_wakeup(); - if (mpu_next_state < PWRDM_POWER_INACTIVE) { omap_vc_set_auto_trans(mpu_voltdm, OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE); omap_sr_enable(mpu_voltdm); } + omap2_gpio_resume_after_idle(omap4_device_next_state_off()); + return; } diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 89af4ad..b374a9e 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -214,11 +214,9 @@ struct omap_gpio_platform_data { }; extern void omap2_gpio_prepare_for_idle(int off_mode); -extern void omap2_gpio_resume_after_idle(void); +extern void omap2_gpio_resume_after_idle(int off_mode); extern void omap_set_gpio_debounce(int gpio, int enable); extern void omap_set_gpio_debounce_time(int gpio, int enable); -extern void omap2_gpio_set_edge_wakeup(void); -extern void omap2_gpio_restore_edge_wakeup(void); /*-------------------------------------------------------------------------*/ /* Wrappers for "new style" GPIO calls, using the new infrastructure diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d91a5aa..26a5a7e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1385,72 +1385,63 @@ static int omap_gpio_pm_runtime_resume(struct device *dev) } #ifdef CONFIG_ARCH_OMAP2PLUS -void omap2_gpio_set_edge_wakeup(void) +static void omap2_gpio_set_edge_wakeup(struct gpio_bank *bank) { - struct gpio_bank *bank; + u32 level_low = 0; + u32 level_high = 0; + u32 wkup_status = 0; - list_for_each_entry(bank, &omap_gpio_list, node) { - u32 level_low = 0; - u32 level_high = 0; - u32 wkup_status = 0; + if (pm_runtime_get_sync(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " + "failed\n", __func__, bank->id); + return; + } - if (pm_runtime_get_sync(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " - "failed\n", __func__, bank->id); - return; - } + level_low = __raw_readl(bank->base + + bank->regs->leveldetect0); + level_high = __raw_readl(bank->base + + bank->regs->leveldetect1); + wkup_status = __raw_readl(bank->base + + bank->regs->wkup_status); + bank->context.edge_falling = __raw_readl(bank->base + + bank->regs->fallingdetect); + bank->context.edge_rising = __raw_readl(bank->base + + bank->regs->risingdetect); - level_low = __raw_readl(bank->base + - bank->regs->leveldetect0); - level_high = __raw_readl(bank->base + - bank->regs->leveldetect1); - wkup_status = __raw_readl(bank->base + - bank->regs->wkup_status); - bank->context.edge_falling = __raw_readl(bank->base + - bank->regs->fallingdetect); - bank->context.edge_rising = __raw_readl(bank->base + - bank->regs->risingdetect); + /* + * Set edge trigger for all gpio's that are + * expected to produce wakeup from low power. + * even if they are set for level detection only. + */ + __raw_writel(bank->context.edge_falling | (level_low & wkup_status), + (bank->base + bank->regs->fallingdetect)); + __raw_writel(bank->context.edge_rising | (level_high & wkup_status), + (bank->base + bank->regs->risingdetect)); - /* - * Set edge trigger for all gpio's that are - * expected to produce wakeup from low power. - * even if they are set for level detection only. - */ - __raw_writel(bank->context.edge_falling | (level_low & wkup_status), - (bank->base + bank->regs->fallingdetect)); - __raw_writel(bank->context.edge_rising | (level_high & wkup_status), - (bank->base + bank->regs->risingdetect)); - - if (pm_runtime_put_sync_suspend(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " - "failed\n", __func__, bank->id); - return; - } + if (pm_runtime_put_sync_suspend(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " + "failed\n", __func__, bank->id); + return; } } -void omap2_gpio_restore_edge_wakeup(void) +static void omap2_gpio_restore_edge_wakeup(struct gpio_bank *bank) { - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - /* restore edge setting */ - if (pm_runtime_get_sync(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " - "failed\n", __func__, bank->id); - return; - } + if (pm_runtime_get_sync(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync " + "failed\n", __func__, bank->id); + return; + } - __raw_writel(bank->context.edge_falling, - (bank->base + bank->regs->fallingdetect)); - __raw_writel(bank->context.edge_rising, - (bank->base + bank->regs->risingdetect)); + __raw_writel(bank->context.edge_falling, + (bank->base + bank->regs->fallingdetect)); + __raw_writel(bank->context.edge_rising, + (bank->base + bank->regs->risingdetect)); - if (pm_runtime_put_sync_suspend(bank->dev) < 0) { - dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " - "failed\n", __func__, bank->id); - return; - } + if (pm_runtime_put_sync_suspend(bank->dev) < 0) { + dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync " + "failed\n", __func__, bank->id); + return; } } @@ -1458,12 +1449,11 @@ void omap2_gpio_prepare_for_idle(int off_mode) { struct gpio_bank *bank; - if (!off_mode) - return; - list_for_each_entry(bank, &omap_gpio_list, node) { - if (!bank->mod_usage || !bank->loses_context) + if (!bank->mod_usage || !bank->loses_context || !off_mode) { + omap2_gpio_set_edge_wakeup(bank); continue; + } if (pm_runtime_put_sync_suspend(bank->dev) < 0) dev_err(bank->dev, "%s: GPIO bank %d " @@ -1472,13 +1462,15 @@ void omap2_gpio_prepare_for_idle(int off_mode) } } -void omap2_gpio_resume_after_idle(void) +void omap2_gpio_resume_after_idle(int off_mode) { struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { - if (!bank->mod_usage || !bank->loses_context) + if (!bank->mod_usage || !bank->loses_context || !off_mode) { + omap2_gpio_restore_edge_wakeup(bank); continue; + } if (pm_runtime_get_sync(bank->dev) < 0) dev_err(bank->dev, "%s: GPIO bank %d " |