From 404fd02e96d33840f58f83f88815e2a259cdc532 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Thu, 7 Aug 2014 18:09:44 +0800 Subject: ENGR00326277-1: imx6: ldo_bypass: fix VDDARM voltage setting violate datasheet Current only set VDDARM_IN@1.175V/VDDSOC_IN@1.175V before ldo bypass switch. So untile 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. Signed-off-by: Robin Gong --- arch/arm/cpu/armv7/mx6/soc.c | 45 ++++++++++++++++++++++++++++++- arch/arm/include/asm/arch-mx6/sys_proto.h | 4 ++- 2 files changed, 47 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index 50c867c..a3f2a2a 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -835,7 +835,41 @@ int check_1_2G(void) return result; } -void set_anatop_bypass(void) +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); +#ifndef CONFIG_MX6DL + set_ldo_voltage(LDO_ARM, 975); +#else + set_ldo_voltage(LDO_ARM, 1150); +#endif +} + +int set_anatop_bypass(void) { struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; u32 reg = readl(&anatop->reg_core); @@ -843,7 +877,16 @@ void set_anatop_bypass(void) /* bypass VDDARM/VDDSOC */ reg = reg | (0x1F << 18) | 0x1F; writel(reg, &anatop->reg_core); + + return arm_orig_podf; } + +void finish_anatop_bypass(void) +{ + if (!arm_orig_podf) + set_arm_freq_400M(false); +} + #endif #ifdef CONFIG_IMX_HDMI diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h index f358c36..c8e5136 100644 --- a/arch/arm/include/asm/arch-mx6/sys_proto.h +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h @@ -26,8 +26,10 @@ unsigned imx_ddr_size(void); #ifdef CONFIG_LDO_BYPASS_CHECK int check_ldo_bypass(void); int check_1_2G(void); -void set_anatop_bypass(void); +int set_anatop_bypass(void); void ldo_mode_set(int ldo_bypass); +void prep_anatop_bypass(void); +void finish_anatop_bypass(void); #endif #ifdef CONFIG_MX6SX -- cgit v1.1