From patchwork Fri Jun 24 12:06:33 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benoit Cousson X-Patchwork-Id: 916012 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 p5OC92NK022202 for ; Fri, 24 Jun 2011 12:09:03 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755946Ab1FXMIt (ORCPT ); Fri, 24 Jun 2011 08:08:49 -0400 Received: from comal.ext.ti.com ([198.47.26.152]:54282 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755768Ab1FXMIo (ORCPT ); Fri, 24 Jun 2011 08:08:44 -0400 Received: from dlep33.itg.ti.com ([157.170.170.112]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id p5OC8h7V018324 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 24 Jun 2011 07:08:43 -0500 Received: from dlep26.itg.ti.com (smtp-le.itg.ti.com [157.170.170.27]) by dlep33.itg.ti.com (8.13.7/8.13.8) with ESMTP id p5OC8gwD020679; Fri, 24 Jun 2011 07:08:42 -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 p5OC8gm5005247; Fri, 24 Jun 2011 07:08:42 -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; Fri, 24 Jun 2011 07:08:42 -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 p5OC8KmP032613; Fri, 24 Jun 2011 07:08:41 -0500 From: Benoit Cousson To: , CC: santosh.shilimkar@ti.com, linux-omap@vger.kernel.org, Benoit Cousson Subject: [PATCH v2 7/7] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence Date: Fri, 24 Jun 2011 14:06:33 +0200 Message-ID: <1308917193-16912-8-git-send-email-b-cousson@ti.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1308917193-16912-1-git-send-email-b-cousson@ti.com> References: <1308917193-16912-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]); Fri, 24 Jun 2011 12:09:03 +0000 (UTC) From: Nayak, Rajendra On OMAP4, the PRCM recommended sequence for enabling a module after power-on-reset is: -1- Force clkdm to SW_WKUP -2- Enabling the clocks -3- Configure desired module mode to "enable" or "auto" -4- Wait for the desired module idle status to be FUNC -5- Program clkdm in HW_AUTO(if supported) This sequence applies to all older OMAPs' as well, however since they use autodeps, it makes sure that no clkdm is in IDLE, and hence not requiring a force SW_WKUP when a module is being enabled. OMAP4 does not need to support autodeps, because of the dyanamic dependency feature, wherein the HW takes care of waking up a clockdomain from idle and hence the module, whenever an interconnect access happens to the given module. Implementing the sequence for OMAP4 requires the clockdomain handling that is currently done in clock framework to be done as part of hwmod framework since the step -4- above to "Wait for the desired module idle status to be FUNC" is done as part of hwmod framework. Signed-off-by: Rajendra Nayak [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API] Signed-off-by: Benoit Cousson Cc: Paul Walmsley --- arch/arm/mach-omap2/clock.c | 17 +---------------- arch/arm/mach-omap2/clockdomain44xx.c | 9 +-------- arch/arm/mach-omap2/omap_hwmod.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 180299e..2828d29 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -268,9 +268,6 @@ void omap2_clk_disable(struct clk *clk) clk->ops->disable(clk); } - if (clk->clkdm) - clkdm_clk_disable(clk->clkdm, clk); - if (clk->parent) omap2_clk_disable(clk->parent); } @@ -308,30 +305,18 @@ int omap2_clk_enable(struct clk *clk) } } - if (clk->clkdm) { - ret = clkdm_clk_enable(clk->clkdm, clk); - if (ret) { - WARN(1, "clock: %s: could not enable clockdomain %s: " - "%d\n", clk->name, clk->clkdm->name, ret); - goto oce_err2; - } - } - if (clk->ops && clk->ops->enable) { trace_clock_enable(clk->name, 1, smp_processor_id()); ret = clk->ops->enable(clk); if (ret) { WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret); - goto oce_err3; + goto oce_err2; } } return 0; -oce_err3: - if (clk->clkdm) - clkdm_clk_disable(clk->clkdm, clk); oce_err2: if (clk->parent) omap2_clk_disable(clk->parent); diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index 4b10727..e4b8e06 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -101,14 +101,7 @@ static int omap4_clkdm_is_idle(struct clockdomain *clkdm) static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) { - bool hwsup = false; - - hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, clkdm->clkdm_offs); - - if (!hwsup) - clkdm_wakeup(clkdm); - + clkdm_wakeup(clkdm); return 0; } diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 6b144c4..cb85f65 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1360,6 +1360,7 @@ static int _reset(struct omap_hwmod *oh) static int _enable(struct omap_hwmod *oh) { int r; + int hwsup = 0; if (oh->_state != _HWMOD_STATE_INITIALIZED && oh->_state != _HWMOD_STATE_IDLE && @@ -1378,6 +1379,19 @@ static int _enable(struct omap_hwmod *oh) omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); _add_initiator_dep(oh, mpu_oh); + + /* + * A clockdomain must be in SW_SUP before enabling completely the + * module. The clockdomain can be set in HW_AUTO only when the module + * become ready. + */ + hwsup = clkdm_is_idle(oh->clkdm); + r = clkdm_hwmod_enable(oh->clkdm, oh); + if (r) { + WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n", + oh->name, oh->clkdm->name, r); + return r; + } _enable_clocks(oh); _enable_module(oh); @@ -1392,6 +1406,13 @@ static int _enable(struct omap_hwmod *oh) r = _wait_target_ready(oh); if (!r) { + /* + * Set the clockdomain to HW_AUTO only if the target is ready, + * assuming that the previous state was HW_AUTO + */ + if (hwsup) + clkdm_allow_idle(oh->clkdm); + oh->_state = _HWMOD_STATE_ENABLED; /* Access the sysconfig only if the target is ready */ @@ -1402,8 +1423,9 @@ static int _enable(struct omap_hwmod *oh) } } else { _disable_clocks(oh); - pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", - oh->name, r); + clkdm_hwmod_disable(oh->clkdm, oh); + pr_warning("omap_hwmod: %s: _wait_target_ready failed: %d\n", + oh->name, r); } return r; @@ -1444,6 +1466,7 @@ static int _idle(struct omap_hwmod *oh) * transition to complete properly. */ _disable_clocks(oh); + clkdm_hwmod_disable(oh->clkdm, oh); /* Mux pins for device idle if populated */ if (oh->mux && oh->mux->pads_dynamic) @@ -1541,6 +1564,7 @@ static int _shutdown(struct omap_hwmod *oh) pr_warning("omap_hwmod: %s: _wait_target_disable failed\n", oh->name); _disable_clocks(oh); + clkdm_hwmod_disable(oh->clkdm, oh); } /* XXX Should this code also force-disable the optional clocks? */