>-----Original Message-----
>From: Kevin Hilman [mailto:[email protected]]
>Sent: Wednesday, September 22, 2010 7:55 PM
>To: Kalliguddi, Hema
>Cc: [email protected]; Varadarajan, Charulatha;
>Basak, Partha; Tero Kristo
>Subject: Re: [PATCH 2/2] OMAP2+: GPIO: move late PM out of
>interrupts-disabled idle path
>
>"Kalliguddi, Hema" <[email protected]> writes:
>
>>>-----Original Message-----
>>>From: [email protected]
>>>[mailto:[email protected]] On Behalf Of Kevin Hilman
>>>Sent: Tuesday, September 14, 2010 4:33 AM
>>>To: [email protected]
>>>Cc: Varadarajan, Charulatha; Basak, Partha; Tero Kristo
>>>Subject: [PATCH 2/2] OMAP2+: GPIO: move late PM out of
>>>interrupts-disabled idle path
>>>
>>>From: Kevin Hilman <[email protected]>
>>>
>>>Currently, we wait until late in the idle path where interrupts are
>>>disabled to do runtime-PM-like management for certain special-case
>>>devices like GPIO.
>>>
>>>As a prerequiste to moving GPIO to the new runtime PM framework, move
>>>this runtime-PM-like code out of the late idle path into new device
>>>idle and resume functions that can be called before interrupts are
>>>disabled by CPUidle and/or suspend.
>>>
>>>In addition, move all the GPIO-specific logic into the GPIO core
>>>instead of keeping GPIO-specific knowledge of power-states, context
>>>saving etc. in the PM core.
>>>
>>>Also, call the new device-idle and -resume methods from CPUidle and
>>>static suspend path.
>>>
>>>Signed-off-by: Kevin Hilman <[email protected]>
>>>---
>>> arch/arm/mach-omap2/cpuidle34xx.c | 4 ++
>>> arch/arm/mach-omap2/pm.h | 2 +
>>> arch/arm/mach-omap2/pm24xx.c | 2 +-
>>> arch/arm/mach-omap2/pm34xx.c | 38 +++++++++------------
>>> arch/arm/plat-omap/gpio.c | 57
>>>++++++++++++++++++++++++--------
>>> arch/arm/plat-omap/include/plat/gpio.h | 4 +--
>>> 6 files changed, 67 insertions(+), 40 deletions(-)
>>>
>>>diff --git a/arch/arm/mach-omap2/cpuidle34xx.c
>>>b/arch/arm/mach-omap2/cpuidle34xx.c
>>>index 0923b82..681d823 100644
>>>--- a/arch/arm/mach-omap2/cpuidle34xx.c
>>>+++ b/arch/arm/mach-omap2/cpuidle34xx.c
>>>@@ -274,9 +274,13 @@ static int omap3_enter_idle_bm(struct
>>>cpuidle_device *dev,
>>> pwrdm_set_next_pwrst(per_pd, per_next_state);
>>>
>>> select_state:
>>>+ omap3_device_idle();
>>>+
>>> dev->last_state = new_state;
>>> ret = omap3_enter_idle(dev, new_state);
>>>
>>>+ omap3_device_resume();
>>>+
>>> /* Restore original PER state if it was modified */
>>> if (per_next_state != per_saved_state)
>>> pwrdm_set_next_pwrst(per_pd, per_saved_state);
>>>diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
>>>index 3de6ece..33cae4b 100644
>>>--- a/arch/arm/mach-omap2/pm.h
>>>+++ b/arch/arm/mach-omap2/pm.h
>>>@@ -22,6 +22,8 @@ extern void omap_sram_idle(void);
>>> extern int omap3_can_sleep(void);
>>> extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
>>> extern int omap3_idle_init(void);
>>>+extern void omap3_device_idle(void);
>>>+extern void omap3_device_resume(void);
>>>
>>> struct cpuidle_params {
>>> u8 valid;
>>>diff --git a/arch/arm/mach-omap2/pm24xx.c
>>>b/arch/arm/mach-omap2/pm24xx.c
>>>index 6aeedea..7bbf0db 100644
>>>--- a/arch/arm/mach-omap2/pm24xx.c
>>>+++ b/arch/arm/mach-omap2/pm24xx.c
>>>@@ -106,7 +106,7 @@ static void omap2_enter_full_retention(void)
>>> l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) |
>>>OMAP24XX_USBSTANDBYCTRL;
>>> omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
>>>
>>>- omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);
>>>+ omap2_gpio_prepare_for_idle();
>>>
>>> if (omap2_pm_debug) {
>>> omap2_pm_dump(0, 0, 0);
>>>diff --git a/arch/arm/mach-omap2/pm34xx.c
>>>b/arch/arm/mach-omap2/pm34xx.c
>>>index bb2ba1e..9e590d9 100644
>>>--- a/arch/arm/mach-omap2/pm34xx.c
>>>+++ b/arch/arm/mach-omap2/pm34xx.c
>>>@@ -74,16 +74,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
>>> static struct powerdomain *core_pwrdm, *per_pwrdm;
>>> static struct powerdomain *cam_pwrdm;
>>>
>>>-static inline void omap3_per_save_context(void)
>>>-{
>>>- omap_gpio_save_context();
>>>-}
>>>-
>>>-static inline void omap3_per_restore_context(void)
>>>-{
>>>- omap_gpio_restore_context();
>>>-}
>>>-
>>> static void omap3_enable_io_chain(void)
>>> {
>>> int timeout = 0;
>>>@@ -332,6 +322,16 @@ static void restore_table_entry(void)
>>> restore_control_register(control_reg_value);
>>> }
>>>
>>>+void omap3_device_idle(void)
>>>+{
>>>+ omap2_gpio_prepare_for_idle();
>>>+}
>>>+
>>
>> Is not it is a good idea to pass the new_state as the
>parameter for the driver calls?
>> It will reduce each individual drivers reading the PRCM
>register to findout the next state.
>> This might save some time in the idle loop.
>
>I chose not to pass the parameters on purpose. All of the intelligence
>for device idle (including which powerdomain state to check)
>should live
>in the driver code.
>
OK agree.
>If reading the PRCM registers is becoming a problem, it will
>be a simple
>patch to patch the powerdomain core to cache the current value of it's
>next state so at least reads of next_state will be fast.
>
This is good idea, with this we can avoid n number of PRCM register reads.
Today it may not be a problem as there are few hooks in the idle path
But if there are more number of driver calls, then it might be useful patch.
~Hema
>Kevin
>
>>>+void omap3_device_resume(void)
>>>+{
>>>+ omap2_gpio_resume_after_idle();
>>>+}
>>>+
>>
>> Here we will need to pass the next_state as well as
>previous_state as parameters. If we agree to
>> pass the parameters.
>>
>> ~Hema
>>
>>> void omap_sram_idle(void)
>>> {
>>> /* Variable to tell what needs to be saved and restored
>>>@@ -344,7 +344,7 @@ void omap_sram_idle(void)
>>> int mpu_next_state = PWRDM_POWER_ON;
>>> int per_next_state = PWRDM_POWER_ON;
>>> int core_next_state = PWRDM_POWER_ON;
>>>- int core_prev_state, per_prev_state;
>>>+ int core_prev_state;
>>> u32 sdrc_pwr = 0;
>>>
>>> if (!_omap_sram_idle)
>>>@@ -387,12 +387,9 @@ void omap_sram_idle(void)
>>> }
>>>
>>> /* PER */
>>>- if (per_next_state < PWRDM_POWER_ON) {
>>>+ if (per_next_state < PWRDM_POWER_ON)
>>> omap_uart_prepare_idle(2);
>>>- omap2_gpio_prepare_for_idle(per_next_state);
>>>- if (per_next_state == PWRDM_POWER_OFF)
>>>- omap3_per_save_context();
>>>- }
>>>+
>>>
>>> /* CORE */
>>> if (core_next_state < PWRDM_POWER_ON) {
>>>@@ -454,13 +451,8 @@ void omap_sram_idle(void)
>>> omap3_intc_resume_idle();
>>>
>>> /* PER */
>>>- if (per_next_state < PWRDM_POWER_ON) {
>>>- per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
>>>- omap2_gpio_resume_after_idle();
>>>- if (per_prev_state == PWRDM_POWER_OFF)
>>>- omap3_per_restore_context();
>>>+ if (per_next_state < PWRDM_POWER_ON)
>>> omap_uart_resume_idle(2);
>>>- }
>>>
>>> /* Disable IO-PAD and IO-CHAIN wakeup */
>>> if (omap3_has_io_wakeup() &&
>>>@@ -570,6 +562,7 @@ static void omap2_pm_wakeup_on_timer(u32
>>>seconds, u32 milliseconds)
>>> static int omap3_pm_prepare(void)
>>> {
>>> disable_hlt();
>>>+ omap3_device_idle();
>>> return 0;
>>> }
>>>
>>>@@ -637,6 +630,7 @@ static int omap3_pm_enter(suspend_state_t unused)
>>>
>>> static void omap3_pm_finish(void)
>>> {
>>>+ omap3_device_resume();
>>> enable_hlt();
>>> }
>>>
>>>diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
>>>index 7951eef..b0467c1 100644
>>>--- a/arch/arm/plat-omap/gpio.c
>>>+++ b/arch/arm/plat-omap/gpio.c
>>>@@ -29,6 +29,8 @@
>>> #include <asm/mach/irq.h>
>>> #include <plat/powerdomain.h>
>>>
>>>+static struct powerdomain *per_pwrdm;
>>>+
>>> /*
>>> * OMAP1510 GPIO registers
>>> */
>>>@@ -207,6 +209,9 @@ struct gpio_bank {
>>> u32 dbck_enable_mask;
>>> };
>>>
>>>+static void omap3_gpio_restore_context(void);
>>>+static void omap3_gpio_save_context(void);
>>>+
>>> #define METHOD_MPUIO 0
>>> #define METHOD_GPIO_1510 1
>>> #define METHOD_GPIO_1610 2
>>>@@ -1778,6 +1783,8 @@ static int __init _omap_gpio_init(void)
>>> }
>>> #endif
>>>
>>>+ if (cpu_class_is_omap2())
>>>+ per_pwrdm = pwrdm_lookup("per_pwrdm");
>>>
>>> #ifdef CONFIG_ARCH_OMAP15XX
>>> if (cpu_is_omap15xx()) {
>>>@@ -2074,14 +2081,22 @@ static struct sys_device omap_gpio_device = {
>>>
>>> static int workaround_enabled;
>>>
>>>-void omap2_gpio_prepare_for_idle(int power_state)
>>>+void omap2_gpio_prepare_for_idle(void)
>>> {
>>>- int i, c = 0;
>>>- int min = 0;
>>>+ int i, c = 0, min = 0;
>>>+ int per_next_state;
>>>+
>>>+ if (!per_pwrdm)
>>>+ return;
>>>+
>>>+ per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
>>>+ if (per_next_state >= PWRDM_POWER_INACTIVE)
>>>+ return;
>>>
>>> if (cpu_is_omap34xx())
>>> min = 1;
>>>
>>>+ workaround_enabled = 0;
>>> for (i = min; i < gpio_bank_count; i++) {
>>> struct gpio_bank *bank = &gpio_bank[i];
>>> u32 l1, l2;
>>>@@ -2089,7 +2104,7 @@ void omap2_gpio_prepare_for_idle(int
>power_state)
>>> if (bank->dbck_enable_mask)
>>> clk_disable(bank->dbck);
>>>
>>>- if (power_state > PWRDM_POWER_OFF)
>>>+ if (per_next_state > PWRDM_POWER_OFF)
>>> continue;
>>>
>>> /* If going to OFF, remove triggering for all
>>>@@ -2135,20 +2150,35 @@ void omap2_gpio_prepare_for_idle(int
>>>power_state)
>>>
>>> c++;
>>> }
>>>- if (!c) {
>>>- workaround_enabled = 0;
>>>- return;
>>>- }
>>>- workaround_enabled = 1;
>>>+ if (c)
>>>+ workaround_enabled = 1;
>>>+
>>>+ if (cpu_is_omap34xx() && (per_next_state == PWRDM_POWER_OFF))
>>>+ omap3_gpio_save_context();
>>> }
>>>
>>> void omap2_gpio_resume_after_idle(void)
>>> {
>>>- int i;
>>>- int min = 0;
>>>+ int i, min = 0;
>>>+ int per_next_state;
>>>+
>>>+ if (!per_pwrdm)
>>>+ return;
>>>+
>>>+ per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
>>>+ if (per_next_state >= PWRDM_POWER_INACTIVE)
>>>+ return;
>>>+
>>>+ if (cpu_is_omap34xx() && (per_next_state == PWRDM_POWER_OFF)) {
>>>+ int per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
>>>+
>>>+ if (per_prev_state == PWRDM_POWER_OFF)
>>>+ omap3_gpio_restore_context();
>>>+ }
>>>
>>> if (cpu_is_omap34xx())
>>> min = 1;
>>>+
>>> for (i = min; i < gpio_bank_count; i++) {
>>> struct gpio_bank *bank = &gpio_bank[i];
>>> u32 l, gen, gen0, gen1;
>>>@@ -2235,14 +2265,13 @@ void omap2_gpio_resume_after_idle(void)
>>> }
>>> }
>>> }
>>>-
>>> }
>>>
>>> #endif
>>>
>>> #ifdef CONFIG_ARCH_OMAP3
>>> /* save the registers of bank 2-6 */
>>>-void omap_gpio_save_context(void)
>>>+static void omap3_gpio_save_context(void)
>>> {
>>> int i;
>>>
>>>@@ -2275,7 +2304,7 @@ void omap_gpio_save_context(void)
>>> }
>>>
>>> /* restore the required registers of bank 2-6 */
>>>-void omap_gpio_restore_context(void)
>>>+static void omap3_gpio_restore_context(void)
>>> {
>>> int i;
>>>
>>>diff --git a/arch/arm/plat-omap/include/plat/gpio.h
>>>b/arch/arm/plat-omap/include/plat/gpio.h
>>>index de1c604..c81ef94 100644
>>>--- a/arch/arm/plat-omap/include/plat/gpio.h
>>>+++ b/arch/arm/plat-omap/include/plat/gpio.h
>>>@@ -72,12 +72,10 @@
>>> IH_GPIO_BASE + (nr))
>>>
>>> extern int omap_gpio_init(void); /* Call from board init only */
>>>-extern void omap2_gpio_prepare_for_idle(int power_state);
>>>+extern void omap2_gpio_prepare_for_idle(void);
>>> extern void omap2_gpio_resume_after_idle(void);
>>> extern void omap_set_gpio_debounce(int gpio, int enable);
>>> extern void omap_set_gpio_debounce_time(int gpio, int enable);
>>>-extern void omap_gpio_save_context(void);
>>>-extern void omap_gpio_restore_context(void);
>>>
>>>/*-------------------------------------------------------------
>>>------------*/
>>>
>>> /* Wrappers for "new style" GPIO calls, using the new infrastructure
>>>--
>>>1.7.2.1
>>>
>>>--
>>>To unsubscribe from this list: send the line "unsubscribe
>>>linux-omap" in
>>>the body of a message to [email protected]
>>>More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html