aboutsummaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch176
1 files changed, 176 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch b/extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch
new file mode 100644
index 00000000..16335ccb
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/dvfs/0014-OMAP3-Introduce-custom-set-rate-and-get-rate-APIs-fo.patch
@@ -0,0 +1,176 @@
+From 6fb7bd2b3da02e6e799d3c7661a1acb6572f9add Mon Sep 17 00:00:00 2001
+From: Thara Gopinath <thara@ti.com>
+Date: Wed, 18 Aug 2010 16:22:32 +0530
+Subject: [PATCH 14/20] OMAP3: Introduce custom set rate and get rate APIs for scalable devices
+
+This patch also introduces omap3_mpu_set_rate, omap3_iva_set_rate,
+omap3_l3_set_rate, omap3_mpu_get_rate, omap3_iva_get_rate,
+omap3_l3_get_rate as device specific set rate and get rate
+APIs for OMAP3 mpu, iva and l3_main devices. This patch also
+calls into omap_device_populate_rate_fns during system init to register
+various set_rate and get_rate APIs with the omap device layer
+
+Signed-off-by: Thara Gopinath <thara@ti.com>
+---
+ arch/arm/mach-omap2/pm.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 110 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
+index d5a102c..94ab0dd 100644
+--- a/arch/arm/mach-omap2/pm.c
++++ b/arch/arm/mach-omap2/pm.c
+@@ -14,6 +14,7 @@
+ #include <linux/io.h>
+ #include <linux/err.h>
+ #include <linux/opp.h>
++#include <linux/delay.h>
+
+ #include <plat/omap-pm.h>
+ #include <plat/omap_device.h>
+@@ -22,6 +23,8 @@
+
+ #include "powerdomain.h"
+ #include "clockdomain.h"
++#include "cm-regbits-34xx.h"
++#include "cm2xxx_3xxx.h"
+ #include "pm.h"
+
+ static struct omap_device_pm_latency *pm_lats;
+@@ -31,6 +34,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);
+@@ -56,6 +61,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)
+ {
+@@ -77,6 +102,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 = omap2_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 = omap2_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.
+ */
+@@ -90,6 +183,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);
++
++ }
+ }
+
+ /* Types of sleep_switch used in omap_set_pwrdm_state */
+--
+1.6.6.1
+