Hi,

Tom, Nishant,  could you please review this series ?

Thank you in advance.
Regards,
Andrii

On 05/13/2013 05:15 PM, Andrii Tseglytskyi wrote:
Adaptive Body Biasing (ABB) modulates transistor bias voltages
dynamically in order to optimize switching speed versus leakage.
Adaptive Body-Bias ldos are present for some voltage domains
starting with OMAP3630. There are three modes of operation:

* Bypass - the default, it just follows the vdd voltage
* Foward Body-Bias - applies voltage bias to increase transistor
   performance at the cost of power.  Used to operate safely at high
   OPPs.
* Reverse Body-Bias - applies voltage bias to decrease leakage and
   save power.  Used to save power at lower OPPs.

Signed-off-by: Andrii Tseglytskyi <andrii.tseglyts...@ti.com>
---
  arch/arm/cpu/armv7/omap-common/Makefile |    1 +
  arch/arm/cpu/armv7/omap-common/abb.c    |  139 +++++++++++++++++++++++++++++++
  arch/arm/cpu/armv7/omap5/Makefile       |    1 +
  arch/arm/cpu/armv7/omap5/abb.c          |   65 +++++++++++++++
  arch/arm/include/asm/arch-omap3/omap3.h |    9 ++
  arch/arm/include/asm/arch-omap4/omap.h  |    7 ++
  arch/arm/include/asm/arch-omap5/omap.h  |   13 +++
  arch/arm/include/asm/omap_common.h      |   22 +++++
  8 files changed, 257 insertions(+)
  create mode 100644 arch/arm/cpu/armv7/omap-common/abb.c
  create mode 100644 arch/arm/cpu/armv7/omap5/abb.c

diff --git a/arch/arm/cpu/armv7/omap-common/Makefile 
b/arch/arm/cpu/armv7/omap-common/Makefile
index 55e82ba..c4b9809 100644
--- a/arch/arm/cpu/armv7/omap-common/Makefile
+++ b/arch/arm/cpu/armv7/omap-common/Makefile
@@ -34,6 +34,7 @@ COBJS += hwinit-common.o
  COBJS += clocks-common.o
  COBJS += emif-common.o
  COBJS += vc.o
