OMAP3+: introduce generic ABB support
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> Acked-by: Nishanth Menon <nm@ti.com>
This commit is contained in:
parent
a662e0c345
commit
4d0df9c1e9
@ -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),)
|
||||
|
137
arch/arm/cpu/armv7/omap-common/abb.c
Normal file
137
arch/arm/cpu/armv7/omap-common/abb.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
*
|
||||
* Adaptive Body Bias programming sequence for OMAP family
|
||||
*
|
||||
* (C) Copyright 2013
|
||||
* Texas Instruments, <www.ti.com>
|
||||
*
|
||||
* Andrii Tseglytskyi <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;
|
||||
}
|
||||
|
||||
/*
|
||||
* For some OMAP silicons additional setup for LDOVBB register is
|
||||
* required. This is determined by data retrieved from corresponding
|
||||
* OPP EFUSE register. Data, which is retrieved from EFUSE - is
|
||||
* ABB enable/disable flag and VSET value, which must be copied
|
||||
* to LDOVBB register. If function call fails - return quietly,
|
||||
* it means no ABB is required for such silicon.
|
||||
*
|
||||
* For silicons, which don't require LDOVBB setup "fuse" and
|
||||
* "ldovbb" offsets are not defined. ABB will be initialized in
|
||||
* the common way for them.
|
||||
*/
|
||||
if (fuse && ldovbb) {
|
||||
if (abb_setup_ldovbb(fuse, ldovbb))
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear ABB registers */
|
||||
writel(0, setup);
|
||||
writel(0, control);
|
||||
|
||||
/* configure timings, based on oscillator value */
|
||||
abb_setup_timings(setup);
|
||||
|
||||
/* clear pending interrupts before setup */
|
||||
setbits_le32(txdone, txdone_mask);
|
||||
|
||||
/* select ABB type */
|
||||
setbits_le32(setup, abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK);
|
||||
|
||||
/* initiate ABB ldo change */
|
||||
setbits_le32(control, opp_sel_mask | OMAP_ABB_CONTROL_OPP_CHANGE_MASK);
|
||||
|
||||
/* wait until transition complete */
|
||||
if (!wait_on_value(txdone_mask, txdone_mask, (void *)txdone, LDELAY))
|
||||
puts("Error: ABB txdone is not set\n");
|
||||
|
||||
/* clear ABB tranxdone */
|
||||
setbits_le32(txdone, txdone_mask);
|
||||
}
|
@ -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))
|
||||
|
67
arch/arm/cpu/armv7/omap5/abb.c
Normal file
67
arch/arm/cpu/armv7/omap5/abb.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
*
|
||||
* Adaptive Body Bias programming sequence for OMAP5 family
|
||||
*
|
||||
* (C) Copyright 2013
|
||||
* Texas Instruments, <www.ti.com>
|
||||
*
|
||||
* Andrii Tseglytskyi <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, OMAP5_ABB_LDOVBBMPU_VSET_OUT_MASK, vset);
|
||||
|
||||
return 0;
|
||||
}
|
@ -253,4 +253,11 @@ 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
|
||||
|
@ -143,4 +143,12 @@ struct s32ktimer {
|
||||
#define NON_SECURE_SRAM_END 0x4030E000 /* Not inclusive */
|
||||
/* base address for indirect vectors (internal boot mode) */
|
||||
#define SRAM_ROM_VECT_BASE 0x4030D000
|
||||
|
||||
/* 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)
|
||||
|
||||
#endif
|
||||
|
@ -215,6 +215,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;
|
||||
|
@ -242,6 +242,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;
|
||||
@ -328,6 +330,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;
|
||||
@ -350,6 +354,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;
|
||||
@ -419,6 +424,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;
|
||||
@ -545,6 +551,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
|
||||
@ -555,6 +564,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;
|
||||
|
Loading…
Reference in New Issue
Block a user