1 From 42e395f0dcc618300267f440f613572635eb2e55 Mon Sep 17 00:00:00 2001
2 From: Thara Gopinath <thara@ti.com>
3 Date: Wed, 18 Aug 2010 16:22:32 +0530
4 Subject: [PATCH 14/19] OMAP3: Introduce custom set rate and get rate APIs for scalable devices
6 This patch also introduces omap3_mpu_set_rate, omap3_iva_set_rate,
7 omap3_l3_set_rate, omap3_mpu_get_rate, omap3_iva_get_rate,
8 omap3_l3_get_rate as device specific set rate and get rate
9 APIs for OMAP3 mpu, iva and l3_main devices. This patch also
10 calls into omap_device_populate_rate_fns during system init to register
11 various set_rate and get_rate APIs with the omap device layer
13 Signed-off-by: Thara Gopinath <thara@ti.com>
15 arch/arm/mach-omap2/pm.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++
16 1 files changed, 110 insertions(+), 0 deletions(-)
18 diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
19 index d5a102c..94ab0dd 100644
20 --- a/arch/arm/mach-omap2/pm.c
21 +++ b/arch/arm/mach-omap2/pm.c
24 #include <linux/err.h>
25 #include <linux/opp.h>
26 +#include <linux/delay.h>
28 #include <plat/omap-pm.h>
29 #include <plat/omap_device.h>
32 #include "powerdomain.h"
33 #include "clockdomain.h"
34 +#include "cm-regbits-34xx.h"
35 +#include "cm2xxx_3xxx.h"
38 static struct omap_device_pm_latency *pm_lats;
39 @@ -31,6 +34,8 @@ static struct device *iva_dev;
40 static struct device *l3_dev;
41 static struct device *dsp_dev;
43 +static struct clk *dpll1_clk, *dpll2_clk, *dpll3_clk;
45 struct device *omap2_get_mpuss_device(void)
47 WARN_ON_ONCE(!mpu_dev);
48 @@ -56,6 +61,26 @@ struct device *omap4_get_dsp_device(void)
50 EXPORT_SYMBOL(omap4_get_dsp_device);
52 +static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult)
54 + unsigned long new_jiffy_l, new_jiffy_h;
57 + * Recalculate loops_per_jiffy. We do it this way to
58 + * avoid math overflow on 32-bit machines. Maybe we
59 + * should make this architecture dependent? If you have
60 + * a better way of doing this, please replace!
62 + * new = old * mult / div
64 + new_jiffy_h = ref / div;
65 + new_jiffy_l = (ref % div) / 100;
66 + new_jiffy_h *= mult;
67 + new_jiffy_l = new_jiffy_l * mult / div;
69 + return new_jiffy_h + new_jiffy_l * 100;
72 /* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
73 static int _init_omap_device(char *name, struct device **new_dev)
75 @@ -77,6 +102,74 @@ static int _init_omap_device(char *name, struct device **new_dev)
79 +static unsigned long omap3_mpu_get_rate(struct device *dev)
81 + return dpll1_clk->rate;
84 +static int omap3_mpu_set_rate(struct device *dev, unsigned long rate)
86 + unsigned long cur_rate = omap3_mpu_get_rate(dev);
89 +#ifdef CONFIG_CPU_FREQ
90 + struct cpufreq_freqs freqs_notify;
92 + freqs_notify.old = cur_rate / 1000;
93 + freqs_notify.new = rate / 1000;
94 + freqs_notify.cpu = 0;
95 + /* Send pre notification to CPUFreq */
96 + cpufreq_notify_transition(&freqs_notify, CPUFREQ_PRECHANGE);
98 + ret = clk_set_rate(dpll1_clk, rate);
100 + dev_warn(dev, "%s: Unable to set rate to %ld\n",
105 +#ifdef CONFIG_CPU_FREQ
106 + /* Send a post notification to CPUFreq */
107 + cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE);
110 +#ifndef CONFIG_CPU_FREQ
111 + /*Update loops_per_jiffy if processor speed is being changed*/
112 + loops_per_jiffy = compute_lpj(loops_per_jiffy,
113 + cur_rate / 1000, rate / 1000);
118 +static int omap3_iva_set_rate(struct device *dev, unsigned long rate)
120 + return clk_set_rate(dpll2_clk, rate);
123 +static unsigned long omap3_iva_get_rate(struct device *dev)
125 + return dpll2_clk->rate;
128 +static int omap3_l3_set_rate(struct device *dev, unsigned long rate)
132 + l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
133 + OMAP3430_CLKSEL_L3_MASK;
135 + return clk_set_rate(dpll3_clk, rate * l3_div);
138 +static unsigned long omap3_l3_get_rate(struct device *dev)
142 + l3_div = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
143 + OMAP3430_CLKSEL_L3_MASK;
144 + return dpll3_clk->rate / l3_div;
148 * Build omap_devices for processors and bus.
150 @@ -90,6 +183,23 @@ static void omap2_init_processor_devices(void)
152 _init_omap_device("l3_main", &l3_dev);
155 + if (cpu_is_omap34xx()) {
156 + dpll1_clk = clk_get(NULL, "dpll1_ck");
157 + dpll2_clk = clk_get(NULL, "dpll2_ck");
158 + dpll3_clk = clk_get(NULL, "dpll3_m2_ck");
161 + omap_device_populate_rate_fns(mpu_dev,
162 + omap3_mpu_set_rate, omap3_mpu_get_rate);
164 + omap_device_populate_rate_fns(iva_dev,
165 + omap3_iva_set_rate, omap3_iva_get_rate);
167 + omap_device_populate_rate_fns(l3_dev,
168 + omap3_l3_set_rate, omap3_l3_get_rate);
173 /* Types of sleep_switch used in omap_set_pwrdm_state */