+COBJS  += abb.o
  endif
ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TI814X),)
diff --git a/arch/arm/cpu/armv7/omap-common/abb.c 
b/arch/arm/cpu/armv7/omap-common/abb.c
new file mode 100644
index 0000000..7ade110
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap-common/abb.c
@@ -0,0 +1,139 @@
+/*
+ *
+ * Adaptive Body Bias programming sequence for OMAP family
+ *
+ * (C) Copyright 2013
+ * Texas Instruments, <www.ti.com>
+ *
+ * Andrii Tseglytskyi R <andrii.tseglyts...@ti.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/omap_common.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+
+__weak s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb)
+{
+       return -1;
+}
+
+static void abb_setup_timings(u32 setup)
+{
+       u32 sys_rate, sr2_cnt, clk_cycles;
+
+       /*
+        * SR2_WTCNT_VALUE is the settling time for the ABB ldo after a
+        * transition and must be programmed with the correct time at boot.
+        * The value programmed into the register is the number of SYS_CLK
+        * clock cycles that match a given wall time profiled for the ldo.
+        * This value depends on:
+        * settling time of ldo in micro-seconds (varies per OMAP family),
+        * of clock cycles per SYS_CLK period (varies per OMAP family),
+        * the SYS_CLK frequency in MHz (varies per board)
+        * The formula is:
+        *
+        *                     ldo settling time (in micro-seconds)
+        * SR2_WTCNT_VALUE = ------------------------------------------
+        *                  (# system clock cycles) * (sys_clk period)
+        *
+        * Put another way:
+        *
+        * SR2_WTCNT_VALUE = settling time / (# SYS_CLK cycles / SYS_CLK rate))
+        *
+        * To avoid dividing by zero multiply both "# clock cycles" and
+        * "settling time" by 10 such that the final result is the one we want.
+        */
+
+       /* calculate SR2_WTCNT_VALUE */
+       sys_rate = DIV_ROUND(V_OSCK, 1000000);
+       clk_cycles = DIV_ROUND(OMAP_ABB_CLOCK_CYCLES * 10, sys_rate);
+       sr2_cnt = DIV_ROUND(OMAP_ABB_SETTLING_TIME * 10, clk_cycles);
+
+       setbits_le32(setup,
+                    sr2_cnt << (ffs(OMAP_ABB_SETUP_SR2_WTCNT_VALUE_MASK) - 1));
+}
+
+void abb_setup(u32 fuse, u32 ldovbb, u32 setup, u32 control,
+              u32 txdone, u32 txdone_mask, u32 opp)
+{
+       u32 abb_type_mask, opp_sel_mask;
+
+       /* sanity check */
+       if (!setup || !control || !txdone)
+               return;
+
+       /* setup ABB only in case of Fast or Slow OPP */
+       switch (opp) {
+       case OMAP_ABB_FAST_OPP:
+               abb_type_mask = OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK;
+               opp_sel_mask = OMAP_ABB_CONTROL_FAST_OPP_SEL_MASK;
+               break;
+       case OMAP_ABB_SLOW_OPP:
+               abb_type_mask = OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK;
+               opp_sel_mask = OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK;
+               break;
+       default:
+              return;
+       }
+
+       /* - On OMAP5+ silicons some ABB setting are fused
+        *  in corresponding OPP control registers. Also additional
+        *  setup for LDOVBB is required. Initialization
+        *  sequence contains specific part which handles this.
+        *  If function call fails - return quitely, it means
+        *  no ABB is required for silicon.
+        *
+        * - OMAP3 and OMAP4 don't have any fused settings for ABB.
+        *   EFUSE and LDOVBB registers are also not defined for them.
+        *   ABB will be initialized in the common way without
+        *   ldovbb setup.
+        */
+       if (fuse && ldovbb) {
+               if (abb_setup_ldovbb(fuse, ldovbb))
+                       return;
+       }
+
+       /* configure timings, based on oscillator value */
+       abb_setup_timings(setup);
+
+       /* select ABB type */
+       clrsetbits_le32(setup,
+                       abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK,
+                       abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK);
+
+       /* initiate ABB ldo change */
+       clrsetbits_le32(control,
+                       opp_sel_mask | OMAP_ABB_CONTROL_OPP_CHANGE_MASK,
+                       opp_sel_mask | OMAP_ABB_CONTROL_OPP_CHANGE_MASK);
+
+       /* wait until transition complete */
+       if (!wait_on_value(OMAP_ABB_CONTROL_SR2_IN_TRANSITION_MASK, 0,
+                          (void *)control, LDELAY))
+               puts("Error: ABB is in transition\n");
+
+       if (!wait_on_value(OMAP_ABB_MPU_TXDONE_MASK, OMAP_ABB_MPU_TXDONE_MASK,
+                          (void *)txdone, LDELAY))
+               puts("Error: ABB txdone is not set\n");
+
+       /* clear ABB tranxdone */
+       setbits_le32(txdone, OMAP_ABB_MPU_TXDONE_MASK);
+}
diff --git a/arch/arm/cpu/armv7/omap5/Makefile 
b/arch/arm/cpu/armv7/omap5/Makefile
index ce00e2c..6ff8dbb 100644
--- a/arch/arm/cpu/armv7/omap5/Makefile
+++ b/arch/arm/cpu/armv7/omap5/Makefile
@@ -30,6 +30,7 @@ COBJS += emif.o
  COBJS += sdram.o
  COBJS += prcm-regs.o
  COBJS += hw_data.o
+COBJS  += abb.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
  OBJS  := $(addprefix $(obj),$(COBJS) $(SOBJS))
