Message ID | 1368454519-23197-2-git-send-email-andrii.tseglytskyi@ti.com |
---|---|
State | Superseded |
Delegated to: | Tom Rini |
Headers | show |
Few minor comments follow: On 17:15-20130513, Andrii Tseglytskyi wrote: <snip> > 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 @@ <snip> > + /* - On OMAP5+ silicons some ABB setting are fused /* * please > + * 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. OMAP4 does have ABB efuse offset for OPP_TURBO. LDOVBB override is not used. please rephrase accordingly. > + */ > + if (fuse && ldovbb) { > + if (abb_setup_ldovbb(fuse, ldovbb)) > + return; > + } <snip> > +s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb) > +{ > + u32 vset; > + > + /* ABB parameters must be properly fused > + * otherwise ABB should be disabled */ please fix comment style. > + 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 > + */ could be one line :) > +#define OMAP_ABB_SETTLING_TIME 30 > +#define OMAP_ABB_CLOCK_CYCLES 8 <snip> otherwise looks ok to me.
On 05/13/2013 05:58 PM, Nishanth Menon wrote: > Few minor comments follow: > On 17:15-20130513, Andrii Tseglytskyi wrote: > <snip> >> 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 @@ > <snip> >> + /* - On OMAP5+ silicons some ABB setting are fused > /* > * > please >> + * 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. > OMAP4 does have ABB efuse offset for OPP_TURBO. LDOVBB override is not > used. please rephrase accordingly. OK. >> + */ >> + if (fuse && ldovbb) { >> + if (abb_setup_ldovbb(fuse, ldovbb)) >> + return; >> + } > <snip> >> +s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb) >> +{ >> + u32 vset; >> + >> + /* ABB parameters must be properly fused >> + * otherwise ABB should be disabled */ > please fix comment style. OK >> + 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 >> + */ > could be one line :) Yeah it could. The reason why I did this - all comments in this file have such style. Anyway, agree with you. >> +#define OMAP_ABB_SETTLING_TIME 30 >> +#define OMAP_ABB_CLOCK_CYCLES 8 > <snip> > otherwise looks ok to me. > > Thank you, Regards, Andrii
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.tseglytskyi@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.tseglytskyi@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.tseglytskyi@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;
On Wed, May 15, 2013 at 03:42:45PM +0300, Andrii Tseglytskyi wrote: > Hi, > > Tom, Nishant, could you please review this series ? Reviewed-by: Tom Rini <trini@ti.com>
On 10:08-20130515, Tom Rini wrote: > On Wed, May 15, 2013 at 03:42:45PM +0300, Andrii Tseglytskyi wrote: > > Hi, > > > > Tom, Nishant, could you please review this series ? > > Reviewed-by: Tom Rini <trini@ti.com> I think the right thread was: PATCH v02 0/2] OMAP3+: introduce generic Adaptive Body Bias Support ? seems line V2 is the updated series..
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.tseglytskyi@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.tseglytskyi@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;
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.tseglytskyi@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