From patchwork Fri Oct 29 15:38:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thara Gopinath X-Patchwork-Id: 290582 X-Patchwork-Delegate: khilman@deeprootsystems.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 o9TFckX8013015 for ; Fri, 29 Oct 2010 15:38:46 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933900Ab0J2Pin (ORCPT ); Fri, 29 Oct 2010 11:38:43 -0400 Received: from bear.ext.ti.com ([192.94.94.41]:34619 "EHLO bear.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933859Ab0J2Pil (ORCPT ); Fri, 29 Oct 2010 11:38:41 -0400 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id o9TFcb3Z020215 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 29 Oct 2010 10:38:39 -0500 Received: from localhost.localdomain (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id o9TFcTYu012648; Fri, 29 Oct 2010 21:08:35 +0530 (IST) From: Thara Gopinath To: linux-omap@vger.kernel.org Cc: paul@pwsan.com, khilman@deeprootsystems.com, b-cousson@ti.com, vishwanath.bs@ti.com, sawant@ti.com, Thara Gopinath Subject: [PATCH v2 10/14] OMAP3: Introduce custom set rate and get rate APIs for scalable devices Date: Fri, 29 Oct 2010 21:08:24 +0530 Message-Id: <1288366708-32302-11-git-send-email-thara@ti.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1288366708-32302-1-git-send-email-thara@ti.com> References: <1288366708-32302-1-git-send-email-thara@ti.com> 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 (demeter1.kernel.org [140.211.167.41]); Fri, 29 Oct 2010 15:38:46 +0000 (UTC) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 0651667..0fa7fca 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,8 @@ #include #include +#include "cm-regbits-34xx.h" +#include "prm.h" #include "pm.h" static struct omap_device_pm_latency *pm_lats; @@ -32,6 +35,8 @@ static struct device *iva_dev; static struct device *l3_dev; static struct device *dsp_dev; +static struct clk *dpll1_clk, *dpll2_clk, *dpll3_clk; + struct device *omap2_get_mpuss_device(void) { WARN_ON_ONCE(!mpu_dev); @@ -57,6 +62,26 @@ struct device *omap4_get_dsp_device(void) } EXPORT_SYMBOL(omap4_get_dsp_device); +static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult) +{ + unsigned long new_jiffy_l, new_jiffy_h; + + /* + * Recalculate loops_per_jiffy. We do it this way to + * avoid math overflow on 32-bit machines. Maybe we + * should make this architecture dependent? If you have + * a better way of doing this, please replace! + * + * new = old * mult / div + */ + new_jiffy_h = ref / div; + new_jiffy_l = (ref % div) / 100; + new_jiffy_h *= mult; + new_jiffy_l = new_jiffy_l * mult / div; + + return new_jiffy_h + new_jiffy_l * 100; +} + /* static int _init_omap_device(struct omap_hwmod *oh, void *user) */ static int _init_omap_device(char *name, struct device **new_dev) { @@ -78,6 +103,74 @@ static int _init_omap_device(char *name, struct device **new_dev) return 0; } +static unsigned long omap3_mpu_get_rate(struct device *dev) +{ + return dpll1_clk->rate; +} + +static int omap3_mpu_set_rate(struct device *dev, unsigned long rate) +{ + unsigned long cur_rate = omap3_mpu_get_rate(dev); + int ret; + +#ifdef CONFIG_CPU_FREQ + struct cpufreq_freqs freqs_notify; + + freqs_notify.old = cur_rate / 1000; + freqs_notify.new = rate / 1000; + freqs_notify.cpu = 0; + /* Send pre notification to CPUFreq */ + cpufreq_notify_transition(&freqs_notify, CPUFREQ_PRECHANGE); +#endif + ret = clk_set_rate(dpll1_clk, rate); + if (ret) { + dev_warn(dev, "%s: Unable to set rate to %ld\n", + __func__, rate); + return ret; + } + +#ifdef CONFIG_CPU_FREQ + /* Send a post notification to CPUFreq */ + cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE); +#endif + +#ifndef CONFIG_CPU_FREQ + /*Update loops_per_jiffy if processor speed is being changed*/ + loops_per_jiffy = compute_lpj(loops_per_jiffy, + cur_rate / 1000, rate / 1000); +#endif + return 0; +} + +static int omap3_iva_set_rate(struct device *dev, unsigned long rate) +{ + return clk_set_rate(dpll2_clk, rate); +} + +static unsigned long omap3_iva_get_rate(struct device *dev) +{ + return dpll2_clk->rate; +} + +static int omap3_l3_set_rate(struct device *dev, unsigned long rate) +{ + int l3_div; + + l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & + OMAP3430_CLKSEL_L3_MASK; + + return clk_set_rate(dpll3_clk, rate * l3_div); +} + +static unsigned long omap3_l3_get_rate(struct device *dev) +{ + int l3_div; + + l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & + OMAP3430_CLKSEL_L3_MASK; + return dpll3_clk->rate / l3_div; +} + /* * Build omap_devices for processors and bus. */ @@ -91,6 +184,23 @@ static void omap2_init_processor_devices(void) } else { _init_omap_device("l3_main", &l3_dev); } + + if (cpu_is_omap34xx()) { + dpll1_clk = clk_get(NULL, "dpll1_ck"); + dpll2_clk = clk_get(NULL, "dpll2_ck"); + dpll3_clk = clk_get(NULL, "dpll3_m2_ck"); + + if (mpu_dev) + omap_device_populate_rate_fns(mpu_dev, + omap3_mpu_set_rate, omap3_mpu_get_rate); + if (iva_dev) + omap_device_populate_rate_fns(iva_dev, + omap3_iva_set_rate, omap3_iva_get_rate); + if (l3_dev) + omap_device_populate_rate_fns(l3_dev, + omap3_l3_set_rate, omap3_l3_get_rate); + + } } /*