Eduardo Valentin wrote:
Hello Mike,

On Fri, Apr 16, 2010 at 11:33:22PM +0200, ext Mike Turquette wrote:
Introduces voltscale_adaptive_body_bias function to voltage.c.
voltscale_adaptive_body_bias is called by omap_voltage_scale after a
voltage transition has occured.  Currently voltscale_adaptive_body_bias
only implements Forward Body-Bias (FBB) for OMAP3630 when MPU runs at
1GHz or higher.  In the future Reverse Body-Bias might be included.

FBB is an Adaptive Body-Bias technique to boost performance for weak
process devices at high OPPs. This results in voltage boost on the VDD1
PMOS back gates when running at maximum OPP.  Current recommendations
are to enable FBB on all 3630 regardless of silicon characteristics and
EFUSE values.

ABB applies to all OMAP silicon based on 45nm process, which includes
OMAP4.  OMAP4 recommendations for ABB are not complete and will be added
to voltscale_adaptive_body_bias in the future.


What is not clear to me in this ABB activation is about the idle path.
At least, from your patch, it looks like it does care about ABB & system in 
idle state.

So, my question is, what is the recommendation if system idles in 1GHz OPP with 
FBB enabled?
Should we care to disable it by software and re-enable it while waking up?

The recommendation for 3630 is to always have FBB enabled at 1GHz or higher on the ARM. This includes idle states. There was some internal discussion about disabling FBB around idle, but the decision was to leave it enabled due to stability issues when running at high OPPs. This increases leakage during idle, but not significantly I'm told. I haven't measured the delta in idle caused by this.

For OMAP4 recommendations might be to disable around idle path. My V2 patchset (will publish next week) breaks this code up into enable_fbb() disable_fbb() functions which makes this sort of thing easy.

Or is it somehow bound to SmartReflex activation (then your patch would rely to 
the fact that
SR is enabled & disabled before & after WFI)?

No, it does not mirror SR explicitly and this is intentional due to stability issues mentioned above.

Regards,
Mike

Signed-off-by: Mike Turquette <mturque...@ti.com>
---
 arch/arm/mach-omap2/voltage.c |  129 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 127 insertions(+), 2 deletions(-)

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;
 }
/**
--
1.6.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to