From patchwork Fri Apr 16 21:33:22 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Turquette X-Patchwork-Id: 93214 X-Patchwork-Delegate: khilman@deeprootsystems.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3GLY7bT031373 for ; Fri, 16 Apr 2010 21:34:11 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932526Ab0DPVeH (ORCPT ); Fri, 16 Apr 2010 17:34:07 -0400 Received: from mail-pw0-f46.google.com ([209.85.160.46]:45575 "EHLO mail-pw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932521Ab0DPVeE (ORCPT ); Fri, 16 Apr 2010 17:34:04 -0400 Received: by pwj9 with SMTP id 9so2363388pwj.19 for ; Fri, 16 Apr 2010 14:34:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=ObcCEbW/TKAcTf5cOiEHrurTxBajU46Yo9fj/KSlORE=; b=D72fVUUN1N+i0qWrofMMFjX7X7d2gRWJu9S05bhzumnrRi+Et/O/ZtiVSpStHhFIRH 2c3BjEaAneA8/LwmUASkMYxKiO/7mi19nFn8sEDpU8uaYK5j4llWAwCPn+MrikL3VP1K PZnP+jivAQoDNmh36ur/OeL7FQHtKJUz1U7tY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=jgVi6dmCkK7I2k6C0chnrPPzOmEUuFVSi2Wq9FVwzsZsuhm+xvtBYoGqOloXsqAK7Q UKnHpEXF0TB65z9nbUkK5XkwLU0qHY5XusCKGyIuf0Nl/HSQqbIeTzmseDLo6vKorRHr K6NA7CM6epZxB5E7KLXM8E6iZgx3knu7hXLDs= Received: by 10.141.88.12 with SMTP id q12mr2577627rvl.188.1271453644103; Fri, 16 Apr 2010 14:34:04 -0700 (PDT) Received: from localhost.localdomain (adsl-99-31-84-167.dsl.rcsntx.sbcglobal.net [99.31.84.167]) by mx.google.com with ESMTPS id 21sm2160016iwn.15.2010.04.16.14.34.02 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 16 Apr 2010 14:34:03 -0700 (PDT) From: Mike Turquette To: linux-omap@vger.kernel.org Cc: Vishwanath Sripathy , Thara Gopinath , Shweta Gulati , Nishanth Menon , Kevin Hilman , Mike Turquette Subject: [PATCH 2/3] OMAP3630: PM: implement Foward Body-Bias for OPP1G Date: Fri, 16 Apr 2010 16:33:22 -0500 Message-Id: <1271453603-21929-3-git-send-email-mturquette@ti.com> X-Mailer: git-send-email 1.7.0.5 In-Reply-To: <1271453603-21929-1-git-send-email-mturquette@ti.com> References: <1271453603-21929-1-git-send-email-mturquette@ti.com> 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.3 (demeter.kernel.org [140.211.167.41]); Fri, 16 Apr 2010 21:34:13 +0000 (UTC) diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index c2c8192..98d8bb3 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -37,6 +37,11 @@ #define VP_IDLE_TIMEOUT 200 #define VP_TRANXDONE_TIMEOUT 300 +#define ABB_MAX_SETTLING_TIME 30 +#define ABB_FAST_OPP 1 +#define ABB_NOMINAL_OPP 2 +#define ABB_SLOW_OPP 3 + /** * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of * board data or PMIC data @@ -635,6 +640,118 @@ static int vp_forceupdate_scale_voltage(u32 vdd, unsigned long target_volt, } /** + * voltscale_adaptive_body_bias - controls ABB ldo during voltage scaling + * @target_volt: target voltage determines if ABB ldo is active or bypassed + * + * Adaptive Body-Bias is a technique in all OMAP silicon that uses the 45nm + * process. ABB can boost voltage in high OPPs for silicon with weak + * characteristics (forward Body-Bias) as well as lower voltage in low OPPs + * for silicon with strong characteristics (Reverse Body-Bias). + * + * Only Foward Body-Bias for operating at high OPPs is implemented below, per + * recommendations from silicon team. + * Reverse Body-Bias for saving power in active cases and sleep cases is not + * yet implemented. + * OMAP4 hardward also supports ABB ldo, but no recommendations have been made + * to implement it yet. + */ +int voltscale_adaptive_body_bias(unsigned long target_volt) +{ + u32 sr2en_enabled; + int timeout; + int sr2_wtcnt_value; + + /* calculate SR2_WTCNT_VALUE settling time */ + sr2_wtcnt_value = (ABB_MAX_SETTLING_TIME * + (clk_get_rate("sys_ck") / 1000000) / 8); + + /* has SR2EN been enabled previously? */ + sr2en_enabled = (prm_read_mod_reg(OMAP3430_GR_MOD, + OMAP3_PRM_LDO_ABB_CTRL_OFFSET) & + OMAP3630_SR2EN); + + /* select fast, nominal or slow OPP for ABB ldo */ + /* FIXME: include OMAP4 once recommendations are complete */ + if (cpu_is_omap3630() && (target_volt >= 1350000)) { + /* program for fast opp - enable FBB */ + prm_rmw_mod_reg_bits(OMAP3630_OPP_SEL_MASK, + (ABB_FAST_OPP << OMAP3630_OPP_SEL_SHIFT), + OMAP3430_GR_MOD, + OMAP3_PRM_LDO_ABB_SETUP_OFFSET); + + /* enable the ABB ldo if not done already */ + if (!sr2en_enabled) + prm_set_mod_reg_bits(OMAP3630_SR2EN, + OMAP3430_GR_MOD, + OMAP3_PRM_LDO_ABB_CTRL_OFFSET); + } else if (sr2en_enabled) { + /* program for nominal opp - bypass ABB ldo */ + prm_rmw_mod_reg_bits(OMAP3630_OPP_SEL_MASK, + (ABB_NOMINAL_OPP << OMAP3630_OPP_SEL_SHIFT), + OMAP3430_GR_MOD, + OMAP3_PRM_LDO_ABB_SETUP_OFFSET); + } else { + /* nothing to do here yet... might enable RBB here someday */ + return 0; + } + + /* set ACTIVE_FBB_SEL for all 45nm silicon */ + prm_set_mod_reg_bits(OMAP3630_ACTIVE_FBB_SEL, + OMAP3430_GR_MOD, + OMAP3_PRM_LDO_ABB_CTRL_OFFSET); + + /* program settling time of 30us for ABB ldo transition */ + prm_rmw_mod_reg_bits(OMAP3630_SR2_WTCNT_VALUE_MASK, + (sr2_wtcnt_value << OMAP3630_SR2_WTCNT_VALUE_SHIFT), + OMAP3430_GR_MOD, + OMAP3_PRM_LDO_ABB_CTRL_OFFSET); + + /* clear ABB ldo interrupt status */ + prm_write_mod_reg(OMAP3630_ABB_LDO_TRANXDONE_ST, + OCP_MOD, + OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); + + /* enable ABB LDO OPP change */ + prm_set_mod_reg_bits(OMAP3630_OPP_CHANGE, + OMAP3430_GR_MOD, + OMAP3_PRM_LDO_ABB_SETUP_OFFSET); + + timeout = 0; + + /* wait until OPP change completes */ + while ((timeout < ABB_MAX_SETTLING_TIME ) && + (!(prm_read_mod_reg(OCP_MOD, + OMAP2_PRCM_IRQSTATUS_MPU_OFFSET) & + OMAP3630_ABB_LDO_TRANXDONE_ST))) { + udelay(1); + timeout++; + } + + if (timeout == ABB_MAX_SETTLING_TIME) + pr_debug("ABB: TRANXDONE timed out waiting for OPP change\n"); + + timeout = 0; + + /* Clear all pending TRANXDONE interrupts/status */ + while (timeout < ABB_MAX_SETTLING_TIME) { + prm_write_mod_reg(OMAP3630_ABB_LDO_TRANXDONE_ST, + OCP_MOD, + OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); + if (!(prm_read_mod_reg(OCP_MOD, + OMAP2_PRCM_IRQSTATUS_MPU_OFFSET) + & OMAP3630_ABB_LDO_TRANXDONE_ST)) + break; + + udelay(1); + timeout++; + } + if (timeout == ABB_MAX_SETTLING_TIME) + pr_debug("ABB: TRANXDONE timed out trying to clear status\n"); + + return 0; +} + +/** * get_curr_vdd1_voltage : Gets the current non-auto-compensated vdd1 voltage * * This is a temporary placeholder for this API. This should ideally belong @@ -758,11 +875,19 @@ void omap_voltageprocessor_disable(int vp_id) int omap_voltage_scale(int vdd, unsigned long target_volt, unsigned long current_volt) { + int ret; + if (voltscale_vpforceupdate) - return vp_forceupdate_scale_voltage(vdd, target_volt, + ret = vp_forceupdate_scale_voltage(vdd, target_volt, current_volt); else - return vc_bypass_scale_voltage(vdd, target_volt, current_volt); + ret = vc_bypass_scale_voltage(vdd, target_volt, current_volt); + + /* FIXME OMAP4 needs ABB too; recommendations not yet complete */ + if (ret && (cpu_is_omap3630() && vdd == VDD1)) + ret = voltscale_adaptive_body_bias(target_volt); + + return ret; } /**