diff mbox

[U-Boot,07/12] imx:mx6 Support LDO bypass

Message ID 1420793987-7621-8-git-send-email-Peng.Fan@freescale.com
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

Peng Fan Jan. 9, 2015, 8:59 a.m. UTC
The basic graph for voltage input is:
   VDDARM_IN ---> LDO_DIG(ARM) ---> VDD_ARM_CAP
   VDDSOC_IN ---> LDO_DIG(SOC) ---> VDD_SOC_CAP

We can bypass the LDO to save power, if the board already has pmic.

set_anatop_bypass is the function to do the bypass VDDARM and VDDSOC
work.

Current only set VDDARM_IN@1.175V/VDDSOC_IN@1.175V before ldo
bypass switch. So until ldo bypass switch happened, these voltage
setting is set in ldo-enable mode. But in datasheet, we need
1.15V + 125mV = 1.275V for VDDARM_IN. We need to downgrade cpufreq
to 400Mhz and restore after ldo bypass mode switch. So add
prep_anatop_bypass/finish_anatop_bypass/set_arm_freq_400M to do
this work.

LDO bypass is dependent on the flatten device tree file. If speed
grading fuse is for 1.2GHz, enable LDO bypass and setup PMIC voltages.
So add check for 1.2GHz core speed. So add check_1_2G function.

In ldo-bypass mode, we need trigger WDOG_B pin to reset pmic in
ldo-bypass mode. So add set_wdog_reset to do this work.

Also add related function prototype in sys_proto.h

Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Signed-off-by: Robin Gong <b38343@freescale.com>
Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
---
 arch/arm/cpu/armv7/mx6/soc.c              | 141 ++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx6/sys_proto.h |   9 ++
 2 files changed, 150 insertions(+)

Comments

Stefano Babic Feb. 10, 2015, 11:23 a.m. UTC | #1
Hi Peng,

On 09/01/2015 09:59, Peng Fan wrote:
> The basic graph for voltage input is:
>    VDDARM_IN ---> LDO_DIG(ARM) ---> VDD_ARM_CAP
>    VDDSOC_IN ---> LDO_DIG(SOC) ---> VDD_SOC_CAP
> 
> We can bypass the LDO to save power, if the board already has pmic.
> 
> set_anatop_bypass is the function to do the bypass VDDARM and VDDSOC
> work.
> 
> Current only set VDDARM_IN@1.175V/VDDSOC_IN@1.175V before ldo
> bypass switch. So until ldo bypass switch happened, these voltage
> setting is set in ldo-enable mode. But in datasheet, we need
> 1.15V + 125mV = 1.275V for VDDARM_IN. We need to downgrade cpufreq
> to 400Mhz and restore after ldo bypass mode switch. So add
> prep_anatop_bypass/finish_anatop_bypass/set_arm_freq_400M to do
> this work.
> 
> LDO bypass is dependent on the flatten device tree file. If speed
> grading fuse is for 1.2GHz, enable LDO bypass and setup PMIC voltages.
> So add check for 1.2GHz core speed. So add check_1_2G function.
> 
> In ldo-bypass mode, we need trigger WDOG_B pin to reset pmic in
> ldo-bypass mode. So add set_wdog_reset to do this work.
> 
> Also add related function prototype in sys_proto.h
> 

Ok - with this explanation, I would try to understand how the changes
can be split. If the feature/change works for several boards, it makes
sense to have it common and general. If it is only for one board, must
flow into the board directory.

It looks like that ldo-bypass is strictly dependent on the board.
Firstly, it must have PMIC, and not all boards have it. Your last sentence:

> In ldo-bypass mode, we need trigger WDOG_B pin to reset pmic in
> ldo-bypass mode. So add set_wdog_reset to do this work.

This looks to me as an item very bound to the board. Could it be
possible to use another pin (I do not know the schematics, I remember
that such as reset pin was fix on previous i.MX) ? If answer is yes, can
these changes be used by other board or are they only for sabresd ?


> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
> Signed-off-by: Robin Gong <b38343@freescale.com>
> Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
> ---
>  arch/arm/cpu/armv7/mx6/soc.c              | 141 ++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-mx6/sys_proto.h |   9 ++
>  2 files changed, 150 insertions(+)
> 
> diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
> index 5f5f497..5d02755 100644
> --- a/arch/arm/cpu/armv7/mx6/soc.c
> +++ b/arch/arm/cpu/armv7/mx6/soc.c
> @@ -18,6 +18,7 @@
>  #include <asm/arch/sys_proto.h>
>  #include <asm/imx-common/boot_mode.h>
>  #include <asm/imx-common/dma.h>
> +#include <libfdt.h>
>  #include <stdbool.h>
>  #include <asm/arch/mxc_hdmi.h>
>  #include <asm/arch/crm_regs.h>
> @@ -429,6 +430,146 @@ void s_init(void)
>  	writel(mask528, &anatop->pfd_528_clr);
>  }
>  
> +#ifdef CONFIG_LDO_BYPASS_CHECK
> +DECLARE_GLOBAL_DATA_PTR;
> +static int ldo_bypass;

mmmhh....global to the module ?

> +
> +int check_ldo_bypass(void)
> +{
> +	const int *ldo_mode;
> +	int node;
> +
> +	/* get the right fdt_blob from the global working_fdt */
> +	gd->fdt_blob = working_fdt;
> +	/* Get the node from FDT for anatop ldo-bypass */
> +	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> +		"fsl,imx6q-gpc");
> +	if (node < 0) {
> +		printf("No gpc device node %d, force to ldo-enable.\n", node);
> +		return 0;
> +	}
> +	ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL);

I am quite lost. I have searched in kernel (current TOT), and I have not
found such property. Can you help me to understand ?

