From patchwork Tue Feb 9 10:58:14 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "G.N, Vijayakumar" X-Patchwork-Id: 77996 X-Patchwork-Delegate: paul@pwsan.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o19AwohC018316 for ; Tue, 9 Feb 2010 10:58:51 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754088Ab0BIK6s (ORCPT ); Tue, 9 Feb 2010 05:58:48 -0500 Received: from arroyo.ext.ti.com ([192.94.94.40]:32885 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754062Ab0BIK6r convert rfc822-to-8bit (ORCPT ); Tue, 9 Feb 2010 05:58:47 -0500 Received: from dbdp20.itg.ti.com ([172.24.170.38]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id o19AwhJS030863 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 9 Feb 2010 04:58:46 -0600 Received: from dbde70.ent.ti.com (localhost [127.0.0.1]) by dbdp20.itg.ti.com (8.13.8/8.13.8) with ESMTP id o19AwfdQ005828; Tue, 9 Feb 2010 16:28:41 +0530 (IST) Received: from dbde02.ent.ti.com ([172.24.170.145]) by dbde70.ent.ti.com ([172.24.170.148]) with mapi; Tue, 9 Feb 2010 16:28:41 +0530 From: "G.N, Vijayakumar" To: "linux-omap@vger.kernel.org" CC: "Sripathy, Vishwanath" , "Turquette, Mike" , "khilman@deeprootsystems.com" , "paul@pwsan.com" Date: Tue, 9 Feb 2010 16:28:14 +0530 Subject: [PATCHV3] OMAP3630: Clock: Workaround for DPLL HS divider limitation Thread-Topic: [PATCHV3] OMAP3630: Clock: Workaround for DPLL HS divider limitation Thread-Index: AcqmaPSorFK7Xno8Qzi7GOg9JEfHzgDDT4tw Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Tue, 09 Feb 2010 10:58:51 +0000 (UTC) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index c1c1b93..1e6297f 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -133,6 +133,47 @@ const struct clkops clkops_omap3430es2_hsotgusb_wait = { .find_companion = omap2_clk_dflt_find_companion, }; +/** + * omap3_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering + * from HSDivider PWRDN problem Implements Errata ID: i556. + * @clk: DPLL output struct clk + * + * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck, dpll4_m5_ck + * & dpll4_m6_ck dividers gets loaded with reset valueafter their respective + * PWRDN bits are set. + * Any dummy write (Any other value different from the Read value) to the + * corresponding CM_CLKSEL register will refresh the dividers. + */ +int omap3_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk) +{ + u32 dummy_v, orig_v, clksel_shift; + int ret; + + /* Enable PWRDN bit of HSDIVIDER */ + ret = omap2_dflt_clk_enable(clk); + + /* Restore the dividers */ + if (!ret) { + clksel_shift = __ffs(clk->parent->clksel_mask); + orig_v = dummy_v = __raw_readl(clk->parent->clksel_reg); + + /* Write any other value different from the Read value */ + dummy_v ^= (1 << clksel_shift); + __raw_writel(dummy_v, clk->parent->clksel_reg); + + /* Write the original divider */ + __raw_writel(orig_v, clk->parent->clksel_reg); + } + return ret; +} + +const struct clkops clkops_omap3_pwrdn_with_hsdiv_wait_restore = { + .enable = omap3_pwrdn_clk_enable_with_hsdiv_restore, + .disable = omap2_dflt_clk_disable, + .find_companion = omap2_clk_dflt_find_companion, + .find_idlest = omap2_clk_dflt_find_idlest, +}; + const struct clkops omap3_clkops_noncore_dpll_ops = { .enable = omap3_noncore_dpll_enable, .disable = omap3_noncore_dpll_disable, diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 313efc0..29ef390 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -21,5 +21,6 @@ extern const struct clkops clkops_omap3430es2_ssi_wait; extern const struct clkops clkops_omap3430es2_hsotgusb_wait; extern const struct clkops clkops_omap3430es2_dss_usbhost_wait; extern const struct clkops omap3_clkops_noncore_dpll_ops; +extern const struct clkops clkops_omap3_pwrdn_with_hsdiv_wait_restore; #endif diff --git a/arch/arm/mach-omap2/clock34xx_data.c b/arch/arm/mach-omap2/clock34xx_data.c index 8728f1f..9d11d53 100644 --- a/arch/arm/mach-omap2/clock34xx_data.c +++ b/arch/arm/mach-omap2/clock34xx_data.c @@ -3240,6 +3240,26 @@ int __init omap3xxx_clk_init(void) } } + if (cpu_is_omap3630()) { + + /* + * For 3630: override clkops_omap2_dflt_wait for the + * clocks affected from PWRDN reset Limitation + */ + dpll3_m3x2_ck.ops = + &clkops_omap3_pwrdn_with_hsdiv_wait_restore; + dpll4_m2x2_ck.ops = + &clkops_omap3_pwrdn_with_hsdiv_wait_restore; + dpll4_m3x2_ck.ops = + &clkops_omap3_pwrdn_with_hsdiv_wait_restore; + dpll4_m4x2_ck.ops = + &clkops_omap3_pwrdn_with_hsdiv_wait_restore; + dpll4_m5x2_ck.ops = + &clkops_omap3_pwrdn_with_hsdiv_wait_restore; + dpll4_m6x2_ck.ops = + &clkops_omap3_pwrdn_with_hsdiv_wait_restore; + } + clk_init(&omap2_clk_functions); for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++)