From patchwork Wed Feb 16 06:52:44 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Walmsley X-Patchwork-Id: 566021 X-Patchwork-Delegate: paul@pwsan.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p1G6sGtT021604 for ; Wed, 16 Feb 2011 06:54:51 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752874Ab1BPGyH (ORCPT ); Wed, 16 Feb 2011 01:54:07 -0500 Received: from utopia.booyaka.com ([72.9.107.138]:47507 "EHLO utopia.booyaka.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751378Ab1BPGyD (ORCPT ); Wed, 16 Feb 2011 01:54:03 -0500 Received: (qmail 11964 invoked by uid 1019); 16 Feb 2011 06:54:02 -0000 MBOX-Line: From nobody Tue Feb 15 23:52:44 2011 Subject: [PATCH 02/11] OMAP2: clock: add DPLL autoidle support To: linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org From: Paul Walmsley Cc: Kevin Hilman Date: Tue, 15 Feb 2011 23:52:44 -0700 Message-ID: <20110216065243.22089.78413.stgit@twilight.localdomain> In-Reply-To: <20110216065030.22089.61217.stgit@twilight.localdomain> References: <20110216065030.22089.61217.stgit@twilight.localdomain> User-Agent: StGit/0.15 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.6 (demeter1.kernel.org [140.211.167.41]); Wed, 16 Feb 2011 06:54:51 +0000 (UTC) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 3a798ef..41cb404 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -112,7 +112,8 @@ obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o \ clkt2xxx_sys.o \ clkt2xxx_dpllcore.o \ clkt2xxx_virt_prcm_set.o \ - clkt2xxx_apll.o clkt2xxx_osc.o + clkt2xxx_apll.o clkt2xxx_osc.o \ + clkt2xxx_dpll.o obj-$(CONFIG_ARCH_OMAP2420) += clock2420_data.o obj-$(CONFIG_ARCH_OMAP2430) += clock2430.o clock2430_data.o obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o \ diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c new file mode 100644 index 0000000..1502a7b --- /dev/null +++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c @@ -0,0 +1,63 @@ +/* + * OMAP2-specific DPLL control functions + * + * Copyright (C) 2011 Nokia Corporation + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include + +#include "clock.h" +#include "cm2xxx_3xxx.h" +#include "cm-regbits-24xx.h" + +/* Private functions */ + +/** + * _allow_idle - enable DPLL autoidle bits + * @clk: struct clk * of the DPLL to operate on + * + * Enable DPLL automatic idle control. The DPLL will enter low-power + * stop when its downstream clocks are gated. No return value. + * REVISIT: DPLL can optionally enter low-power bypass by writing 0x1 + * instead. Add some mechanism to optionally enter this mode. + */ +static void _allow_idle(struct clk *clk) +{ + if (!clk || !clk->dpll_data) + return; + + omap2xxx_cm_set_dpll_auto_low_power_stop(); +} + +/** + * _deny_idle - prevent DPLL from automatically idling + * @clk: struct clk * of the DPLL to operate on + * + * Disable DPLL automatic idle control. No return value. + */ +static void _deny_idle(struct clk *clk) +{ + if (!clk || !clk->dpll_data) + return; + + omap2xxx_cm_set_dpll_disable_autoidle(); +} + + +/* Public data */ + +const struct clkops clkops_omap2xxx_dpll_ops = { + .allow_idle = _allow_idle, + .deny_idle = _deny_idle, +}; + diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 0725a6a..9972d89 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -148,6 +148,7 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) #define omap2_clk_exit_cpufreq_table 0 #endif +extern const struct clkops clkops_omap2xxx_dpll_ops; extern const struct clkops clkops_omap3_noncore_dpll_ops; extern const struct clkops clkops_omap3_core_dpll_ops; extern const struct clkops clkops_omap4_dpllmx_ops; diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index ee73e14..30fbcbd 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -125,7 +125,7 @@ static struct dpll_data dpll_dd = { */ static struct clk dpll_ck = { .name = "dpll_ck", - .ops = &clkops_null, + .ops = &clkops_omap2xxx_dpll_ops, .parent = &sys_ck, /* Can be func_32k also */ .dpll_data = &dpll_dd, .clkdm_name = "wkup_clkdm", diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index a1298e5..1ff150a 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -125,7 +125,7 @@ static struct dpll_data dpll_dd = { */ static struct clk dpll_ck = { .name = "dpll_ck", - .ops = &clkops_null, + .ops = &clkops_omap2xxx_dpll_ops, .parent = &sys_ck, /* Can be func_32k also */ .dpll_data = &dpll_dd, .clkdm_name = "wkup_clkdm", diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c index 96954aa..6b0c7c8 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c @@ -25,6 +25,10 @@ #include "cm-regbits-24xx.h" #include "cm-regbits-34xx.h" +/* CM_AUTOIDLE_PLL.AUTO_* bit values */ +#define DPLL_AUTOIDLE_DISABLE 0x0 +#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP 0x3 + static const u8 cm_idlest_offs[] = { CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3 }; @@ -125,6 +129,29 @@ void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask) _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask); } +/* + * DPLL autoidle control + */ + +static void _omap2xxx_set_dpll_autoidle(u8 m) +{ + u32 v; + + v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); + v &= ~OMAP24XX_AUTO_DPLL_MASK; + v |= m << OMAP24XX_AUTO_DPLL_SHIFT; + omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE); +} + +void omap2xxx_cm_set_dpll_disable_autoidle(void) +{ + _omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP); +} + +void omap2xxx_cm_set_dpll_auto_low_power_stop(void) +{ + _omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE); +} /* * diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h index 5e9ea5b..5f4df1c 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h @@ -122,6 +122,9 @@ extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask); extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask); extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask); +extern void omap2xxx_cm_set_dpll_disable_autoidle(void); +extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void); + #endif /* CM register bits shared between 24XX and 3430 */ diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 97feb3a..23b4607 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -378,6 +378,7 @@ static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; + u32 v; /* Enable autoidle */ omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, @@ -468,11 +469,12 @@ static void __init prcm_setup_regs(void) omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD, CM_AUTOIDLE); - /* Put DPLL and both APLLs into autoidle mode */ - omap2_cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) | - (0x03 << OMAP24XX_AUTO_96M_SHIFT) | - (0x03 << OMAP24XX_AUTO_54M_SHIFT), - PLL_MOD, CM_AUTOIDLE); + /* Put both APLLs into autoidle mode */ + v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); + v &= ~(OMAP24XX_AUTO_96M_MASK | OMAP24XX_AUTO_54M_SHIFT); + v |= (0x03 << OMAP24XX_AUTO_96M_SHIFT) | + (0x03 << OMAP24XX_AUTO_54M_SHIFT); + omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE); omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK | OMAP24XX_AUTO_WDT1_MASK |