diff --git a/arch/arm/cpu/armv7/omap5/abb.c b/arch/arm/cpu/armv7/omap5/abb.c
new file mode 100644
index 0000000..1139361
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap5/abb.c
@@ -0,0 +1,65 @@
+/*
+ *
+ * Adaptive Body Bias programming sequence for OMAP5 family
+ *
+ * (C) Copyright 2013
+ * Texas Instruments, <www.ti.com>
+ *
+ * Andrii Tseglytskyi R <andrii.tseglyts...@ti.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/omap_common.h>
+#include <asm/io.h>
+
+/*
+ * Setup LDOVBB for OMAP5.
+ * On OMAP5+ some ABB settings are fused. They are handled
+ * in the following way:
+ *
+ * 1. corresponding EFUSE register contains ABB enable bit
+ *    and VSET value
+ * 2. If ABB enable bit is set to 1, than ABB should be
+ *    enabled, otherwise ABB should be disabled
+ * 3. If ABB is enabled, than VSET value should be copied
+ *    to corresponding MUX control register
+ */
+s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb)
+{
+       u32 vset;
+
+       /* ABB parameters must be properly fused
+        * otherwise ABB should be disabled */
+       vset = readl(fuse);
+       if (!(vset & OMAP5_ABB_FUSE_ENABLE_MASK))
+               return -1;
+
+       /* prepare VSET value for LDOVBB mux register */
+       vset &= OMAP5_ABB_FUSE_VSET_MASK;
+       vset >>= ffs(OMAP5_ABB_FUSE_VSET_MASK) - 1;
+       vset <<= ffs(OMAP5_ABB_LDOVBBMPU_VSET_OUT_MASK) - 1;
+       vset |= OMAP5_ABB_LDOVBBMPU_MUX_CTRL_MASK;
+
+       /* setup LDOVBB using fused value */
+       clrsetbits_le32(ldovbb, vset, vset);
+
+       return 0;
+}
diff --git a/arch/arm/include/asm/arch-omap3/omap3.h 
b/arch/arm/include/asm/arch-omap3/omap3.h
index 2b5e9ae..66361d5 100644
--- a/arch/arm/include/asm/arch-omap3/omap3.h
+++ b/arch/arm/include/asm/arch-omap3/omap3.h
@@ -253,4 +253,13 @@ struct gpio {
#define OMAP3_EMU_HAL_START_HAL_CRITICAL 4 +/*
+ * ABB settings
+ */
+#define OMAP_ABB_SETTLING_TIME         30
+#define OMAP_ABB_CLOCK_CYCLES          8
+
+/* ABB tranxdone mask */
+#define OMAP_ABB_MPU_TXDONE_MASK       (0x1 << 26)
+
  #endif
diff --git a/arch/arm/include/asm/arch-omap4/omap.h 
b/arch/arm/include/asm/arch-omap4/omap.h
index ad984da..559ad26 100644
--- a/arch/arm/include/asm/arch-omap4/omap.h
+++ b/arch/arm/include/asm/arch-omap4/omap.h
@@ -170,6 +170,13 @@ struct s32ktimer {
  #define CH_FLAGS_CHFLASH      (0x1 << 2)
  #define CH_FLAGS_CHMMCSD      (0x1 << 3)
+/* ABB settings */
+#define OMAP_ABB_SETTLING_TIME         50
+#define OMAP_ABB_CLOCK_CYCLES          16
+
+/* ABB tranxdone mask */
+#define OMAP_ABB_MPU_TXDONE_MASK       (0x1 << 7)
+
  #ifndef __ASSEMBLY__
  struct omap_boot_parameters {
        char *boot_message;
diff --git a/arch/arm/include/asm/arch-omap5/omap.h 
b/arch/arm/include/asm/arch-omap5/omap.h
index 887fcaa..caa1234 100644
--- a/arch/arm/include/asm/arch-omap5/omap.h
+++ b/arch/arm/include/asm/arch-omap5/omap.h
@@ -243,6 +243,19 @@ struct s32ktimer {
  #define SRCODE_OVERRIDE_SEL_XS_SHIFT  0
  #define SRCODE_OVERRIDE_SEL_XS_MASK   (1 << 0)
+/* ABB settings */
+#define OMAP_ABB_SETTLING_TIME         50
+#define OMAP_ABB_CLOCK_CYCLES          16
+
+/* ABB tranxdone mask */
+#define OMAP_ABB_MPU_TXDONE_MASK               (0x1 << 7)
+
+/* ABB efuse masks */
+#define OMAP5_ABB_FUSE_VSET_MASK               (0x1F << 24)
+#define OMAP5_ABB_FUSE_ENABLE_MASK             (0x1 << 29)
+#define OMAP5_ABB_LDOVBBMPU_MUX_CTRL_MASK      (0x1 << 10)
+#define OMAP5_ABB_LDOVBBMPU_VSET_OUT_MASK      (0x1f << 0)
+
  #ifndef __ASSEMBLY__
  struct srcomp_params {
        s8 divide_factor;
diff --git a/arch/arm/include/asm/omap_common.h 
b/arch/arm/include/asm/omap_common.h
index 091ddb5..4892c0a 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -240,6 +240,8 @@ struct prcm_regs {
        u32 cm_l3init_fsusb_clkctrl;
        u32 cm_l3init_ocp2scp1_clkctrl;
+ u32 prm_irqstatus_mpu_2;
+
        /* cm2.l4per */
        u32 cm_l4per_clkstctrl;
        u32 cm_l4per_dynamicdep;
@@ -325,6 +327,8 @@ struct prcm_regs {
        u32 prm_sldo_mpu_ctrl;
        u32 prm_sldo_mm_setup;
        u32 prm_sldo_mm_ctrl;
+       u32 prm_abbldo_mpu_setup;
+       u32 prm_abbldo_mpu_ctrl;
u32 cm_div_m4_dpll_core;
        u32 cm_div_m5_dpll_core;
@@ -347,6 +351,7 @@ struct prcm_regs {
struct omap_sys_ctrl_regs {
        u32 control_status;
+       u32 control_std_fuse_opp_vdd_mpu_2;
        u32 control_core_mmr_lock1;
        u32 control_core_mmr_lock2;
        u32 control_core_mmr_lock3;
@@ -416,6 +421,7 @@ struct omap_sys_ctrl_regs {
        u32 control_port_emif2_sdram_config;
        u32 control_emif1_sdram_config_ext;
        u32 control_emif2_sdram_config_ext;
+       u32 control_wkup_ldovbb_mpu_voltage_ctrl;
        u32 control_smart1nopmio_padconf_0;
        u32 control_smart1nopmio_padconf_1;
        u32 control_padconf_mode;
@@ -542,6 +548,9 @@ void enable_non_essential_clocks(void);
  void scale_vcores(struct vcores_data const *);
  u32 get_offset_code(u32 volt_offset, struct pmic_data *pmic);
  void do_scale_vcore(u32 vcore_reg, u32 volt_mv, struct pmic_data *pmic);
+void abb_setup(u32 fuse, u32 ldovbb, u32 setup, u32 control,
+              u32 txdone, u32 txdone_mask, u32 opp);
+s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb);
/* Max value for DPLL multiplier M */
  #define OMAP_DPLL_MAX_N       127
@@ -552,6 +561,19 @@ void do_scale_vcore(u32 vcore_reg, u32 volt_mv, struct 
pmic_data *pmic);
  #define OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL     2
  #define OMAP_INIT_CONTEXT_UBOOT_AFTER_CH      3
+/* ABB */
+#define OMAP_ABB_NOMINAL_OPP           0
+#define OMAP_ABB_FAST_OPP              1
+#define OMAP_ABB_SLOW_OPP              3
+#define OMAP_ABB_CONTROL_FAST_OPP_SEL_MASK             (0x1 << 0)
+#define OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK             (0x1 << 1)
+#define OMAP_ABB_CONTROL_OPP_CHANGE_MASK               (0x1 << 2)
+#define OMAP_ABB_CONTROL_SR2_IN_TRANSITION_MASK                (0x1 << 6)
+#define OMAP_ABB_SETUP_SR2EN_MASK                      (0x1 << 0)
+#define OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK             (0x1 << 2)
+#define OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK             (0x1 << 1)
+#define OMAP_ABB_SETUP_SR2_WTCNT_VALUE_MASK            (0xff << 8)
+
  static inline u32 omap_revision(void)
  {
        extern u32 *const omap_si_rev;

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to