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

Tim Harvey tharvey at gateworks.com
Tue Feb 10 15:33:38 CET 2015


On Fri, Jan 9, 2015 at 12:59 AM, Peng Fan <Peng.Fan at 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 at 1.175V/VDDSOC_IN at 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 at 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


More information about the U-Boot mailing list