[U-Boot] [PATCH v1 1/2] OMAP3+: introduce generic ABB support
Andrii Tseglytskyi
andrii.tseglytskyi at ti.com
Wed May 15 14:42:45 CEST 2013
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 at 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 at 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 at 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;
More information about the U-Boot
mailing list