> +	/*
> +	 * return 1 if "fsl,ldo-bypass = <1>", else return 0 if
> +	 * "fsl,ldo-bypass = <0>" or no "fsl,ldo-bypass" property
> +	 */
> +	ldo_bypass = fdt32_to_cpu(*ldo_mode) == 1 ? 1 : 0;
> +
> +	return ldo_bypass;
> +}
> +
> +int check_1_2G(void)
> +{
> +	u32 reg;
> +	int result = 0;
> +	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
> +	struct fuse_bank *bank = &ocotp->bank[0];
> +	struct fuse_bank0_regs *fuse_bank0 =
> +			(struct fuse_bank0_regs *)bank->fuse_regs;
> +
> +	reg = readl(&fuse_bank0->cfg3);
> +	if (((reg >> 16) & 0x3) == 0x3) {
> +		if (ldo_bypass) {
> +			printf("Wrong dtb file used! i.MX6Q@1.2Ghz only works with ldo-enable mode!\n");
> +			/*
> +			 * Currently, only imx6q-sabresd board might be here,
> +			 * since only i.MX6Q support 1.2G and only Sabresd board
> +			 * support ldo-bypass mode. So hardcode here.
> +			 * You can also modify your board(i.MX6Q) dtb name if it
> +			 * supports both ldo-bypass and ldo-enable mode.

This enforce my doubts.

> +			 */
> +			printf("Please use imx6q-sabresd-ldo.dtb!\n");

In any case, do not use hard-coded filenames into u-boot. They can change.

> +			hang();
> +		}
> +		result = 1;
> +	}
> +
> +	return result;
> +}
> +
> +static int arm_orig_podf;
> +void set_arm_freq_400M(bool is_400M)
> +{
> +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +
> +	if (is_400M)
> +		writel(0x1, &mxc_ccm->cacrr);
> +	else
> +		writel(arm_orig_podf, &mxc_ccm->cacrr);
> +}
> +
> +void prep_anatop_bypass(void)
> +{
> +	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +
> +	arm_orig_podf = readl(&mxc_ccm->cacrr);
> +	/*
> +	 * Downgrade ARM speed to 400Mhz as half of boot 800Mhz before ldo
> +	 * bypassed, also downgrade internal vddarm ldo to 0.975V.
> +	 * VDDARM_IN 0.975V + 125mV = 1.1V < Max(1.3V)
> +	 * otherwise at 800Mhz(i.mx6dl):
> +	 * VDDARM_IN 1.175V + 125mV = 1.3V = Max(1.3V)
> +	 * We need provide enough gap in this case.
> +	 * skip if boot from 400M.
> +	 */
> +	if (!arm_orig_podf)
> +		set_arm_freq_400M(true);
> +#if !defined(CONFIG_MX6DL) && !defined(CONFIG_MX6SX)
> +	set_ldo_voltage(LDO_ARM, 975);
> +#else
> +	set_ldo_voltage(LDO_ARM, 1150);
> +#endif
> +}
> +
> +void set_wdog_reset(struct wdog_regs *wdog)
> +{
> +	u32 reg = readw(&wdog->wcr);
> +	/*
> +	 * use WDOG_B mode to reset external pmic because it's risky for the
> +	 * following watchdog reboot in case of cpu freq at lowest 400Mhz with
> +	 * ldo-bypass mode. Because boot frequency maybe higher 800Mhz i.e. So
> +	 * in ldo-bypass mode watchdog reset will only triger POR reset, not
> +	 * WDOG reset. But below code depends on hardware design, if HW didn't
> +	 * connect WDOG_B pin to external pmic such as i.mx6slevk, we can skip
> +	 * these code since it assumed boot from 400Mhz always.
> +	 */
> +	reg = readw(&wdog->wcr);
> +	reg |= 1 << 3;
> +	/*
> +	 * WDZST bit is write-once only bit. Align this bit in kernel,
> +	 * otherwise kernel code will have no chance to set this bit.
> +	 */
> +	reg |= 1 << 0;
> +	writew(reg, &wdog->wcr);
> +}
> +
> +int set_anatop_bypass(int wdog_reset_pin)
> +{
> +	struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +	struct wdog_regs *wdog;
> +	u32 reg = readl(&ccm_regs->reg_core);
> +
> +	/* bypass VDDARM/VDDSOC */
> +	reg = reg | (0x1F << 18) | 0x1F;
> +	writel(reg, &ccm_regs->reg_core);
> +
> +	if (wdog_reset_pin == 2)
> +		wdog = (struct wdog_regs *)WDOG2_BASE_ADDR;
> +	else if (wdog_reset_pin == 1)
> +		wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
> +	else
> +		return arm_orig_podf;
> +	set_wdog_reset(wdog);
> +	return arm_orig_podf;
> +}
> +
> +void finish_anatop_bypass(void)
> +{
> +	if (!arm_orig_podf)
> +		set_arm_freq_400M(false);
> +}
> +#endif
> +
>  #ifdef CONFIG_IMX_HDMI
>  void imx_enable_hdmi_phy(void)
>  {
> diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h
> index 28ba844..e6f2112 100644
> --- a/arch/arm/include/asm/arch-mx6/sys_proto.h
> +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h
> @@ -28,6 +28,15 @@ const char *get_imx_type(u32 imxtype);
>  unsigned imx_ddr_size(void);
>  void set_chipselect_size(int const);
>  
> +void set_wdog_reset(struct wdog_regs *wdog);
> +#ifdef CONFIG_LDO_BYPASS_CHECK

Why do we need #ifdef ?


> +int check_ldo_bypass(void);
> +int check_1_2G(void);
> +void ldo_mode_set(int ldo_bypass);
> +int set_anatop_bypass(int wdog_reset_pin);
> +void prep_anatop_bypass(void);
> +void finish_anatop_bypass(void);
> +#endif
>  /*
>   * Initializes on-chip ethernet controllers.
>   * to override, implement board_eth_init()
> 

Best regards,
Stefano Babic
Tim Harvey Feb. 10, 2015, 2:33 p.m. UTC | #2
On Fri, Jan 9, 2015 at 12:59 AM, Peng Fan <Peng.Fan@freescale.com> wrote:
> The basic graph for voltage input is:
>    VDDARM_IN ---> LDO_DIG(ARM) ---> VDD_ARM_CAP
>    VDDSOC_IN ---> LDO_DIG(SOC) ---> VDD_SOC_CAP
>

Hi Peng,

Glad to see someone else interested in IMX6 LDO bypass mode. I've made
a couple of stabs at getting it supported in mainline but I haven't
had the time to follow-through yet there.

> We can bypass the LDO to save power, if the board already has pmic.
>
> set_anatop_bypass is the function to do the bypass VDDARM and VDDSOC
> work.
>
> Current only set VDDARM_IN@1.175V/VDDSOC_IN@1.175V before ldo
> bypass switch. So until ldo bypass switch happened, these voltage
> setting is set in ldo-enable mode. But in datasheet, we need
> 1.15V + 125mV = 1.275V for VDDARM_IN. We need to downgrade cpufreq
> to 400Mhz and restore after ldo bypass mode switch. So add
> prep_anatop_bypass/finish_anatop_bypass/set_arm_freq_400M to do
> this work.
>
> LDO bypass is dependent on the flatten device tree file. If speed
> grading fuse is for 1.2GHz, enable LDO bypass and setup PMIC voltages.
> So add check for 1.2GHz core speed. So add check_1_2G function.

This isn't quite how it works. If you are 'operating at 1.2GHz'
(supposing you had a processor cabable of it) you must use the LDO (to
avoid ripple sensitivity issues).

>
> In ldo-bypass mode, we need trigger WDOG_B pin to reset pmic in
> ldo-bypass mode. So add set_wdog_reset to do this work.

This is very board dependent. Here you are referring to a board that
has a reset input to the PMIC's from the IMX6's watchdog output. In
this case, this reset routing/pinmux would be needed regardless of
using ldo-bypass mode or not and that should just be a pinmux of the
pin your using for WDOG_B.

>

<snip>

> diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
> index 5f5f497..5d02755 100644
> --- a/arch/arm/cpu/armv7/mx6/soc.c
> +++ b/arch/arm/cpu/armv7/mx6/soc.c
> @@ -18,6 +18,7 @@
>  #include <asm/arch/sys_proto.h>
>  #include <asm/imx-common/boot_mode.h>
>  #include <asm/imx-common/dma.h>
> +#include <libfdt.h>
>  #include <stdbool.h>
>  #include <asm/arch/mxc_hdmi.h>
>  #include <asm/arch/crm_regs.h>
> @@ -429,6 +430,146 @@ void s_init(void)
>         writel(mask528, &anatop->pfd_528_clr);
>  }
>
> +#ifdef CONFIG_LDO_BYPASS_CHECK
> +DECLARE_GLOBAL_DATA_PTR;
> +static int ldo_bypass;
> +
> +int check_ldo_bypass(void)
> +{
> +       const int *ldo_mode;
> +       int node;
> +
> +       /* get the right fdt_blob from the global working_fdt */
> +       gd->fdt_blob = working_fdt;
> +       /* Get the node from FDT for anatop ldo-bypass */
> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> +               "fsl,imx6q-gpc");
> +       if (node < 0) {
> +               printf("No gpc device node %d, force to ldo-enable.\n", node);
> +               return 0;
> +       }
> +       ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL);
> +       /*
> +        * return 1 if "fsl,ldo-bypass = <1>", else return 0 if
> +        * "fsl,ldo-bypass = <0>" or no "fsl,ldo-bypass" property
> +        */
> +       ldo_bypass = fdt32_to_cpu(*ldo_mode) == 1 ? 1 : 0;
> +
> +       return ldo_bypass;
> +}

What you are doing here is relying on a device-tree binding from the
Freescale 'vendor' kernel, which will NEVER make it upstream and this
is one of the issues I was running into getting ldo-bypass capability
upstream in the kernel.

The issue here is that LDO bypass is dependent on the following things:
  1. your voltage rail requirements - which are dependent on the CPU
frequency (there is a nice table in the IMX6 datasheets of voltage on
each rail at each frequency operating point validated by Freescale).
The exception of always using the LDO for 1.2GHz is specified here as
well.
  2. you have a PMIC in your design on VDD_ARM_IN and VDD_SOC_IN rails
- this should be specified in the device-tree as well
  3. you have valid PMIC drivers configured

In the kernel, its not desired to have a single device-tree node
called 'fsl,ldo-bypass' for an enable. Instead you need to make sure
that you PMIC regulators that are 'not' the internal IMX6 anatop
regulators. This property is not a mainline linux device-tree binding.

> +
> +int check_1_2G(void)
> +{
> +       u32 reg;
> +       int result = 0;
> +       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
> +       struct fuse_bank *bank = &ocotp->bank[0];
> +       struct fuse_bank0_regs *fuse_bank0 =
> +                       (struct fuse_bank0_regs *)bank->fuse_regs;
> +
> +       reg = readl(&fuse_bank0->cfg3);
> +       if (((reg >> 16) & 0x3) == 0x3) {
> +               if (ldo_bypass) {
> +                       printf("Wrong dtb file used! i.MX6Q@1.2Ghz only works with ldo-enable mode!\n");
> +                       /*
> +                        * Currently, only imx6q-sabresd board might be here,
> +                        * since only i.MX6Q support 1.2G and only Sabresd board
> +                        * support ldo-bypass mode. So hardcode here.
> +                        * You can also modify your board(i.MX6Q) dtb name if it
> +                        * supports both ldo-bypass and ldo-enable mode.
> +                        */
> +                       printf("Please use imx6q-sabresd-ldo.dtb!\n");
> +                       hang();
> +               }
> +               result = 1;
> +       }
> +
> +       return result;
> +}

While it is correct that you must not use LDO bypass when operating at
1.2GHz, that does not mean that a CPU capable of 1.2GHz can't use LDO
bypass at the lower operating points.

> +
> +static int arm_orig_podf;
> +void set_arm_freq_400M(bool is_400M)
> +{
> +       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> +
> +       if (is_400M)
> +               writel(0x1, &mxc_ccm->cacrr);
> +       else
> +               writel(arm_orig_podf, &mxc_ccm->cacrr);
> +}

I have no idea what is going on here. Are we now running at different
CPU frequencies in U-boot? The IMX6 comes up in either 800MHz or
400MHz per BOOT_CFG3 e-fuse and from the U-Boot I'm working with
(still on 2010.04 but pretty sure its the same in 2014.10) the CPU
frequency is never changed in the bootloader.

This brings me to the question of why does LDO bypass have anything at
all do to with the bootloader?

