public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Stefano Babic <sbabic@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 07/12] imx:mx6 Support LDO bypass
Date: Tue, 10 Feb 2015 12:23:57 +0100	[thread overview]
Message-ID: <54D9EA4D.7010307@denx.de> (raw)
In-Reply-To: <1420793987-7621-8-git-send-email-Peng.Fan@freescale.com>

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 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.
> 
> 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 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.

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

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

  reply	other threads:[~2015-02-10 11:23 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-09  8:59 [U-Boot] [PATCH 00/12] imx:mx6 add ldo bypass Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 01/12] imx:mx6slevk add pmic and i2c configuration Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 02/12] imx:mx6sl add I2c pad settings Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 03/12] imx:mx6slevk implement power init board Peng Fan
2015-02-10 11:01   ` Stefano Babic
2015-01-09  8:59 ` [U-Boot] [PATCH 04/12] imx:mx6 update mxc_ccm_reg Peng Fan
2015-02-10 11:03   ` Stefano Babic
2015-02-11  2:19     ` Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 05/12] imx:mx6 update fuse_bank0_regs Peng Fan
2015-02-10 11:51   ` Stefano Babic
2015-01-09  8:59 ` [U-Boot] [PATCH 06/12] pmic:pfuze add macro for setting voltage Peng Fan
2015-02-10 11:54   ` Stefano Babic
2015-02-11  2:06     ` Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 07/12] imx:mx6 Support LDO bypass Peng Fan
2015-02-10 11:23   ` Stefano Babic [this message]
2015-02-10 14:50     ` Tim Harvey
2015-02-10 14:59       ` Fabio Estevam
2015-02-10 15:29         ` Tim Harvey
2015-02-11  8:42       ` Stefano Babic
2015-02-10 14:33   ` Tim Harvey
2015-02-11 10:49     ` Robin Gong
2015-02-11 15:47       ` Tim Harvey
2015-02-13  0:08         ` Tim Harvey
2015-02-13  7:20           ` Robin Gong
2015-02-13  8:16         ` Robin Gong
2015-02-24 15:56           ` Tim Harvey
2015-01-09  8:59 ` [U-Boot] [PATCH 08/12] imx:mx6slevk add ldo mode set function Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 09/12] imx:mx6sabresd Add ldo_mode_set function Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 10/12] imx:mx6sxsabresd add ldo mode set function Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 11/12] imx:mx6qsabreauto add ldo mode init Peng Fan
2015-01-09  8:59 ` [U-Boot] [PATCH 12/12] ARM:imx call ldo_mode_set in arch_preboot_os Peng Fan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54D9EA4D.7010307@denx.de \
    --to=sbabic@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox