From patchwork Sun Dec 9 01:23:40 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Walmsley X-Patchwork-Id: 1853441 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 3A6AFDF223 for ; Sun, 9 Dec 2012 01:28:49 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1ThVeM-0001sE-2W; Sun, 09 Dec 2012 01:25:46 +0000 Received: from utopia.booyaka.com ([74.50.51.50]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1ThVdC-0001am-I0 for linux-arm-kernel@lists.infradead.org; Sun, 09 Dec 2012 01:24:44 +0000 Received: (qmail 8505 invoked by uid 1019); 9 Dec 2012 01:24:31 -0000 MBOX-Line: From nobody Sat Dec 8 18:23:40 2012 Subject: [PATCH 05/10] ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code To: linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org From: Paul Walmsley Date: Sat, 08 Dec 2012 18:23:40 -0700 Message-ID: <20121209012339.19716.10548.stgit@dusk.lan> In-Reply-To: <20121209011755.19716.25244.stgit@dusk.lan> References: <20121209011755.19716.25244.stgit@dusk.lan> User-Agent: StGit/0.16-37-g27ac3 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121208_202435_060394_3D7F0674 X-CRM114-Status: GOOD ( 19.54 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Kevin Hilman , Jean Pihet X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Move omap_set_pwrdm_state() from the PM code to the powerdomain code, and refactor it to split it up into several functions. A subsequent patch will rename it to conform with the existing powerdomain function names. Signed-off-by: Paul Walmsley Cc: Jean Pihet Cc: Kevin Hilman --- arch/arm/mach-omap2/pm.c | 61 -------------------- arch/arm/mach-omap2/pm.h | 1 arch/arm/mach-omap2/powerdomain.c | 112 +++++++++++++++++++++++++++---------- arch/arm/mach-omap2/powerdomain.h | 3 + 4 files changed, 85 insertions(+), 92 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index cc8ed0f..2e2a897 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -76,10 +76,6 @@ static void __init omap2_init_processor_devices(void) } } -/* Types of sleep_switch used in omap_set_pwrdm_state */ -#define FORCEWAKEUP_SWITCH 0 -#define LOWPOWERSTATE_SWITCH 1 - int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) { if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) && @@ -92,63 +88,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) } /* - * This sets pwrdm state (other than mpu & core. Currently only ON & - * RET are supported. - */ -int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst) -{ - u8 curr_pwrst, next_pwrst; - int sleep_switch = -1, ret = 0, hwsup = 0; - - if (!pwrdm || IS_ERR(pwrdm)) - return -EINVAL; - - while (!(pwrdm->pwrsts & (1 << pwrst))) { - if (pwrst == PWRDM_POWER_OFF) - return ret; - pwrst--; - } - - next_pwrst = pwrdm_read_next_pwrst(pwrdm); - if (next_pwrst == pwrst) - return ret; - - curr_pwrst = pwrdm_read_pwrst(pwrdm); - if (curr_pwrst < PWRDM_POWER_ON) { - if ((curr_pwrst > pwrst) && - (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { - sleep_switch = LOWPOWERSTATE_SWITCH; - } else { - hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); - clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); - sleep_switch = FORCEWAKEUP_SWITCH; - } - } - - ret = pwrdm_set_next_pwrst(pwrdm, pwrst); - if (ret) - pr_err("%s: unable to set power state of powerdomain: %s\n", - __func__, pwrdm->name); - - switch (sleep_switch) { - case FORCEWAKEUP_SWITCH: - if (hwsup) - clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); - else - clkdm_sleep(pwrdm->pwrdm_clkdms[0]); - break; - case LOWPOWERSTATE_SWITCH: - pwrdm_set_lowpwrstchange(pwrdm); - pwrdm_state_switch(pwrdm); - break; - } - - return ret; -} - - - -/* * This API is to be called during init to set the various voltage * domains to the voltage as per the opp table. Typically we boot up * at the nominal voltage. So this function finds out the rate of diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 686137d..707e9cb 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -33,7 +33,6 @@ static inline int omap4_idle_init(void) extern void *omap3_secure_ram_storage; extern void omap3_pm_off_mode_enable(int); extern void omap_sram_idle(void); -extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused); extern int (*omap_pm_suspend)(void); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 97b3881..05f00660 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -921,35 +921,6 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0; } -/** - * pwrdm_set_lowpwrstchange - Request a low power state change - * @pwrdm: struct powerdomain * - * - * Allows a powerdomain to transtion to a lower power sleep state - * from an existing sleep state without waking up the powerdomain. - * Returns -EINVAL if the powerdomain pointer is null or if the - * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0 - * upon success. - */ -int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) -{ - int ret = -EINVAL; - - if (!pwrdm) - return -EINVAL; - - if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) - return -EINVAL; - - pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n", - pwrdm->name); - - if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange) - ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm); - - return ret; -} - int pwrdm_state_switch(struct powerdomain *pwrdm) { int ret; @@ -984,6 +955,89 @@ int pwrdm_post_transition(struct powerdomain *pwrdm) return 0; } +/* Types of sleep_switch used in omap_set_pwrdm_state */ +#define ALREADYACTIVE_SWITCH 0 +#define FORCEWAKEUP_SWITCH 1 +#define LOWPOWERSTATE_SWITCH 2 + +static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm, + u8 pwrst, bool *hwsup) +{ + u8 curr_pwrst, sleep_switch; + + curr_pwrst = pwrdm_read_pwrst(pwrdm); + if (curr_pwrst < PWRDM_POWER_ON) { + if (curr_pwrst > pwrst && + pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE && + arch_pwrdm->pwrdm_set_lowpwrstchange) { + sleep_switch = LOWPOWERSTATE_SWITCH; + } else { + *hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); + clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); + sleep_switch = FORCEWAKEUP_SWITCH; + } + } else { + sleep_switch = ALREADYACTIVE_SWITCH; + } + + return sleep_switch; +} + +static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm, + u8 sleep_switch, bool hwsup) +{ + switch (sleep_switch) { + case FORCEWAKEUP_SWITCH: + if (hwsup) + clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); + else + clkdm_sleep(pwrdm->pwrdm_clkdms[0]); + break; + case LOWPOWERSTATE_SWITCH: + if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE && + arch_pwrdm->pwrdm_set_lowpwrstchange) + arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm); + pwrdm_state_switch(pwrdm); + break; + } +} + +/* + * This sets pwrdm state (other than mpu & core. Currently only ON & + * RET are supported. + */ +int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst) +{ + u8 next_pwrst, sleep_switch; + int ret = 0; + bool hwsup = false; + + if (!pwrdm || IS_ERR(pwrdm)) + return -EINVAL; + + while (!(pwrdm->pwrsts & (1 << pwrst))) { + if (pwrst == PWRDM_POWER_OFF) + return ret; + pwrst--; + } + + next_pwrst = pwrdm_read_next_pwrst(pwrdm); + if (next_pwrst == pwrst) + return ret; + + sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, pwrst, + &hwsup); + + ret = pwrdm_set_next_pwrst(pwrdm, pwrst); + if (ret) + pr_err("%s: unable to set power state of powerdomain: %s\n", + __func__, pwrdm->name); + + _pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup); + + return ret; +} + /** * pwrdm_get_context_loss_count - get powerdomain's context loss count * @pwrdm: struct powerdomain * to wait for diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 7c1534b..1edb3b7 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -228,10 +228,11 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); int pwrdm_state_switch(struct powerdomain *pwrdm); int pwrdm_pre_transition(struct powerdomain *pwrdm); int pwrdm_post_transition(struct powerdomain *pwrdm); -int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state); + extern void omap242x_powerdomains_init(void); extern void omap243x_powerdomains_init(void); extern void omap3xxx_powerdomains_init(void);