From patchwork Fri Jan 21 10:37:05 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tero Kristo X-Patchwork-Id: 494581 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0L9Vhbo013996 for ; Fri, 21 Jan 2011 09:31:43 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751755Ab1AUJbm (ORCPT ); Fri, 21 Jan 2011 04:31:42 -0500 Received: from smtp.nokia.com ([147.243.128.24]:51836 "EHLO mgw-da01.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751001Ab1AUJbl (ORCPT ); Fri, 21 Jan 2011 04:31:41 -0500 Received: from sokoban.nmp.nokia.com (sokoban.nmp.nokia.com [172.22.215.13]) by mgw-da01.nokia.com (Switch-3.4.3/Switch-3.4.3) with ESMTP id p0L9Va9H032227; Fri, 21 Jan 2011 11:31:36 +0200 From: Tero Kristo To: linux-omap@vger.kernel.org Cc: Paul Walmsley , Kevin Hilman , Santosh Shilimkar , Vishwanath Sripathy Subject: [PATCHv2] OMAP3: CPUIdle: prevent CORE from going off if doing so would reset an active clockdomain Date: Fri, 21 Jan 2011 12:37:05 +0200 Message-Id: <1295606225-11834-1-git-send-email-tero.kristo@nokia.com> X-Mailer: git-send-email 1.7.1 X-Nokia-AV: Clean Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 21 Jan 2011 09:31:44 +0000 (UTC) diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index f3e043f..d31b858 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -61,7 +61,7 @@ struct omap3_processor_cx { struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES]; struct omap3_processor_cx current_cx_state; struct powerdomain *mpu_pd, *core_pd, *per_pd; -struct powerdomain *cam_pd; +struct powerdomain *cam_pd, *dss_pd, *iva2_pd, *sgx_pd, *usb_pd; /* * The latencies/thresholds for various C states have @@ -235,7 +235,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, { struct cpuidle_state *new_state = next_valid_state(dev, state); u32 core_next_state, per_next_state = 0, per_saved_state = 0; - u32 cam_state; + u32 cam_state, dss_state, iva2_state, sgx_state, usb_state; struct omap3_processor_cx *cx; int ret; @@ -256,6 +256,8 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * its own code. */ + /* XXX Add CORE-active check here */ + /* * Prevent idle completely if CAM is active. * CAM does not have wakeup capability in OMAP3. @@ -275,6 +277,36 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, (core_next_state > PWRDM_POWER_RET)) per_next_state = PWRDM_POWER_RET; + /* XXX Add prevent-PER-off check here */ + + /* + * If we are attempting CORE off, check if any other powerdomains + * are at retention or higher. CORE off causes chipwide reset which + * would reset these domains also. + */ + if (core_next_state == PWRDM_POWER_OFF) { + iva2_state = pwrdm_read_pwrst(iva2_pd); + sgx_state = pwrdm_read_pwrst(sgx_pd); + usb_state = pwrdm_read_pwrst(usb_pd); + dss_state = pwrdm_read_pwrst(dss_pd); + + if (cam_state > PWRDM_POWER_OFF || + dss_state > PWRDM_POWER_OFF || + iva2_state > PWRDM_POWER_OFF || + per_next_state > PWRDM_POWER_OFF || + sgx_state > PWRDM_POWER_OFF || + usb_state > PWRDM_POWER_OFF) + core_next_state = PWRDM_POWER_RET; + } + + /* Fallback to new target core/mpu state */ + while (cx->core_state < core_next_state) { + state--; + cx = cpuidle_get_statedata(state); + } + + new_state = state; + /* Are we changing PER target state? */ if (per_next_state != per_saved_state) pwrdm_set_next_pwrst(per_pd, per_next_state); @@ -489,6 +521,10 @@ int __init omap3_idle_init(void) core_pd = pwrdm_lookup("core_pwrdm"); per_pd = pwrdm_lookup("per_pwrdm"); cam_pd = pwrdm_lookup("cam_pwrdm"); + dss_pd = pwrdm_lookup("dss_pwrdm"); + iva2_pd = pwrdm_lookup("iva2_pwrdm"); + sgx_pd = pwrdm_lookup("sgx_pwrdm"); + usb_pd = pwrdm_lookup("usbhost_pwrdm"); omap_init_power_states(); cpuidle_register_driver(&omap3_idle_driver);