From patchwork Mon Jun 27 16:11:41 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benoit Cousson X-Patchwork-Id: 921542 X-Patchwork-Delegate: b-cousson@ti.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p5RGD3D9028999 for ; Mon, 27 Jun 2011 16:13:03 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752684Ab1F0QNA (ORCPT ); Mon, 27 Jun 2011 12:13:00 -0400 Received: from bear.ext.ti.com ([192.94.94.41]:59790 "EHLO bear.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752665Ab1F0QM7 (ORCPT ); Mon, 27 Jun 2011 12:12:59 -0400 Received: from dlep35.itg.ti.com ([157.170.170.118]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id p5RGCvwl004743 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 27 Jun 2011 11:12:57 -0500 Received: from dlep26.itg.ti.com (smtp-le.itg.ti.com [157.170.170.27]) by dlep35.itg.ti.com (8.13.7/8.13.8) with ESMTP id p5RGCuL8011204; Mon, 27 Jun 2011 11:12:57 -0500 (CDT) Received: from dlee73.ent.ti.com (localhost [127.0.0.1]) by dlep26.itg.ti.com (8.13.8/8.13.8) with ESMTP id p5RGCuFq023632; Mon, 27 Jun 2011 11:12:56 -0500 (CDT) Received: from dlelxv22.itg.ti.com (172.17.1.197) by DLEE73.ent.ti.com (157.170.170.88) with Microsoft SMTP Server id 8.3.106.1; Mon, 27 Jun 2011 11:12:56 -0500 Received: from localhost.localdomain (lncpu04.tif.ti.com [137.167.102.15]) by dlelxv22.itg.ti.com (8.13.8/8.13.8) with ESMTP id p5RGCgaH030849; Mon, 27 Jun 2011 11:12:55 -0500 From: Benoit Cousson To: , CC: santosh.shilimkar@ti.com, linux-omap@vger.kernel.org, toddpoynor@google.com, Benoit Cousson Subject: [PATCH v3 6/8] OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework Date: Mon, 27 Jun 2011 18:11:41 +0200 Message-ID: <1309191103-8817-7-git-send-email-b-cousson@ti.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1309191103-8817-1-git-send-email-b-cousson@ti.com> References: <1309191103-8817-1-git-send-email-b-cousson@ti.com> MIME-Version: 1.0 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]); Mon, 27 Jun 2011 16:13:04 +0000 (UTC) Duplicate the existing API for clockdomain enable from clock to enable a clock domain from hwmod framework. This will be needed when the hwmod framework will move from the current clock centric approach to the module based approach. Signed-off-by: Benoit Cousson Cc: Paul Walmsley Cc: Rajendra Nayak --- arch/arm/mach-omap2/clockdomain.c | 132 +++++++++++++++++++++++++++---------- arch/arm/mach-omap2/clockdomain.h | 3 + 2 files changed, 100 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 3f2a8e7..a1b22cd 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -817,7 +817,50 @@ int clkdm_allows_idle(struct clockdomain *clkdm) } -/* Clockdomain-to-clock framework interface code */ +/* Clockdomain-to-clock/hwmod framework interface code */ + +static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) +{ + if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable) + return -EINVAL; + + /* + * For arch's with no autodeps, clkcm_clk_enable + * should be called for every clock instance or hwmod that is + * enabled, so the clkdm can be force woken up. + */ + if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) + return 0; + + arch_clkdm->clkdm_clk_enable(clkdm); + pwrdm_wait_transition(clkdm->pwrdm.ptr); + pwrdm_clkdm_state_switch(clkdm); + + pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name); + + return 0; +} + +static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm) +{ + if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) + return -EINVAL; + + if (atomic_read(&clkdm->usecount) == 0) { + WARN_ON(1); /* underflow */ + return -ERANGE; + } + + if (atomic_dec_return(&clkdm->usecount) > 0) + return 0; + + arch_clkdm->clkdm_clk_disable(clkdm); + pwrdm_clkdm_state_switch(clkdm); + + pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name); + + return 0; +} /** * clkdm_clk_enable - add an enabled downstream clock to this clkdm @@ -840,25 +883,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) * downstream clocks for debugging purposes? */ - if (!clkdm || !clk) - return -EINVAL; - - if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable) + if (!clk) return -EINVAL; - if (atomic_inc_return(&clkdm->usecount) > 1) - return 0; - - /* Clockdomain now has one enabled downstream clock */ - - pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, - clk->name); - - arch_clkdm->clkdm_clk_enable(clkdm); - pwrdm_wait_transition(clkdm->pwrdm.ptr); - pwrdm_clkdm_state_switch(clkdm); - - return 0; + return _clkdm_clk_hwmod_enable(clkdm); } /** @@ -882,30 +910,64 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) * downstream clocks for debugging purposes? */ - if (!clkdm || !clk) + if (!clk) return -EINVAL; - if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable) - return -EINVAL; + return _clkdm_clk_hwmod_disable(clkdm); +} -#ifdef DEBUG - if (atomic_read(&clkdm->usecount) == 0) { - WARN_ON(1); /* underflow */ - return -ERANGE; - } -#endif +/** + * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm + * @clkdm: struct clockdomain * + * @oh: struct omap_hwmod * of the enabled downstream hwmod + * + * Increment the usecount of the clockdomain @clkdm and ensure that it + * is awake before @oh is enabled. Intended to be called by + * module_enable() code. + * If the clockdomain is in software-supervised idle mode, force the + * clockdomain to wake. If the clockdomain is in hardware-supervised idle + * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the + * clockdomain can be read from/written to by on-chip processors. + * Returns -EINVAL if passed null pointers; + * returns 0 upon success or if the clockdomain is in hwsup idle mode. + */ +int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh) +{ + /* + * XXX Rewrite this code to maintain a list of enabled + * downstream hwmods for debugging purposes? + */ - if (atomic_dec_return(&clkdm->usecount) > 0) - return 0; + if (!oh) + return -EINVAL; - /* All downstream clocks of this clockdomain are now disabled */ + return _clkdm_clk_hwmod_enable(clkdm); +} - pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, - clk->name); +/** + * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm + * @clkdm: struct clockdomain * + * @oh: struct omap_hwmod * of the disabled downstream hwmod + * + * Decrement the usecount of this clockdomain @clkdm when @oh is + * disabled. Intended to be called by module_disable() code. + * If the clockdomain usecount goes to 0, put the clockdomain to sleep + * (software-supervised mode) or remove the clkdm autodependencies + * (hardware-supervised mode). + * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount + * underflows and debugging is enabled; or returns 0 upon success or if the + * clockdomain is in hwsup idle mode. + */ +int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) +{ + /* + * XXX Rewrite this code to maintain a list of enabled + * downstream hwmods for debugging purposes? + */ - arch_clkdm->clkdm_clk_disable(clkdm); - pwrdm_clkdm_state_switch(clkdm); + if (!oh) + return -EINVAL; - return 0; + return _clkdm_clk_hwmod_disable(clkdm); } diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 2d3d970..8f0a7d6 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -20,6 +20,7 @@ #include "powerdomain.h" #include +#include #include /* @@ -186,6 +187,8 @@ int clkdm_sleep(struct clockdomain *clkdm); int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); +int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh); +int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh); extern void __init omap2xxx_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void);