It is true that the Freescale vendor kernel will keep the LDO in
bypass mode if its registers are set that way from the bootloader, so
that is probably what your after here. But again, that is a poor
kernel implementation that likely won't make it upstream and a
solution that doesn't handle the dynamic situation of a 1.2GHz cpu
stepping down and not needing the LDO. It is also true that there are
alternate device-tree's for the Freescale vendor kernel for some
boards that have a PMIC such that one device-tree is setup to always
use the LDO, and one is setup to never use the LDO. I think that is a
result of taking the easy way out instead of giving the kernel the
smarts to use the LDO only when needed on these boards.

Tim
Tim Harvey Feb. 10, 2015, 2:50 p.m. UTC | #3
On Tue, Feb 10, 2015 at 3:23 AM, Stefano Babic <sbabic@denx.de> wrote:
>
> Ok - with this explanation, I would try to understand how the changes
> can be split. If the feature/change works for several boards, it makes
> sense to have it common and general. If it is only for one board, must
> flow into the board directory.

It should be common as there are several boards which use PMIC's and can use it.

>
> It looks like that ldo-bypass is strictly dependent on the board.
> Firstly, it must have PMIC, and not all boards have it. Your last sentence:

Any board that has a PMIC capable of regulating VDD_ARM_IN and
VDD_SOC_IN to the setpoints from the IMX6 datasheet can operate in LDO
bypass mode, unless operating at 1.2GHz in which case the datasheet
states that the LDO must be used (not bypassed) to avoid ripple
sensitivity issues.

>
>> In ldo-bypass mode, we need trigger WDOG_B pin to reset pmic in
>> ldo-bypass mode. So add set_wdog_reset to do this work.
>
> This looks to me as an item very bound to the board. Could it be
> possible to use another pin (I do not know the schematics, I remember
> that such as reset pin was fix on previous i.MX) ? If answer is yes, can
> these changes be used by other board or are they only for sabresd ?
>

agreed - this is a board-specific pinmux

>
>> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
>> Signed-off-by: Robin Gong <b38343@freescale.com>
>> Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
>> ---
>>  arch/arm/cpu/armv7/mx6/soc.c              | 141 ++++++++++++++++++++++++++++++
>>  arch/arm/include/asm/arch-mx6/sys_proto.h |   9 ++
>>  2 files changed, 150 insertions(+)
>>
>> diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
>> index 5f5f497..5d02755 100644
>> --- a/arch/arm/cpu/armv7/mx6/soc.c
>> +++ b/arch/arm/cpu/armv7/mx6/soc.c
>> @@ -18,6 +18,7 @@
>>  #include <asm/arch/sys_proto.h>
>>  #include <asm/imx-common/boot_mode.h>
>>  #include <asm/imx-common/dma.h>
>> +#include <libfdt.h>
>>  #include <stdbool.h>
>>  #include <asm/arch/mxc_hdmi.h>
>>  #include <asm/arch/crm_regs.h>
>> @@ -429,6 +430,146 @@ void s_init(void)
>>       writel(mask528, &anatop->pfd_528_clr);
>>  }
>>
>> +#ifdef CONFIG_LDO_BYPASS_CHECK
>> +DECLARE_GLOBAL_DATA_PTR;
>> +static int ldo_bypass;
>
> mmmhh....global to the module ?
>
>> +
>> +int check_ldo_bypass(void)
>> +{
>> +     const int *ldo_mode;
>> +     int node;
>> +
>> +     /* get the right fdt_blob from the global working_fdt */
>> +     gd->fdt_blob = working_fdt;
>> +     /* Get the node from FDT for anatop ldo-bypass */
>> +     node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
>> +             "fsl,imx6q-gpc");
>> +     if (node < 0) {
>> +             printf("No gpc device node %d, force to ldo-enable.\n", node);
>> +             return 0;
>> +     }
>> +     ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL);
>
> I am quite lost. I have searched in kernel (current TOT), and I have not
> found such property. Can you help me to understand ?

Right - you won't find it because its a Freescale vendor kernel
implementation only. A hack if you ask me to avoid having to doing
ldo-byapss the right way.

Here are the threads that I know of regarding ldo-bypass in the
kernel, where it needs to be:

https://lkml.org/lkml/2014/12/18/255
https://lkml.org/lkml/2014/10/31/3

Peng,

I think what you are trying to do here is to put the anatop regulators
in bypass mode so that the Freescale vendor kernel leaves them
bypassed (which is what the 3.10.x based vendor kernels supporting
device-tree at http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git
do). This is what the Freescale vendor U-Boot does and so they have
created a horrible dependence between kernel and bootloader.

Instead you may be interested in what I did for our BSP's that use the
Freescale vendor kernel. Instead of touching U-Boot, I look for the
fsl,ldo-bypass node in the kernel and enable it just like their
bootloader would have:
https://github.com/Gateworks/linux-imx6/commit/a1af6ac6f00b4da7c8a5656e8ff093d4ab5cadee

That said, I would love to see some help getting IMX6 ldo-bypass
support upstream. All of our boards have an external PMIC and are
capable of bypass mode. Bypassing the LDO on such boards really helps
reduce overall board power consumption as well as move heat from the
CPU to the PMIC.

Tim
Fabio Estevam Feb. 10, 2015, 2:59 p.m. UTC | #4
Hi Tim,

On Tue, Feb 10, 2015 at 12:50 PM, Tim Harvey <tharvey@gateworks.com> wrote:

> I think what you are trying to do here is to put the anatop regulators
> in bypass mode so that the Freescale vendor kernel leaves them
> bypassed (which is what the 3.10.x based vendor kernels supporting
> device-tree at http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git
> do). This is what the Freescale vendor U-Boot does and so they have
> created a horrible dependence between kernel and bootloader.

I agree.

> Instead you may be interested in what I did for our BSP's that use the
> Freescale vendor kernel. Instead of touching U-Boot, I look for the
> fsl,ldo-bypass node in the kernel and enable it just like their
> bootloader would have:
> https://github.com/Gateworks/linux-imx6/commit/a1af6ac6f00b4da7c8a5656e8ff093d4ab5cadee
>
> That said, I would love to see some help getting IMX6 ldo-bypass
> support upstream. All of our boards have an external PMIC and are

I want to help you on upstreaming ldo-bypass support in the kernel, Tim.

Can we do like your approach, but defining
imx_anatop_ldobypass_enable() inside
rivers/regulator/anatop-regulator.c instead?

Regards,

Fabio Estevam
Tim Harvey Feb. 10, 2015, 3:29 p.m. UTC | #5
On Tue, Feb 10, 2015 at 6:59 AM, Fabio Estevam <festevam@gmail.com> wrote:
> Hi Tim,
>
> On Tue, Feb 10, 2015 at 12:50 PM, Tim Harvey <tharvey@gateworks.com> wrote:
>
>> I think what you are trying to do here is to put the anatop regulators
>> in bypass mode so that the Freescale vendor kernel leaves them
>> bypassed (which is what the 3.10.x based vendor kernels supporting
>> device-tree at http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git
>> do). This is what the Freescale vendor U-Boot does and so they have
>> created a horrible dependence between kernel and bootloader.
>
> I agree.
>
>> Instead you may be interested in what I did for our BSP's that use the
>> Freescale vendor kernel. Instead of touching U-Boot, I look for the
>> fsl,ldo-bypass node in the kernel and enable it just like their
>> bootloader would have:
>> https://github.com/Gateworks/linux-imx6/commit/a1af6ac6f00b4da7c8a5656e8ff093d4ab5cadee
>>
>> That said, I would love to see some help getting IMX6 ldo-bypass
>> support upstream. All of our boards have an external PMIC and are
>
> I want to help you on upstreaming ldo-bypass support in the kernel, Tim.

Great!

>
> Can we do like your approach, but defining
> imx_anatop_ldobypass_enable() inside
> rivers/regulator/anatop-regulator.c instead?

Yes, I think that makes sense. I hope to be able to get back to this
in a couple of weeks after a round of U-Boot updates that are next on
my list.

Thanks,

Tim
Stefano Babic Feb. 11, 2015, 8:42 a.m. UTC | #6
Hi Tim,

On 10/02/2015 15:50, Tim Harvey wrote:
> On Tue, Feb 10, 2015 at 3:23 AM, Stefano Babic <sbabic@denx.de> wrote:
>>
>> Ok - with this explanation, I would try to understand how the changes
>> can be split. If the feature/change works for several boards, it makes
>> sense to have it common and general. If it is only for one board, must
>> flow into the board directory.
> 
> It should be common as there are several boards which use PMIC's and can use it.
> 

Fully agree.


>> I am quite lost. I have searched in kernel (current TOT), and I have not
>> found such property. Can you help me to understand ?
> 
> Right - you won't find it because its a Freescale vendor kernel
> implementation only. A hack if you ask me to avoid having to doing
> ldo-byapss the right way.

Exactly, this cannot flow into mainline.

> 
> Here are the threads that I know of regarding ldo-bypass in the
> kernel, where it needs to be:
> 
> https://lkml.org/lkml/2014/12/18/255
> https://lkml.org/lkml/2014/10/31/3

Thanks for pointing out !

