diff mbox

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

Message ID 20130517131101.GB4892@kahuna
State Changes Requested
Headers show

Commit Message

Nishanth Menon May 17, 2013, 1:11 p.m. UTC
On 19:49-20130513, Andrii Tseglytskyi wrote:
[...]
> +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;
> +	}
> +
> +	/* configure timings, based on oscillator value */
> +	abb_setup_timings(setup);
Still missing txdone clear..
If txdone was set on entry, you'd escape a bit waiting for transition
completion bit in SR2, However, by clearing TXDONE here, you can just wait
for TXDONE.
> +
> +	/* select ABB type */
> +	clrsetbits_le32(setup,
> +			abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK,
> +			abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK);
This is no better than set_bits! clearbits (addr, clr, set) -> the clr
bits should clear *all* bits of the field. in this example ABB_TYPE
should both be cleared, same in OPP_SEL.
See the following change on top of this series:

> +
> +	/* 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");
superfluous if you wait for txdone.
> +
> +	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..cb33cb8
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/omap5/abb.c
> @@ -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, vset, vset);
here as well -> please why clrbits need to be clearing all field -
suggest looking in all usages.
> +
> +	return 0;
> +}
> diff --git a/arch/arm/include/asm/arch-omap3/omap3.h b/arch/arm/include/asm/arch-omap3/omap3.h
> index 2b5e9ae..c57599a 100644
> --- a/arch/arm/include/asm/arch-omap3/omap3.h
> +++ b/arch/arm/include/asm/arch-omap3/omap3.h
> @@ -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
> 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;
> -- 
> 1.7.9.5
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

Comments

Andrii Tseglytskyi May 20, 2013, 11:06 a.m. UTC | #1
Hi,

Thank you for review.

On 05/17/2013 04:11 PM, Nishanth Menon wrote:

[snip]
> On 19:49-20130513, Andrii Tseglytskyi wrote:
> [...]
>> +	if (fuse && ldovbb) {
>> +		if (abb_setup_ldovbb(fuse, ldovbb))
>> +			return;
>> +	}
>> +
>> +	/* configure timings, based on oscillator value */
>> +	abb_setup_timings(setup);
> Still missing txdone clear..
> If txdone was set on entry, you'd escape a bit waiting for transition
> completion bit in SR2, However, by clearing TXDONE here, you can just wait
> for TXDONE.

We touch ABB first time here. I can add check/clear txdone here to 
double check that everything is fine,
but this may be superfluous.

>> +
>> +	/* select ABB type */
>> +	clrsetbits_le32(setup,
>> +			abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK,
>> +			abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK);
> This is no better than set_bits! clearbits (addr, clr, set) -> the clr
> bits should clear *all* bits of the field. in this example ABB_TYPE
> should both be cleared, same in OPP_SEL.
> See the following change on top of this series:
Yep. should be:

clrsetbits_le32(setup,
                     OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK 
|OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK | OMAP_ABB_SETUP_SR2EN_MASK,
                    abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK)

But I propose to rework this in the following way:
- at the beginning of setup function clear both ABB registers (setup and 
control),
     writel(0, setup);
     writel(0, control);

- use setbits_le32 everywhere.

This guarantees that there will be no trash values in ABB registers and 
increases code readability.
Your opinion?

