From patchwork Wed Jun 8 00:39:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nishanth Menon X-Patchwork-Id: 860252 X-Patchwork-Delegate: khilman@deeprootsystems.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p580dbn5000877 for ; Wed, 8 Jun 2011 00:39:37 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754141Ab1FHAjg (ORCPT ); Tue, 7 Jun 2011 20:39:36 -0400 Received: from na3sys009aog107.obsmtp.com ([74.125.149.197]:52673 "EHLO na3sys009aog107.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753696Ab1FHAjg (ORCPT ); Tue, 7 Jun 2011 20:39:36 -0400 Received: from mail-yx0-f169.google.com ([209.85.213.169]) (using TLSv1) by na3sys009aob107.postini.com ([74.125.148.12]) with SMTP ID DSNKTe7Ex8gBkv3aq+kLMwH82Cd4PyhF1d19@postini.com; Tue, 07 Jun 2011 17:39:36 PDT Received: by mail-yx0-f169.google.com with SMTP id 22so335yxn.0 for ; Tue, 07 Jun 2011 17:39:35 -0700 (PDT) Received: by 10.236.161.232 with SMTP id w68mr1666985yhk.24.1307493573789; Tue, 07 Jun 2011 17:39:33 -0700 (PDT) Received: from localhost (dragon.ti.com [192.94.94.33]) by mx.google.com with ESMTPS id v22sm454399yhm.34.2011.06.07.17.39.32 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 07 Jun 2011 17:39:32 -0700 (PDT) From: Nishanth Menon To: linux-omap Cc: kevin , Nishanth Menon Subject: [pm-wip/voltdm_nm][PATCH 10/10] OMAP2+: PM: init_voltages: handle non compliant bootloaders Date: Tue, 7 Jun 2011 19:39:28 -0500 Message-Id: <1307493568-31798-1-git-send-email-nm@ti.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <[pm-wip/voltdm_nm][PATCH 00/10] OMAP2+: voltage: fixes> References: <[pm-wip/voltdm_nm][PATCH 00/10] OMAP2+: voltage: fixes> 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 (demeter2.kernel.org [140.211.167.43]); Wed, 08 Jun 2011 00:39:38 +0000 (UTC) Bootloaders should in theory setup a frequency which is enabled in OPP table. However, there can be mismatches, and we should try both going lower in addition to the going higher to find a match if bootloader boots up at a OPP than the kernel thinks it should be allowed. We also sequence the frequency and voltage settings properly. Reported-by: Colin Cross Signed-off-by: Nishanth Menon --- PS: Apologies on the spam.. for some reason 10/10 never appeared in http://marc.info/?l=linux-omap&r=2&b=201106&w=2 - grumble grumble :( arch/arm/mach-omap2/pm.c | 55 ++++++++++++++++++++++++++++++++++++--------- 1 files changed, 44 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 7355347..ce7554b 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -174,7 +174,9 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, struct voltagedomain *voltdm; struct clk *clk; struct opp *opp; - unsigned long freq, bootup_volt; + unsigned long freq_cur, freq_valid, bootup_volt; + int raise_freq_idx, i; + int ret = -EINVAL; if (!vdd_name || !clk_name || !dev) { printk(KERN_ERR "%s: Invalid parameters!\n", __func__); @@ -195,16 +197,20 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, goto exit; } - freq = clk->rate; - clk_put(clk); + freq_cur = clk->rate; + freq_valid = freq_cur; rcu_read_lock(); - opp = opp_find_freq_ceil(dev, &freq); + opp = opp_find_freq_ceil(dev, &freq_valid); if (IS_ERR(opp)) { - rcu_read_unlock(); - printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n", - __func__, vdd_name); - goto exit; + opp = opp_find_freq_floor(dev, &freq_valid); + if (IS_ERR(opp)) { + rcu_read_unlock(); + pr_err("%s: no boot OPP match for %ld on vdd_%s\n", + __func__, freq_cur, vdd_name); + ret = -ENOENT; + goto exit_ck; + } } bootup_volt = opp_get_voltage(opp); @@ -212,11 +218,38 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, if (!bootup_volt) { printk(KERN_ERR "%s: unable to find voltage corresponding" "to the bootup OPP for vdd_%s\n", __func__, vdd_name); - goto exit; + ret = -ENOENT; + goto exit_ck; } - voltdm_scale(voltdm, bootup_volt); - return 0; + /* + * Frequency and Voltage have to be sequenced: if we move from + * a lower frequency to higher frequency, raise voltage, followed by + * frequency, and vice versa. we assume that the voltage at boot + * is the required voltage for the frequency it was set for. + */ + raise_freq_idx = freq_cur < freq_valid; + for (i = 0; i < 2; i++) { + if (i == raise_freq_idx) + ret = clk_set_rate(clk, freq_valid); + else + ret = voltdm_scale(voltdm, bootup_volt); + if (ret < 0) { + pr_err("%s: unable to set %s-%s(f=%ld v=%ld)on vdd%s\n", + __func__, + (i == raise_freq_idx) ? "clk" : "voltage", + (i == raise_freq_idx) ? clk_name : vdd_name, + freq_valid, bootup_volt, vdd_name); + goto exit_ck; + } + } + + ret = 0; +exit_ck: + clk_put(clk); + + if (!ret) + return 0; exit: printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",