> 
> Peng,
> 
> I think what you are trying to do here is to put the anatop regulators
> in bypass mode so that the Freescale vendor kernel leaves them
> bypassed (which is what the 3.10.x based vendor kernels supporting
> device-tree at http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git
> do). This is what the Freescale vendor U-Boot does and so they have
> created a horrible dependence between kernel and bootloader.
> 

You are perfectly right.

> Instead you may be interested in what I did for our BSP's that use the
> Freescale vendor kernel. Instead of touching U-Boot, I look for the
> fsl,ldo-bypass node in the kernel and enable it just like their
> bootloader would have:
> https://github.com/Gateworks/linux-imx6/commit/a1af6ac6f00b4da7c8a5656e8ff093d4ab5cadee
> 

Thanks - you are on the right direction ;-)

Best regards,
Stefano
Robin Gong Feb. 11, 2015, 10:49 a.m. UTC | #7
On Tue, Feb 10, 2015 at 06:33:38AM -0800, Tim Harvey wrote:
> On Fri, Jan 9, 2015 at 12:59 AM, Peng Fan <Peng.Fan@freescale.com> wrote:
> > The basic graph for voltage input is:
> >    VDDARM_IN ---> LDO_DIG(ARM) ---> VDD_ARM_CAP
> >    VDDSOC_IN ---> LDO_DIG(SOC) ---> VDD_SOC_CAP
> >
> 
> Hi Peng,
> 
> Glad to see someone else interested in IMX6 LDO bypass mode. I've made
> a couple of stabs at getting it supported in mainline but I haven't
> had the time to follow-through yet there.
> 
> > We can bypass the LDO to save power, if the board already has pmic.
> >
> > set_anatop_bypass is the function to do the bypass VDDARM and VDDSOC
> > work.
> >
> > Current only set VDDARM_IN@1.175V/VDDSOC_IN@1.175V before ldo
> > bypass switch. So until ldo bypass switch happened, these voltage
> > setting is set in ldo-enable mode. But in datasheet, we need
> > 1.15V + 125mV = 1.275V for VDDARM_IN. We need to downgrade cpufreq
> > to 400Mhz and restore after ldo bypass mode switch. So add
> > prep_anatop_bypass/finish_anatop_bypass/set_arm_freq_400M to do
> > this work.
> >
> > LDO bypass is dependent on the flatten device tree file. If speed
> > grading fuse is for 1.2GHz, enable LDO bypass and setup PMIC voltages.
> > So add check for 1.2GHz core speed. So add check_1_2G function.
> 
> This isn't quite how it works. If you are 'operating at 1.2GHz'
> (supposing you had a processor cabable of it) you must use the LDO (to
> avoid ripple sensitivity issues).
>
Hi Peng, the limitation is "must use ldo-enable mode in 1.2Ghz", NOT ldo-bypass
> >
> > In ldo-bypass mode, we need trigger WDOG_B pin to reset pmic in
> > ldo-bypass mode. So add set_wdog_reset to do this work.
> 
> This is very board dependent. Here you are referring to a board that
> has a reset input to the PMIC's from the IMX6's watchdog output. In
> this case, this reset routing/pinmux would be needed regardless of
> using ldo-bypass mode or not and that should just be a pinmux of the
> pin your using for WDOG_B.
>
There are two types of reboot in our chip by watchdog : SRS/warm reset
(Software Reset Signal) and WDOG_B(reset signal output to external pmic
to trigger next power cycle). In fact, warm reset can work most cases except
ldo-bypass mode and this is why we connect WDOG_B reset and ldo-bypass here:
kernel may trigger warm reset at the lowest cpu freq setpoint, for example
VDDARM 0.975v@396Mhz ldo-bypass mode. i.mx6q will reboot with ldo-enable mode
@792Mhz and the VDDARM_IN 0.975v can't support system boot.Thus, we need use
WDOG_B pin to reset external pmic if using ldo-byapss mode.
> >
> 
> <snip>
> 
> > diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
> > index 5f5f497..5d02755 100644
> > --- a/arch/arm/cpu/armv7/mx6/soc.c
> > +++ b/arch/arm/cpu/armv7/mx6/soc.c
> > @@ -18,6 +18,7 @@
> >  #include <asm/arch/sys_proto.h>
> >  #include <asm/imx-common/boot_mode.h>
> >  #include <asm/imx-common/dma.h>
> > +#include <libfdt.h>
> >  #include <stdbool.h>
> >  #include <asm/arch/mxc_hdmi.h>
> >  #include <asm/arch/crm_regs.h>
> > @@ -429,6 +430,146 @@ void s_init(void)
> >         writel(mask528, &anatop->pfd_528_clr);
> >  }
> >
> > +#ifdef CONFIG_LDO_BYPASS_CHECK
> > +DECLARE_GLOBAL_DATA_PTR;
> > +static int ldo_bypass;
> > +
> > +int check_ldo_bypass(void)
> > +{
> > +       const int *ldo_mode;
> > +       int node;
> > +
> > +       /* get the right fdt_blob from the global working_fdt */
> > +       gd->fdt_blob = working_fdt;
> > +       /* Get the node from FDT for anatop ldo-bypass */
> > +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> > +               "fsl,imx6q-gpc");
> > +       if (node < 0) {
> > +               printf("No gpc device node %d, force to ldo-enable.\n", node);
> > +               return 0;
> > +       }
> > +       ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL);
> > +       /*
> > +        * return 1 if "fsl,ldo-bypass = <1>", else return 0 if
> > +        * "fsl,ldo-bypass = <0>" or no "fsl,ldo-bypass" property
> > +        */
> > +       ldo_bypass = fdt32_to_cpu(*ldo_mode) == 1 ? 1 : 0;
> > +
> > +       return ldo_bypass;
> > +}
> 
> What you are doing here is relying on a device-tree binding from the
> Freescale 'vendor' kernel, which will NEVER make it upstream and this
> is one of the issues I was running into getting ldo-bypass capability
> upstream in the kernel.
> 
> The issue here is that LDO bypass is dependent on the following things:
>   1. your voltage rail requirements - which are dependent on the CPU
> frequency (there is a nice table in the IMX6 datasheets of voltage on
> each rail at each frequency operating point validated by Freescale).
> The exception of always using the LDO for 1.2GHz is specified here as
> well.
>   2. you have a PMIC in your design on VDD_ARM_IN and VDD_SOC_IN rails
> - this should be specified in the device-tree as well
>   3. you have valid PMIC drivers configured
> 
> In the kernel, its not desired to have a single device-tree node
> called 'fsl,ldo-bypass' for an enable. Instead you need to make sure
> that you PMIC regulators that are 'not' the internal IMX6 anatop
> regulators. This property is not a mainline linux device-tree binding.
> 
Yes, understood. But we have no better solution, because we need touch both
internal anatop regulator and external pmic regulator in ldo-bypass mode, that
bring kernel cpufreq driver code too messy....
> > +
> > +int check_1_2G(void)
> > +{
> > +       u32 reg;
> > +       int result = 0;
> > +       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
> > +       struct fuse_bank *bank = &ocotp->bank[0];
> > +       struct fuse_bank0_regs *fuse_bank0 =
> > +                       (struct fuse_bank0_regs *)bank->fuse_regs;
> > +
> > +       reg = readl(&fuse_bank0->cfg3);
> > +       if (((reg >> 16) & 0x3) == 0x3) {
> > +               if (ldo_bypass) {
> > +                       printf("Wrong dtb file used! i.MX6Q@1.2Ghz only works with ldo-enable mode!\n");
> > +                       /*
> > +                        * Currently, only imx6q-sabresd board might be here,
> > +                        * since only i.MX6Q support 1.2G and only Sabresd board
> > +                        * support ldo-bypass mode. So hardcode here.
> > +                        * You can also modify your board(i.MX6Q) dtb name if it
> > +                        * supports both ldo-bypass and ldo-enable mode.
> > +                        */
> > +                       printf("Please use imx6q-sabresd-ldo.dtb!\n");
> > +                       hang();
> > +               }
> > +               result = 1;
> > +       }
> > +
> > +       return result;
> > +}
> 
> While it is correct that you must not use LDO bypass when operating at
> 1.2GHz, that does not mean that a CPU capable of 1.2GHz can't use LDO
> bypass at the lower operating points.
>
I see, but to simply things, we regard as 1.2GHz chip(fused) may running at
1.2GHz and force it work in ldo-enable mode although it has chance to running
at 1Ghz. In other words, ldo-bypass mode only set once not dynamically.
> > +
> > +static int arm_orig_podf;
> > +void set_arm_freq_400M(bool is_400M)
> > +{
> > +       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> > +
> > +       if (is_400M)
> > +               writel(0x1, &mxc_ccm->cacrr);
> > +       else
> > +               writel(arm_orig_podf, &mxc_ccm->cacrr);
> > +}
> 
> I have no idea what is going on here. Are we now running at different
> CPU frequencies in U-boot? The IMX6 comes up in either 800MHz or
> 400MHz per BOOT_CFG3 e-fuse and from the U-Boot I'm working with
> (still on 2010.04 but pretty sure its the same in 2014.10) the CPU
> frequency is never changed in the bootloader.
> 
Let's try to explain why we downgrade cpufreq to 400Mhz before ldo-bypass mode
switch(i.mx6q):
  cpufreq    VDDSOC    VDDARM
  400Mhz     0.975v     1.175v
  800Mhz     1.175v     1.175v
