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