From patchwork Mon Apr 20 12:54:04 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Francesco VIRLINZI X-Patchwork-Id: 19011 X-Patchwork-Delegate: lethal@linux-sh.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n3KCsKjg020761 for ; Mon, 20 Apr 2009 12:54:21 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754985AbZDTMyU (ORCPT ); Mon, 20 Apr 2009 08:54:20 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754899AbZDTMyU (ORCPT ); Mon, 20 Apr 2009 08:54:20 -0400 Received: from eu1sys200aog117.obsmtp.com ([207.126.144.143]:43703 "EHLO eu1sys200aog117.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754851AbZDTMyT (ORCPT ); Mon, 20 Apr 2009 08:54:19 -0400 Received: from source ([164.129.1.35]) (using TLSv1) by eu1sys200aob117.postini.com ([207.126.147.11]) with SMTP ID DSNKSexwee5eily6tXQsrAuMdGoosNiyCAj8@postini.com; Mon, 20 Apr 2009 12:54:19 UTC Received: from zeta.dmz-eu.st.com (ns2.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 8147DDB5D for ; Mon, 20 Apr 2009 12:53:00 +0000 (GMT) Received: from mail1.ctn.st.com (mail1.ctn.st.com [164.130.116.128]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id D41CD4C4FA for ; Mon, 20 Apr 2009 12:54:12 +0000 (GMT) Received: from [10.52.139.41] (mdt-dhcp41.ctn.st.com [10.52.139.41]) by mail1.ctn.st.com (MOS 3.8.7a) with ESMTP id DAM54082 (AUTH virlinzi); Mon, 20 Apr 2009 14:54:11 +0200 (CEST) Message-ID: <49EC706C.4000302@st.com> Date: Mon, 20 Apr 2009 14:54:04 +0200 From: Francesco VIRLINZI User-Agent: Thunderbird 2.0.0.21 (X11/20090320) MIME-Version: 1.0 To: Linux-sh Cc: Francesco VIRLINZI Subject: [Proposal][PATCH] sh: clkfwk: Add resume from standby support. Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org Hi all As already done to resume from hibernation I would add a standard way to manage the resume from standby in the clock framework. To do that each clock has to declare to the clock framework what it has to do with the clock it-self. As general rule during a standby a clock can be: - reduced or - disabled therefore in the flags field the clock has to specify what it wants. The ratio in standby is a specified with the highest 16 bits in the flags fields with a rule: #define CLK_PM_EXP_SHIFT (24) #define CLK_PM_RATIO_SHIFT (16) ratio = ((clk->flags >> CLK_PM_RATIO_SHIFT) & 0xff) << ((clk->flags >> CLK_PM_EXP_SHIFT) & 0xff); While to enable/disable I'm using the convention that if the (clk->flags & CLK_PM_TURNOFF) == CLK_PM_TURNOFF) than the clock has to be disabled. In this manned in a single place (where the clock topology is designed) the developers can design also the configuration during the standby. What do you think? Regards Francesco From 5d0c1dec07c65f8de13c9f60a0465060ec2e5e24 Mon Sep 17 00:00:00 2001 From: Francesco Virlinzi Date: Mon, 20 Apr 2009 14:26:58 +0200 Subject: [PATCH] sh: clkfwk: Add resume from standby support. Add the resume from standby support to the clock framework. Each clock in the flags field specifies how it has to be managed during a standby operation. Signed-off-by: Francesco Virlinzi --- arch/sh/include/asm/clock.h | 5 +++ arch/sh/kernel/cpu/clock.c | 76 +++++++++++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index 2f6c962..f132db9 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -38,6 +38,11 @@ struct clk { #define CLK_ALWAYS_ENABLED (1 << 0) #define CLK_RATE_PROPAGATES (1 << 1) +#define CLK_PM_MASK (0xff) +#define CLK_PM_EXP_SHIFT (24) +#define CLK_PM_RATIO_SHIFT (16) +#define CLK_PM_TURNOFF (CLK_PM_MASK << CLK_PM_EXP_SHIFT) + /* Should be defined by processor-specific code */ void arch_init_clk_ops(struct clk_ops **, int type); int __init arch_clk_init(void); diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 1dc8964..72df119 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -365,30 +365,72 @@ static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) { static pm_message_t prev_state; struct clk *clkp; + unsigned long rate, ratio; switch (state.event) { - case PM_EVENT_ON: - /* Resumeing from hibernation */ - if (prev_state.event == PM_EVENT_FREEZE) { - list_for_each_entry(clkp, &clock_list, node) - if (likely(clkp->ops)) { - unsigned long rate = clkp->rate; - - if (likely(clkp->ops->set_parent)) - clkp->ops->set_parent(clkp, + case PM_EVENT_ON: /* Resume from: */ + switch (prev_state.event) { + case PM_EVENT_FREEZE: /* Hibernation */ + list_for_each_entry(clkp, &clock_list, node) { + if (!clkp->ops) + continue; + rate = clkp->rate; + + if (likely(clkp->ops->set_parent)) + clkp->ops->set_parent(clkp, clkp->parent); - if (likely(clkp->ops->set_rate)) - clkp->ops->set_rate(clkp, + if (likely(clkp->ops->set_rate)) + clkp->ops->set_rate(clkp, rate, NO_CHANGE); - else if (likely(clkp->ops->recalc)) - clkp->ops->recalc(clkp); - } - } + else if (likely(clkp->ops->recalc)) + clkp->ops->recalc(clkp); + } break; - case PM_EVENT_FREEZE: + case PM_EVENT_SUSPEND: /* Suspend/Standby */ + list_for_each_entry(clkp, &clock_list, node) { + if (!likely(clkp->ops)) + continue; + /* turn-on */ + if ((clkp->flags & CLK_PM_TURNOFF) == CLK_PM_TURNOFF && + clkp->ops->enable) + clkp->ops->enable(clkp); + else + if (likely(clkp->ops->set_rate)) { + ratio = ((clkp->flags >> CLK_PM_RATIO_SHIFT) & CLK_PM_MASK) + << ((clkp->flags >> CLK_PM_EXP_SHIFT) & CLK_PM_MASK); + if (ratio) + clkp->ops->set_rate(clkp, + clkp->rate * ratio, + NO_CHANGE); + } + } break; + } + break; case PM_EVENT_SUSPEND: - break; + /* reduces/turns-off the frequency based + * on the flags directive + */ + list_for_each_entry_reverse(clkp, &clock_list, node) { + if (!clkp->ops) + continue; + /* turn-off */ + if ((clkp->flags & CLK_PM_TURNOFF) == CLK_PM_TURNOFF && + clkp->ops->disable) + clkp->ops->disable(clkp); + else /* reduce */ + if (likely(clkp->ops->set_rate)) { + ratio = ((clkp->flags >> CLK_PM_RATIO_SHIFT) & CLK_PM_MASK) + << ((clkp->flags >> CLK_PM_EXP_SHIFT) & CLK_PM_MASK); + if (ratio) + clkp->ops->set_rate(clkp, + clkp->rate / ratio, + NO_CHANGE); + } + } + break; + case PM_EVENT_FREEZE: + break; } prev_state = state; -- 1.6.0.6