> diff --git a/arch/arm/cpu/armv7/omap-common/abb.c b/arch/arm/cpu/armv7/omap-common/abb.c
> index 73eadb2..31332fb 100644
> --- a/arch/arm/cpu/armv7/omap-common/abb.c
> +++ b/arch/arm/cpu/armv7/omap-common/abb.c
> @@ -115,14 +115,22 @@ void abb_setup(u32 fuse, u32 ldovbb, u32 setup, u32 control,
>   	/* configure timings, based on oscillator value */
>   	abb_setup_timings(setup);
>   
> +	/*
> +	 * Clear any pending ABB tranxdones before we wait for txdone.
> +	 * We do not know the mode in which we have been handed over
> +	 * the system (warm/cold reboot), ROM code operations etc..
> +	 * on a cold boot, we do not expect to see this set.
> +	 */
> +	setbits_le32(txdone, OMAP_ABB_MPU_TXDONE_MASK);
> +
>   	/* select ABB type */
> -	clrsetbits_le32(setup,
> -			abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK,
> +	clrsetbits_le32(setup, OMAP_ABB_SETUP_ABB_SEL_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,
> +	clrsetbits_le32(control, OMAP_ABB_CONTROL_OPP_SEL_MASK |
> +			OMAP_ABB_CONTROL_OPP_CHANGE_MASK,
>   			opp_sel_mask | OMAP_ABB_CONTROL_OPP_CHANGE_MASK);
>   
>   	/* wait until transition complete */
> diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
> index 4892c0a..c2fc180 100644
> --- a/arch/arm/include/asm/omap_common.h
> +++ b/arch/arm/include/asm/omap_common.h
> @@ -565,13 +565,17 @@ s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb);
>   #define OMAP_ABB_NOMINAL_OPP		0
>   #define OMAP_ABB_FAST_OPP		1
>   #define OMAP_ABB_SLOW_OPP		3
> +#define OMAP_ABB_CONTROL_OPP_SEL_MASK			(0x3 << 0)
>   #define OMAP_ABB_CONTROL_FAST_OPP_SEL_MASK		(0x1 << 0)
> -#define OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK		(0x1 << 1)
> +#define OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK		(0x3 << 0)
> +#define OMAP_ABB_CONTROL_NOMINAL_OPP_SEL_MASK		(0x0 << 0)
>   #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_ABB_SEL_MASK			(OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK | \
> +							 OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK)
>   #define OMAP_ABB_SETUP_SR2_WTCNT_VALUE_MASK		(0xff << 8)
>   
>   static inline u32 omap_revision(void)
>
>> +
>> +	/* 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");
> superfluous if you wait for txdone.

Agree. Can be removed.

[snip]
> +	/* setup LDOVBB using fused value */
> +	clrsetbits_le32(ldovbb, vset, vset);
> here as well -> please why clrbits need to be clearing all field -
> suggest looking in all usages.

This is a mistake :( Should be clrsetbits_le32(ldovbb, 
OMAP5_ABB_LDOVBBMPU_VSET_OUT_MASK, vset)
Thank you for catching this!

>> +
>> +	return 0;
>> +}
>> ____________________
>> U-Boot mailing list
>> U-Boot@lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot
[snip]

Regards,
Andrii
Nishanth Menon May 20, 2013, 1:51 p.m. UTC | #2
On Mon, May 20, 2013 at 6:06 AM, Andrii Tseglytskyi
<andrii.tseglytskyi@ti.com> wrote:
> On 05/17/2013 04:11 PM, Nishanth Menon wrote:
>
> [snip]
>>
>> On 19:49-20130513, Andrii Tseglytskyi wrote:
>> [...]
>>>
>>> +       if (fuse && ldovbb) {
>>> +               if (abb_setup_ldovbb(fuse, ldovbb))
>>> +                       return;
>>> +       }
>>> +
>>> +       /* configure timings, based on oscillator value */
>>> +       abb_setup_timings(setup);
>>
>> Still missing txdone clear..
>> If txdone was set on entry, you'd escape a bit waiting for transition
>> completion bit in SR2, However, by clearing TXDONE here, you can just wait
>> for TXDONE.
>
>
> We touch ABB first time here. I can add check/clear txdone here to double
> check that everything is fine,
> but this may be superfluous.

PRM register may be reset OR not depending on type of reset and SoC,
Though this might be the first line of code to execute in bootloader
that touches this register, there is no guarentee that there is no
pending TRANXDONE interrupt in the register. if there is TRANXDONE
interrupt, it is not something we desire. Hence the suggestion to
clear.

>>> +
>>> +       /* select ABB type */
>>> +       clrsetbits_le32(setup,
>>> +                       abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK,
>>> +                       abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK);
>>
>> This is no better than set_bits! clearbits (addr, clr, set) -> the clr
>> bits should clear *all* bits of the field. in this example ABB_TYPE
>> should both be cleared, same in OPP_SEL.
>> See the following change on top of this series:
>
> Yep. should be:
>
> clrsetbits_le32(setup,
>                     OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK
> |OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK | OMAP_ABB_SETUP_SR2EN_MASK,
>                    abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK)
>
> But I propose to rework this in the following way:
> - at the beginning of setup function clear both ABB registers (setup and
> control),
>     writel(0, setup);
>     writel(0, control);
>
> - use setbits_le32 everywhere.
>
> This guarantees that there will be no trash values in ABB registers and
> increases code readability.
> Your opinion?
>
Case 1) if we have been given control by another bootloader which had
already setup ABB, writing 0 will not impact the current setting as
the transition trigger is OPP_CHANGE
case 2) we are the only bootloader in the system. writing 0 is ok as well.

