From patchwork Fri Jan 9 08:59:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peng Fan X-Patchwork-Id: 426966 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3E5E9140142 for ; Fri, 9 Jan 2015 20:12:00 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 58DE84B653; Fri, 9 Jan 2015 10:11:44 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id N2pjvBIOkL-M; Fri, 9 Jan 2015 10:11:44 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id AEB2B4B670; Fri, 9 Jan 2015 10:11:41 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 28DB64B657 for ; Fri, 9 Jan 2015 10:11:39 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5lckXNNSYLb4 for ; Fri, 9 Jan 2015 10:11:39 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from na01-by2-obe.outbound.protection.outlook.com (mail-by2on0140.outbound.protection.outlook.com [207.46.100.140]) by theia.denx.de (Postfix) with ESMTPS id 5200F4B663 for ; Fri, 9 Jan 2015 10:11:27 +0100 (CET) Received: from CH1PR03CA006.namprd03.prod.outlook.com (10.255.156.151) by DM2PR0301MB0734.namprd03.prod.outlook.com (25.160.97.142) with Microsoft SMTP Server (TLS) id 15.1.49.12; Fri, 9 Jan 2015 09:11:24 +0000 Received: from BL2FFO11FD007.protection.gbl (10.255.156.132) by CH1PR03CA006.outlook.office365.com (10.255.156.151) with Microsoft SMTP Server (TLS) id 15.1.53.17 via Frontend Transport; Fri, 9 Jan 2015 09:11:24 +0000 Received: from tx30smr01.am.freescale.net (192.88.168.50) by BL2FFO11FD007.mail.protection.outlook.com (10.173.161.3) with Microsoft SMTP Server (TLS) id 15.1.49.13 via Frontend Transport; Fri, 9 Jan 2015 09:11:23 +0000 Received: from linux-jyl1.ap.freescale.net (b51431-11.ap.freescale.net [10.193.102.40]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id t099A4J1016257; Fri, 9 Jan 2015 02:11:20 -0700 From: Peng Fan To: Date: Fri, 9 Jan 2015 16:59:42 +0800 Message-ID: <1420793987-7621-8-git-send-email-Peng.Fan@freescale.com> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1420793987-7621-1-git-send-email-Peng.Fan@freescale.com> References: <1420793987-7621-1-git-send-email-Peng.Fan@freescale.com> X-EOPAttributedMessage: 0 Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=Peng.Fan@freescale.com; X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(339900001)(199003)(189002)(50466002)(107046002)(85426001)(89996001)(2351001)(87936001)(50986999)(229853001)(76176999)(47776003)(64706001)(20776003)(46102003)(97736003)(86362001)(99396003)(84676001)(19580405001)(19580395003)(48376002)(4396001)(21056001)(50226001)(31966008)(6806004)(104016003)(106466001)(105606002)(92566001)(110136001)(62966003)(120916001)(77156002)(2950100001)(68736005)(36756003)(77096005); DIR:OUT; SFP:1102; SCL:1; SRVR:DM2PR0301MB0734; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; MLV:sfv; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-DmarcAction: None X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:(3005003);SRVR:DM2PR0301MB0734; X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004); SRVR:DM2PR0301MB0734; X-Forefront-PRVS: 04519BA941 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:; SRVR:DM2PR0301MB0734; X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Jan 2015 09:11:23.9195 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.168.50] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR0301MB0734 Cc: fabio.estevam@freescale.com, b38343@freescale.com, u-boot@lists.denx.de, smoch@web.de, p.marczak@samsung.com, B37916@freescale.com Subject: [U-Boot] [PATCH 07/12] imx:mx6 Support LDO bypass X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 Signed-off-by: Robin Gong Signed-off-by: Nitin Garg --- 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 #include #include +#include #include #include #include @@ -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()