If system boot from 800Mhz, considering VDDARM setting with 1.175v after
ldo-bypass mode switch, and the voltage drop which bring by internal regulator
125mv, we have to set VDDARM 1.175v+125mv = 1.3v before ldo-bypass mode switch,
but the 1.3v beyond our max voltage for VDDARM. So we have to downgrade the cpufreq
to 400Mhz.
> This brings me to the question of why does LDO bypass have anything at
> all do to with the bootloader?
> 
We only need do once ldo-bypass switch, so we hope it can be implemented in
u-boot
> It is true that the Freescale vendor kernel will keep the LDO in
> bypass mode if its registers are set that way from the bootloader, so
> that is probably what your after here. But again, that is a poor
> kernel implementation that likely won't make it upstream and a
> solution that doesn't handle the dynamic situation of a 1.2GHz cpu
> stepping down and not needing the LDO. It is also true that there are
> alternate device-tree's for the Freescale vendor kernel for some
> boards that have a PMIC such that one device-tree is setup to always
> use the LDO, and one is setup to never use the LDO. I think that is a
> result of taking the easy way out instead of giving the kernel the
> smarts to use the LDO only when needed on these boards.
> 
> Tim
Tim Harvey Feb. 11, 2015, 3:47 p.m. UTC | #8
On Wed, Feb 11, 2015 at 2:49 AM, Robin Gong <b38343@freescale.com> wrote:
<snip>
>>
>> This is very board dependent. Here you are referring to a board that
>> has a reset input to the PMIC's from the IMX6's watchdog output. In
>> this case, this reset routing/pinmux would be needed regardless of
>> using ldo-bypass mode or not and that should just be a pinmux of the
>> pin your using for WDOG_B.
>>
> There are two types of reboot in our chip by watchdog : SRS/warm reset
> (Software Reset Signal) and WDOG_B(reset signal output to external pmic
> to trigger next power cycle). In fact, warm reset can work most cases except
> ldo-bypass mode and this is why we connect WDOG_B reset and ldo-bypass here:
> kernel may trigger warm reset at the lowest cpu freq setpoint, for example
> VDDARM 0.975v@396Mhz ldo-bypass mode. i.mx6q will reboot with ldo-enable mode
> @792Mhz and the VDDARM_IN 0.975v can't support system boot.Thus, we need use
> WDOG_B pin to reset external pmic if using ldo-byapss mode.

Hi Robin,

I understand that configuring WDOG_B external reset must be used when
LDO bypass is used. This should be done in the kernel but you can also
set this pinmux up in uboot in the board-specific init.

If your kernel is providing the PMIC driver and cpufreq driver that
alter the cpu core frequencies it must also be configuring pinmux so
that WDOG_B gets routed to the pin that connects to the PMIC so any
reset based on that wdog (SRS or timeout) issues a hard reset to the
PMIC. Failure to do so is a kernel bug. I believe this is done
properly in the Freescale kernel for the reference boards.