So, am ok if you reset the registers prior to programming them.
--
Regards,
Nishanth Menon
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/omap-common/abb.c b/arch/arm/cpu/armv7/omap-common/abb.c
index 73eadb2..31332fb 100644
--- a/arch/arm/cpu/armv7/omap-common/abb.c
+++ b/arch/arm/cpu/armv7/omap-common/abb.c
@@ -115,14 +115,22 @@  void abb_setup(u32 fuse, u32 ldovbb, u32 setup, u32 control,
 	/* configure timings, based on oscillator value */
 	abb_setup_timings(setup);
 
+	/*
+	 * Clear any pending ABB tranxdones before we wait for txdone.
+	 * We do not know the mode in which we have been handed over
+	 * the system (warm/cold reboot), ROM code operations etc..
+	 * on a cold boot, we do not expect to see this set.
+	 */
+	setbits_le32(txdone, OMAP_ABB_MPU_TXDONE_MASK);
+
 	/* select ABB type */
-	clrsetbits_le32(setup,
-			abb_type_mask | OMAP_ABB_SETUP_SR2EN_MASK,
+	clrsetbits_le32(setup, OMAP_ABB_SETUP_ABB_SEL_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,
+	clrsetbits_le32(control, OMAP_ABB_CONTROL_OPP_SEL_MASK |
+			OMAP_ABB_CONTROL_OPP_CHANGE_MASK,
 			opp_sel_mask | OMAP_ABB_CONTROL_OPP_CHANGE_MASK);
 
 	/* wait until transition complete */
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index 4892c0a..c2fc180 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -565,13 +565,17 @@  s8 abb_setup_ldovbb(u32 fuse, u32 ldovbb);
 #define OMAP_ABB_NOMINAL_OPP		0
 #define OMAP_ABB_FAST_OPP		1
 #define OMAP_ABB_SLOW_OPP		3
+#define OMAP_ABB_CONTROL_OPP_SEL_MASK			(0x3 << 0)
 #define OMAP_ABB_CONTROL_FAST_OPP_SEL_MASK		(0x1 << 0)
-#define OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK		(0x1 << 1)
+#define OMAP_ABB_CONTROL_SLOW_OPP_SEL_MASK		(0x3 << 0)
+#define OMAP_ABB_CONTROL_NOMINAL_OPP_SEL_MASK		(0x0 << 0)
 #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_ABB_SEL_MASK			(OMAP_ABB_SETUP_ACTIVE_RBB_SEL_MASK | \
+							 OMAP_ABB_SETUP_ACTIVE_FBB_SEL_MASK)
 #define OMAP_ABB_SETUP_SR2_WTCNT_VALUE_MASK		(0xff << 8)
 
 static inline u32 omap_revision(void)