diff mbox

[U-Boot,v1,1/2] OMAP3+: introduce generic ABB support

Message ID 1368454519-23197-2-git-send-email-andrii.tseglytskyi@ti.com
State Superseded
Delegated to: Tom Rini
Headers show

Commit Message

Andrii Tseglytskyi May 13, 2013, 2:15 p.m. UTC
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

Comments

Nishanth Menon May 13, 2013, 2:58 p.m. UTC | #1
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.
Andrii Tseglytskyi May 13, 2013, 3:07 p.m. UTC | #2
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
Andrii Tseglytskyi May 15, 2013, 12:42 p.m. UTC | #3
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;
Tom Rini May 15, 2013, 2:08 p.m. UTC | #4
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>
Nishanth Menon May 17, 2013, 12:44 p.m. UTC | #5
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 mbox

Patch

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;