If you are trying to take care of an issue caused by a watchdog reset
(SRS or timeout) not properly resetting a PMIC (ie perhaps a PCB
errata where signal doesn't go to the PMIC) then you should probably
simply set the PMIC rails where they need to be for the 800MHz
operation in the bootloader and not muck with the CPU frequency.
Honestly, if your PMIC rails are too low for 800MHz on powerup your
bootloader may not be stable anyway right? Note that the operating
setpoints have the same SOC voltage for both 792MHz and 396MHz, its
only the ARM voltage that is lower for 396 vs 792 and chances are your
not going to have an issue just in the bootloader at that point.

<snip>
>>
>> What you are doing here is relying on a device-tree binding from the
>> Freescale 'vendor' kernel, which will NEVER make it upstream and this
>> is one of the issues I was running into getting ldo-bypass capability
>> upstream in the kernel.
>>
>> The issue here is that LDO bypass is dependent on the following things:
>>   1. your voltage rail requirements - which are dependent on the CPU
>> frequency (there is a nice table in the IMX6 datasheets of voltage on
>> each rail at each frequency operating point validated by Freescale).
>> The exception of always using the LDO for 1.2GHz is specified here as
>> well.
>>   2. you have a PMIC in your design on VDD_ARM_IN and VDD_SOC_IN rails
>> - this should be specified in the device-tree as well
>>   3. you have valid PMIC drivers configured
>>
>> In the kernel, its not desired to have a single device-tree node
>> called 'fsl,ldo-bypass' for an enable. Instead you need to make sure
>> that you PMIC regulators that are 'not' the internal IMX6 anatop
>> regulators. This property is not a mainline linux device-tree binding.
>>
> Yes, understood. But we have no better solution, because we need touch both
> internal anatop regulator and external pmic regulator in ldo-bypass mode, that
> bring kernel cpufreq driver code too messy....

I just don't see the point in having the CPU frequency changed in the
bootloader - leave this up to the OS kernel. I don't think any of this
patch should go into mainline uboot.

I think my kernel patch I referenced provides you with a simple kernel
solution that de-couples ldo-bypass completely from the bootloader.

<snip>
>>
>> While it is correct that you must not use LDO bypass when operating at
>> 1.2GHz, that does not mean that a CPU capable of 1.2GHz can't use LDO
>> bypass at the lower operating points.
>>
> I see, but to simply things, we regard as 1.2GHz chip(fused) may running at
> 1.2GHz and force it work in ldo-enable mode although it has chance to running
> at 1Ghz. In other words, ldo-bypass mode only set once not dynamically.

Are you saying there is an IMX6 variant that powers up per eFUSE
settings at 1.2GHz? The IMX6QDLRM efuse settings I'm looking at just
have two power-up frequency options: 392MHz and 792MHz.

In my opinion, your PMIC should be setting VDD_ARM and VDD_SOC at the
necessary voltages for what the CPU is currently running at, in the
bootloader. Its up to your OS to properly control this to its needs
later. Again, if for some reason (hardware errata) you have a
situation where the PMIC maybe didn't get reset and the board powers
up into the bootloader at a frequency higher than the rails are set
to, then simply set its rails to where they need to be for the freq
your running at in the bootloader.

>> > +
>> > +static int arm_orig_podf;
>> > +void set_arm_freq_400M(bool is_400M)
>> > +{
>> > +       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
>> > +
>> > +       if (is_400M)
>> > +               writel(0x1, &mxc_ccm->cacrr);
>> > +       else
>> > +               writel(arm_orig_podf, &mxc_ccm->cacrr);
>> > +}
>>
>> I have no idea what is going on here. Are we now running at different
>> CPU frequencies in U-boot? The IMX6 comes up in either 800MHz or
>> 400MHz per BOOT_CFG3 e-fuse and from the U-Boot I'm working with
>> (still on 2010.04 but pretty sure its the same in 2014.10) the CPU
>> frequency is never changed in the bootloader.
>>
> Let's try to explain why we downgrade cpufreq to 400Mhz before ldo-bypass mode
> switch(i.mx6q):
>   cpufreq    VDDSOC    VDDARM
>   400Mhz     0.975v     1.175v
>   800Mhz     1.175v     1.175v
> If system boot from 800Mhz, considering VDDARM setting with 1.175v after
> ldo-bypass mode switch, and the voltage drop which bring by internal regulator
> 125mv, we have to set VDDARM 1.175v+125mv = 1.3v before ldo-bypass mode switch,
> but the 1.3v beyond our max voltage for VDDARM. So we have to downgrade the cpufreq
> to 400Mhz.

Too much complexity in my opinion for the power reduction benefits
while in the bootloader. Leave ldo-bypass out of the bootloader and
you won't have to bother with this. The IMX6 can handle a max of 1.3V
on VDD_ARM_IN and VDD_SOC_IN (and 1.5V on the output side of the LDO).
So you can simply set your PMIC in the bootloader to something between
that and 1.175v and be done with it right?

>> This brings me to the question of why does LDO bypass have anything at
>> all do to with the bootloader?
>>
> We only need do once ldo-bypass switch, so we hope it can be implemented in
> u-boot

It doesn't belong in uboot. It was wrong for Freescale to create a
dependence between the bootloader and the kernel when it is so easy to
avoid.

I don't think any of this particular patch should go into mainline uboot.

Regards,

Tim
Tim Harvey Feb. 13, 2015, 12:08 a.m. UTC | #9
On Wed, Feb 11, 2015 at 7:47 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> On Wed, Feb 11, 2015 at 2:49 AM, Robin Gong <b38343@freescale.com> wrote:
> <snip>
>>>
>>> This is very board dependent. Here you are referring to a board that
>>> has a reset input to the PMIC's from the IMX6's watchdog output. In
>>> this case, this reset routing/pinmux would be needed regardless of
>>> using ldo-bypass mode or not and that should just be a pinmux of the
>>> pin your using for WDOG_B.
>>>
>> There are two types of reboot in our chip by watchdog : SRS/warm reset
>> (Software Reset Signal) and WDOG_B(reset signal output to external pmic
>> to trigger next power cycle). In fact, warm reset can work most cases except
>> ldo-bypass mode and this is why we connect WDOG_B reset and ldo-bypass here:
>> kernel may trigger warm reset at the lowest cpu freq setpoint, for example
>> VDDARM 0.975v@396Mhz ldo-bypass mode. i.mx6q will reboot with ldo-enable mode
>> @792Mhz and the VDDARM_IN 0.975v can't support system boot.Thus, we need use
>> WDOG_B pin to reset external pmic if using ldo-byapss mode.
>
> Hi Robin,
>
> I understand that configuring WDOG_B external reset must be used when
> LDO bypass is used. This should be done in the kernel but you can also
> set this pinmux up in uboot in the board-specific init.
>
> If your kernel is providing the PMIC driver and cpufreq driver that
> alter the cpu core frequencies it must also be configuring pinmux so
> that WDOG_B gets routed to the pin that connects to the PMIC so any
> reset based on that wdog (SRS or timeout) issues a hard reset to the
> PMIC. Failure to do so is a kernel bug. I believe this is done
> properly in the Freescale kernel for the reference boards.
>
> If you are trying to take care of an issue caused by a watchdog reset
> (SRS or timeout) not properly resetting a PMIC (ie perhaps a PCB
> errata where signal doesn't go to the PMIC) then you should probably
> simply set the PMIC rails where they need to be for the 800MHz
> operation in the bootloader and not muck with the CPU frequency.
> Honestly, if your PMIC rails are too low for 800MHz on powerup your
> bootloader may not be stable anyway right? Note that the operating
> setpoints have the same SOC voltage for both 792MHz and 396MHz, its
> only the ARM voltage that is lower for 396 vs 792 and chances are your
> not going to have an issue just in the bootloader at that point.
>

Robin,

The issue your describing was interesting to me and I ran some tests
and found that on a board with no reset to the PMIC, an IMX6Q CPU,
ldo-bypass enabled, and the CPU freq set to 400MHz (such that VDD_ARM
rail set to 0.960V for 400MHz operation) the chip does not even come
out of reset (ie when SRS is set in the watchdog controller). So I
don't really see any ability to work around this in bootloader
software since you won't get there in this case.

Possible solutions I can think of for boards without a PMIC reset is
to either blow the eFUSE so the chip comes up in 400MHz or in the
kernel never allow the VDD_ARM or VDD_SOC rail to go below where they
need to be for CPU startup (the only one that does is VDD_ARM) or
before soft-reboot make sure the cpufreq is at 800MHz or above (which
must be done at higher levels before single-cpu mode in
machine_restart). This also does not deal with the case of a watchdog
reset and/or a crash handler.

Are you findings different?

Tim
Robin Gong Feb. 13, 2015, 7:20 a.m. UTC | #10
On Thu, Feb 12, 2015 at 04:08:51PM -0800, Tim Harvey wrote:
> On Wed, Feb 11, 2015 at 7:47 AM, Tim Harvey <tharvey@gateworks.com> wrote:
> > On Wed, Feb 11, 2015 at 2:49 AM, Robin Gong <b38343@freescale.com> wrote:
> > <snip>
> >>>
> >>> This is very board dependent. Here you are referring to a board that
> >>> has a reset input to the PMIC's from the IMX6's watchdog output. In
> >>> this case, this reset routing/pinmux would be needed regardless of
> >>> using ldo-bypass mode or not and that should just be a pinmux of the
> >>> pin your using for WDOG_B.
> >>>
> >> There are two types of reboot in our chip by watchdog : SRS/warm reset
> >> (Software Reset Signal) and WDOG_B(reset signal output to external pmic
> >> to trigger next power cycle). In fact, warm reset can work most cases except
> >> ldo-bypass mode and this is why we connect WDOG_B reset and ldo-bypass here:
> >> kernel may trigger warm reset at the lowest cpu freq setpoint, for example
> >> VDDARM 0.975v@396Mhz ldo-bypass mode. i.mx6q will reboot with ldo-enable mode
> >> @792Mhz and the VDDARM_IN 0.975v can't support system boot.Thus, we need use
> >> WDOG_B pin to reset external pmic if using ldo-byapss mode.
> >
> > Hi Robin,
> >
> > I understand that configuring WDOG_B external reset must be used when
> > LDO bypass is used. This should be done in the kernel but you can also
> > set this pinmux up in uboot in the board-specific init.
> >
> > If your kernel is providing the PMIC driver and cpufreq driver that
> > alter the cpu core frequencies it must also be configuring pinmux so
> > that WDOG_B gets routed to the pin that connects to the PMIC so any
> > reset based on that wdog (SRS or timeout) issues a hard reset to the
> > PMIC. Failure to do so is a kernel bug. I believe this is done
> > properly in the Freescale kernel for the reference boards.
> >
> > If you are trying to take care of an issue caused by a watchdog reset
> > (SRS or timeout) not properly resetting a PMIC (ie perhaps a PCB
> > errata where signal doesn't go to the PMIC) then you should probably
> > simply set the PMIC rails where they need to be for the 800MHz
> > operation in the bootloader and not muck with the CPU frequency.
> > Honestly, if your PMIC rails are too low for 800MHz on powerup your
> > bootloader may not be stable anyway right? Note that the operating
> > setpoints have the same SOC voltage for both 792MHz and 396MHz, its
> > only the ARM voltage that is lower for 396 vs 792 and chances are your
> > not going to have an issue just in the bootloader at that point.
> >
> 
> Robin,
> 
> The issue your describing was interesting to me and I ran some tests
> and found that on a board with no reset to the PMIC, an IMX6Q CPU,
> ldo-bypass enabled, and the CPU freq set to 400MHz (such that VDD_ARM
> rail set to 0.960V for 400MHz operation) the chip does not even come
> out of reset (ie when SRS is set in the watchdog controller). So I
> don't really see any ability to work around this in bootloader
> software since you won't get there in this case.
Yes, ldo-bypass mode depends on reset PMIC while reboot happen. But even on
this feature supported boards, we'd better provide warm reset in ldo-enable
mode,for example, warm reset can keep printed log in DDR while system crash
in last time and trigger watchdog reset. Someone may use DCDC instead of PMIC,
or some board didn't connect WDOG_B reset with PMIC, have to use ldo-enable
mode.
> 
> Possible solutions I can think of for boards without a PMIC reset is
> to either blow the eFUSE so the chip comes up in 400MHz or in the
> kernel never allow the VDD_ARM or VDD_SOC rail to go below where they
> need to be for CPU startup (the only one that does is VDD_ARM) or
> before soft-reboot make sure the cpufreq is at 800MHz or above (which
> must be done at higher levels before single-cpu mode in
> machine_restart). This also does not deal with the case of a watchdog
> reset and/or a crash handler.
> 
Yes, absolutely. But we suggest connecting PMIC reset pin with WDOG_B or just
use ldo-enable mode if they are not very care of power number.
> Are you findings different?
> 
> Tim
Robin Gong Feb. 13, 2015, 8:16 a.m. UTC | #11
On Wed, Feb 11, 2015 at 07:47:57AM -0800, Tim Harvey wrote:
> On Wed, Feb 11, 2015 at 2:49 AM, Robin Gong <b38343@freescale.com> wrote:
> <snip>
> >>
> >> This is very board dependent. Here you are referring to a board that
> >> has a reset input to the PMIC's from the IMX6's watchdog output. In
> >> this case, this reset routing/pinmux would be needed regardless of
> >> using ldo-bypass mode or not and that should just be a pinmux of the
> >> pin your using for WDOG_B.
> >>
> > There are two types of reboot in our chip by watchdog : SRS/warm reset
> > (Software Reset Signal) and WDOG_B(reset signal output to external pmic
> > to trigger next power cycle). In fact, warm reset can work most cases except
> > ldo-bypass mode and this is why we connect WDOG_B reset and ldo-bypass here:
> > kernel may trigger warm reset at the lowest cpu freq setpoint, for example
> > VDDARM 0.975v@396Mhz ldo-bypass mode. i.mx6q will reboot with ldo-enable mode
> > @792Mhz and the VDDARM_IN 0.975v can't support system boot.Thus, we need use
> > WDOG_B pin to reset external pmic if using ldo-byapss mode.
> 
> Hi Robin,
> 
> I understand that configuring WDOG_B external reset must be used when
> LDO bypass is used. This should be done in the kernel but you can also
> set this pinmux up in uboot in the board-specific init.
> 
> If your kernel is providing the PMIC driver and cpufreq driver that
> alter the cpu core frequencies it must also be configuring pinmux so
> that WDOG_B gets routed to the pin that connects to the PMIC so any
> reset based on that wdog (SRS or timeout) issues a hard reset to the
> PMIC. Failure to do so is a kernel bug. I believe this is done
> properly in the Freescale kernel for the reference boards.
>
pinmux is not enough. WDT bit of WDOGx_WCR need to be taken care of if you want
to enable WDOG_B pin reset function. But unfortunately the current wdog driver
of kernel not touch this write-once bit. To limit the impact from kernel, set
this bit in u-boot.
> If you are trying to take care of an issue caused by a watchdog reset
> (SRS or timeout) not properly resetting a PMIC (ie perhaps a PCB
> errata where signal doesn't go to the PMIC) then you should probably
> simply set the PMIC rails where they need to be for the 800MHz
> operation in the bootloader and not muck with the CPU frequency.
> Honestly, if your PMIC rails are too low for 800MHz on powerup your
> bootloader may not be stable anyway right? Note that the operating
> setpoints have the same SOC voltage for both 792MHz and 396MHz, its
> only the ARM voltage that is lower for 396 vs 792 and chances are your
> not going to have an issue just in the bootloader at that point.
> 
As you saw in another mail, bootloader is too late. It'll hang in ROM code.
> <snip>
> >>
> >> What you are doing here is relying on a device-tree binding from the
> >> Freescale 'vendor' kernel, which will NEVER make it upstream and this
> >> is one of the issues I was running into getting ldo-bypass capability
> >> upstream in the kernel.
> >>
> >> The issue here is that LDO bypass is dependent on the following things:
> >>   1. your voltage rail requirements - which are dependent on the CPU
> >> frequency (there is a nice table in the IMX6 datasheets of voltage on
> >> each rail at each frequency operating point validated by Freescale).
> >> The exception of always using the LDO for 1.2GHz is specified here as
> >> well.
> >>   2. you have a PMIC in your design on VDD_ARM_IN and VDD_SOC_IN rails
> >> - this should be specified in the device-tree as well
> >>   3. you have valid PMIC drivers configured
> >>
> >> In the kernel, its not desired to have a single device-tree node
> >> called 'fsl,ldo-bypass' for an enable. Instead you need to make sure
> >> that you PMIC regulators that are 'not' the internal IMX6 anatop
> >> regulators. This property is not a mainline linux device-tree binding.
> >>
> > Yes, understood. But we have no better solution, because we need touch both
> > internal anatop regulator and external pmic regulator in ldo-bypass mode, that
> > bring kernel cpufreq driver code too messy....
> 
> I just don't see the point in having the CPU frequency changed in the
> bootloader - leave this up to the OS kernel. I don't think any of this
> patch should go into mainline uboot.
> 
> I think my kernel patch I referenced provides you with a simple kernel
> solution that de-couples ldo-bypass completely from the bootloader.
> 
Can you please share me the patch link? Thanks.
> <snip>
> >>
> >> While it is correct that you must not use LDO bypass when operating at
> >> 1.2GHz, that does not mean that a CPU capable of 1.2GHz can't use LDO
> >> bypass at the lower operating points.
> >>
> > I see, but to simply things, we regard as 1.2GHz chip(fused) may running at
> > 1.2GHz and force it work in ldo-enable mode although it has chance to running
> > at 1Ghz. In other words, ldo-bypass mode only set once not dynamically.
> 
> Are you saying there is an IMX6 variant that powers up per eFUSE
> settings at 1.2GHz? The IMX6QDLRM efuse settings I'm looking at just
> have two power-up frequency options: 392MHz and 792MHz.
> 
Sorry, I mean max frequency(SPEED_GRADING[1:0]), not power-up frequency. 
> In my opinion, your PMIC should be setting VDD_ARM and VDD_SOC at the
> necessary voltages for what the CPU is currently running at, in the
> bootloader. Its up to your OS to properly control this to its needs
> later. Again, if for some reason (hardware errata) you have a
> situation where the PMIC maybe didn't get reset and the board powers
> up into the bootloader at a frequency higher than the rails are set
> to, then simply set its rails to where they need to be for the freq
> your running at in the bootloader.
> 
> >> > +
> >> > +static int arm_orig_podf;
> >> > +void set_arm_freq_400M(bool is_400M)
> >> > +{
> >> > +       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> >> > +
> >> > +       if (is_400M)
> >> > +               writel(0x1, &mxc_ccm->cacrr);
> >> > +       else
> >> > +               writel(arm_orig_podf, &mxc_ccm->cacrr);
> >> > +}
> >>
> >> I have no idea what is going on here. Are we now running at different
> >> CPU frequencies in U-boot? The IMX6 comes up in either 800MHz or
> >> 400MHz per BOOT_CFG3 e-fuse and from the U-Boot I'm working with
> >> (still on 2010.04 but pretty sure its the same in 2014.10) the CPU
> >> frequency is never changed in the bootloader.
> >>
> > Let's try to explain why we downgrade cpufreq to 400Mhz before ldo-bypass mode
> > switch(i.mx6q):
> >   cpufreq    VDDSOC    VDDARM
> >   400Mhz     0.975v     1.175v
> >   800Mhz     1.175v     1.175v
> > If system boot from 800Mhz, considering VDDARM setting with 1.175v after
> > ldo-bypass mode switch, and the voltage drop which bring by internal regulator
> > 125mv, we have to set VDDARM 1.175v+125mv = 1.3v before ldo-bypass mode switch,
> > but the 1.3v beyond our max voltage for VDDARM. So we have to downgrade the cpufreq
> > to 400Mhz.
> 
> Too much complexity in my opinion for the power reduction benefits
> while in the bootloader. Leave ldo-bypass out of the bootloader and
> you won't have to bother with this. The IMX6 can handle a max of 1.3V
> on VDD_ARM_IN and VDD_SOC_IN (and 1.5V on the output side of the LDO).
> So you can simply set your PMIC in the bootloader to something between
> that and 1.175v and be done with it right?
> 
Not for power reduction, just for match with the voltage setting which data
sheet saying in any time or any narrow timing window. Have to set VDDRAM_IN
1.3v for 800Mhz(VDDARM 1.175v) before ldo-bypass mode switched. And set
VDDARM_IN to 1.175v after ldo-bypass mode switched. But in the narrow window
which VDDARM_IN from 1.3v to 1.175v with ldo-bypass mode enabled. The 1.3v
plus power ripple may beyond the max volage.
> >> This brings me to the question of why does LDO bypass have anything at
> >> all do to with the bootloader?
> >>
> > We only need do once ldo-bypass switch, so we hope it can be implemented in
> > u-boot
> 
> It doesn't belong in uboot. It was wrong for Freescale to create a
> dependence between the bootloader and the kernel when it is so easy to
> avoid.
> 
> I don't think any of this particular patch should go into mainline uboot.
> 
Tim, thanks for your reviewing, understood your concerning. Looks it's better
done in kernel.
> Regards,
> 
> Tim
Tim Harvey Feb. 24, 2015, 3:56 p.m. UTC | #12
On Fri, Feb 13, 2015 at 12:16 AM, Robin Gong <b38343@freescale.com> wrote:
> On Wed, Feb 11, 2015 at 07:47:57AM -0800, Tim Harvey wrote:
>> On Wed, Feb 11, 2015 at 2:49 AM, Robin Gong <b38343@freescale.com> wrote:
>> <snip>
>> >>
>> >> This is very board dependent. Here you are referring to a board that
>> >> has a reset input to the PMIC's from the IMX6's watchdog output. In
>> >> this case, this reset routing/pinmux would be needed regardless of
>> >> using ldo-bypass mode or not and that should just be a pinmux of the
>> >> pin your using for WDOG_B.
>> >>
>> > There are two types of reboot in our chip by watchdog : SRS/warm reset
>> > (Software Reset Signal) and WDOG_B(reset signal output to external pmic
>> > to trigger next power cycle). In fact, warm reset can work most cases except
>> > ldo-bypass mode and this is why we connect WDOG_B reset and ldo-bypass here:
>> > kernel may trigger warm reset at the lowest cpu freq setpoint, for example
>> > VDDARM 0.975v@396Mhz ldo-bypass mode. i.mx6q will reboot with ldo-enable mode
>> > @792Mhz and the VDDARM_IN 0.975v can't support system boot.Thus, we need use
>> > WDOG_B pin to reset external pmic if using ldo-byapss mode.
>>
>> Hi Robin,
>>
>> I understand that configuring WDOG_B external reset must be used when
>> LDO bypass is used. This should be done in the kernel but you can also
>> set this pinmux up in uboot in the board-specific init.
>>
>> If your kernel is providing the PMIC driver and cpufreq driver that
>> alter the cpu core frequencies it must also be configuring pinmux so
>> that WDOG_B gets routed to the pin that connects to the PMIC so any
>> reset based on that wdog (SRS or timeout) issues a hard reset to the
>> PMIC. Failure to do so is a kernel bug. I believe this is done
>> properly in the Freescale kernel for the reference boards.
>>
> pinmux is not enough. WDT bit of WDOGx_WCR need to be taken care of if you want
> to enable WDOG_B pin reset function. But unfortunately the current wdog driver
> of kernel not touch this write-once bit. To limit the impact from kernel, set
> this bit in u-boot.

Hi Robin,

'To limit the impact from kernel, set this bit in u-boot' indicates
that you are trying to create a u-boot and kernel dependence on each
other which is a bad idea. The kernel should take care of everything
it needs without making assumptions on what the bootloader did.

You are correct in that the current imx2_wdt.c does not 'set' the
write-once WCR bit to enable the external reset but it does seem funny
to me that Freescale decided to patch system.c's mxc_restart
(http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/commit/arch/arm/mach-imx/system.c?h=imx_3.10.53_1.1.0_ga&id=ee07b144e1adff13d262e7f353f5804e3c2d3e06)
to try to deal with the machine_restart case but did not patch
imx2_wdt.c to deal with the watchdog timeout case.

Wouldn't these boards also hang when reset from a watchdog timeout
when using ldo-enabled and CPU@397Mhz. It seems to me that you should
also be patching imx2_wdt.c to set WCR for that case.

>> If you are trying to take care of an issue caused by a watchdog reset
>> (SRS or timeout) not properly resetting a PMIC (ie perhaps a PCB
>> errata where signal doesn't go to the PMIC) then you should probably
>> simply set the PMIC rails where they need to be for the 800MHz
>> operation in the bootloader and not muck with the CPU frequency.
>> Honestly, if your PMIC rails are too low for 800MHz on powerup your
>> bootloader may not be stable anyway right? Note that the operating
>> setpoints have the same SOC voltage for both 792MHz and 396MHz, its
>> only the ARM voltage that is lower for 396 vs 792 and chances are your
>> not going to have an issue just in the bootloader at that point.
>>
> As you saw in another mail, bootloader is too late. It'll hang in ROM code.
>>
<snip>
>>
> Can you please share me the patch link? Thanks.

The link was further up in the thread in response to Peng:

Instead of touching U-Boot, in my 'Freescale' kernel I look for the
fsl,ldo-bypass node in the kernel init and enable it just like their
bootloader would have:

https://github.com/Gateworks/linux-imx6/commit/a1af6ac6f00b4da7c8a5656e8ff093d4ab5cadee

It is still not good to rely on the fsl,ldo-bypass property to be set
(which will never make it into mainline) because this does not
garuntee that ldo-bypass is setup and functioning correctly at all (ie
user could have PMIC driver disabled, or not configured in device-tree
properly as source for arm/soc rails) but I haven't figured out the
best solution upstream yet and haven't had time to get back to it. Its
still a much lesser evil than requiring that ldo-bypass be configured
in the bootloader. This patch removes the dependence upon the
bootloader (I will never use Freescales hacked up U-Boot - I think its
still based on a 2009 branch).

I have given up on getting patches into Freescale's kernel - perhaps
being an employee you will have better luck :) I'm still hoping that
someday mainline linux will have all the IPU/VPU/GPU support for IMX6
that is missing (but getting very close!) which is what is forcing me
to use Freescale's kernel for some of our BSP's.

Tim
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
index 5f5f497..5d02755 100644
--- a/arch/arm/cpu/armv7/mx6/soc.c
+++ b/arch/arm/cpu/armv7/mx6/soc.c
@@ -18,6 +18,7 @@ 
 #include <asm/arch/sys_proto.h>
 #include <asm/imx-common/boot_mode.h>
 #include <asm/imx-common/dma.h>
+#include <libfdt.h>
 #include <stdbool.h>
 #include <asm/arch/mxc_hdmi.h>
 #include <asm/arch/crm_regs.h>
@@ -429,6 +430,146 @@  void s_init(void)
 	writel(mask528, &anatop->pfd_528_clr);
 }
 
+#ifdef CONFIG_LDO_BYPASS_CHECK
+DECLARE_GLOBAL_DATA_PTR;
+static int ldo_bypass;
+
+int check_ldo_bypass(void)
+{
+	const int *ldo_mode;
+	int node;
+
+	/* get the right fdt_blob from the global working_fdt */
+	gd->fdt_blob = working_fdt;
+	/* Get the node from FDT for anatop ldo-bypass */
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+		"fsl,imx6q-gpc");
+	if (node < 0) {
+		printf("No gpc device node %d, force to ldo-enable.\n", node);
+		return 0;
+	}
+	ldo_mode = fdt_getprop(gd->fdt_blob, node, "fsl,ldo-bypass", NULL);
+	/*
+	 * return 1 if "fsl,ldo-bypass = <1>", else return 0 if
+	 * "fsl,ldo-bypass = <0>" or no "fsl,ldo-bypass" property
+	 */
+	ldo_bypass = fdt32_to_cpu(*ldo_mode) == 1 ? 1 : 0;
+
+	return ldo_bypass;
+}
+
+int check_1_2G(void)
+{
+	u32 reg;
+	int result = 0;
+	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+	struct fuse_bank *bank = &ocotp->bank[0];
+	struct fuse_bank0_regs *fuse_bank0 =
+			(struct fuse_bank0_regs *)bank->fuse_regs;
+
+	reg = readl(&fuse_bank0->cfg3);
+	if (((reg >> 16) & 0x3) == 0x3) {
+		if (ldo_bypass) {
+			printf("Wrong dtb file used! i.MX6Q@1.2Ghz only works with ldo-enable mode!\n");
+			/*
+			 * Currently, only imx6q-sabresd board might be here,
+			 * since only i.MX6Q support 1.2G and only Sabresd board
+			 * support ldo-bypass mode. So hardcode here.
+			 * You can also modify your board(i.MX6Q) dtb name if it
+			 * supports both ldo-bypass and ldo-enable mode.
+			 */
+			printf("Please use imx6q-sabresd-ldo.dtb!\n");
+			hang();
+		}
+		result = 1;
+	}
+
+	return result;
+}
+
+static int arm_orig_podf;
+void set_arm_freq_400M(bool is_400M)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	if (is_400M)
+		writel(0x1, &mxc_ccm->cacrr);
+	else
+		writel(arm_orig_podf, &mxc_ccm->cacrr);
+}
+
+void prep_anatop_bypass(void)
+{
+	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+	arm_orig_podf = readl(&mxc_ccm->cacrr);
+	/*
+	 * Downgrade ARM speed to 400Mhz as half of boot 800Mhz before ldo
+	 * bypassed, also downgrade internal vddarm ldo to 0.975V.
+	 * VDDARM_IN 0.975V + 125mV = 1.1V < Max(1.3V)
+	 * otherwise at 800Mhz(i.mx6dl):
+	 * VDDARM_IN 1.175V + 125mV = 1.3V = Max(1.3V)
+	 * We need provide enough gap in this case.
+	 * skip if boot from 400M.
+	 */
+	if (!arm_orig_podf)
+		set_arm_freq_400M(true);
+#if !defined(CONFIG_MX6DL) && !defined(CONFIG_MX6SX)
+	set_ldo_voltage(LDO_ARM, 975);
+#else
+	set_ldo_voltage(LDO_ARM, 1150);
+#endif
+}
+
+void set_wdog_reset(struct wdog_regs *wdog)
+{
+	u32 reg = readw(&wdog->wcr);
+	/*
+	 * use WDOG_B mode to reset external pmic because it's risky for the
+	 * following watchdog reboot in case of cpu freq at lowest 400Mhz with
+	 * ldo-bypass mode. Because boot frequency maybe higher 800Mhz i.e. So
+	 * in ldo-bypass mode watchdog reset will only triger POR reset, not
+	 * WDOG reset. But below code depends on hardware design, if HW didn't
+	 * connect WDOG_B pin to external pmic such as i.mx6slevk, we can skip
+	 * these code since it assumed boot from 400Mhz always.
+	 */
+	reg = readw(&wdog->wcr);
+	reg |= 1 << 3;
+	/*
+	 * WDZST bit is write-once only bit. Align this bit in kernel,
+	 * otherwise kernel code will have no chance to set this bit.
+	 */
+	reg |= 1 << 0;
+	writew(reg, &wdog->wcr);
+}
+
+int set_anatop_bypass(int wdog_reset_pin)
+{
+	struct mxc_ccm_reg *ccm_regs = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+	struct wdog_regs *wdog;
+	u32 reg = readl(&ccm_regs->reg_core);
+
+	/* bypass VDDARM/VDDSOC */
+	reg = reg | (0x1F << 18) | 0x1F;
+	writel(reg, &ccm_regs->reg_core);
+
+	if (wdog_reset_pin == 2)
+		wdog = (struct wdog_regs *)WDOG2_BASE_ADDR;
+	else if (wdog_reset_pin == 1)
+		wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
+	else
+		return arm_orig_podf;
+	set_wdog_reset(wdog);
+	return arm_orig_podf;
+}
+
+void finish_anatop_bypass(void)
+{
+	if (!arm_orig_podf)
+		set_arm_freq_400M(false);
+}
+#endif
+
 #ifdef CONFIG_IMX_HDMI
 void imx_enable_hdmi_phy(void)
 {
diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h
index 28ba844..e6f2112 100644
--- a/arch/arm/include/asm/arch-mx6/sys_proto.h
+++ b/arch/arm/include/asm/arch-mx6/sys_proto.h
@@ -28,6 +28,15 @@  const char *get_imx_type(u32 imxtype);
 unsigned imx_ddr_size(void);
 void set_chipselect_size(int const);
 
+void set_wdog_reset(struct wdog_regs *wdog);
+#ifdef CONFIG_LDO_BYPASS_CHECK
+int check_ldo_bypass(void);
+int check_1_2G(void);
+void ldo_mode_set(int ldo_bypass);
+int set_anatop_bypass(int wdog_reset_pin);
+void prep_anatop_bypass(void);
+void finish_anatop_bypass(void);
+#endif
 /*
  * Initializes on-chip ethernet controllers.
  * to override, implement board_eth_init()