diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch')
-rw-r--r-- | extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch new file mode 100644 index 00000000..6624d1ec --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap-2.6.39/pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch | |||
@@ -0,0 +1,170 @@ | |||
1 | From f375d3c39d2835929d34c2a046b8c43cea6d1467 Mon Sep 17 00:00:00 2001 | ||
2 | From: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
3 | Date: Mon, 14 Mar 2011 17:08:49 +0530 | ||
4 | Subject: [PATCH 7/8] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430 | ||
5 | |||
6 | On OMAP SMP configuartion, both processors share the voltage | ||
7 | and clock. So both CPUs needs to be scaled together and hence | ||
8 | needs software co-ordination. | ||
9 | |||
10 | Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
11 | Cc: Kevin Hilman <khilman@ti.com> | ||
12 | cc: Vishwanath BS <vishwanath.bs@ti.com> | ||
13 | --- | ||
14 | arch/arm/mach-omap2/omap2plus-cpufreq.c | 73 ++++++++++++++++++++++++++----- | ||
15 | 1 files changed, 62 insertions(+), 11 deletions(-) | ||
16 | |||
17 | diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
18 | index 14f84cc..8d472f6 100644 | ||
19 | --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
20 | +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c | ||
21 | @@ -26,9 +26,11 @@ | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/opp.h> | ||
25 | +#include <linux/cpu.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/smp_plat.h> | ||
29 | +#include <asm/cpu.h> | ||
30 | |||
31 | #include <plat/clock.h> | ||
32 | #include <plat/omap-pm.h> | ||
33 | @@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu) | ||
34 | { | ||
35 | unsigned long rate; | ||
36 | |||
37 | - if (cpu) | ||
38 | + if (cpu >= NR_CPUS) | ||
39 | return 0; | ||
40 | |||
41 | rate = clk_get_rate(mpu_clk) / 1000; | ||
42 | @@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy, | ||
43 | unsigned int target_freq, | ||
44 | unsigned int relation) | ||
45 | { | ||
46 | - int ret = 0; | ||
47 | + int i, ret = 0; | ||
48 | struct cpufreq_freqs freqs; | ||
49 | |||
50 | + /* Changes not allowed until all CPUs are online */ | ||
51 | + if (is_smp() && (num_online_cpus() < NR_CPUS)) | ||
52 | + return ret; | ||
53 | + | ||
54 | /* Ensure desired rate is within allowed range. Some govenors | ||
55 | * (ondemand) will just pass target_freq=0 to get the minimum. */ | ||
56 | if (target_freq < policy->min) | ||
57 | @@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy, | ||
58 | if (target_freq > policy->max) | ||
59 | target_freq = policy->max; | ||
60 | |||
61 | - freqs.old = omap_getspeed(0); | ||
62 | + freqs.old = omap_getspeed(policy->cpu); | ||
63 | freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; | ||
64 | - freqs.cpu = 0; | ||
65 | + freqs.cpu = policy->cpu; | ||
66 | |||
67 | if (freqs.old == freqs.new) | ||
68 | return ret; | ||
69 | |||
70 | - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
71 | + if (!is_smp()) { | ||
72 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
73 | + goto set_freq; | ||
74 | + } | ||
75 | + | ||
76 | + /* notifiers */ | ||
77 | + for_each_cpu(i, policy->cpus) { | ||
78 | + freqs.cpu = i; | ||
79 | + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
80 | + } | ||
81 | |||
82 | +set_freq: | ||
83 | #ifdef CONFIG_CPU_FREQ_DEBUG | ||
84 | pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); | ||
85 | #endif | ||
86 | @@ -105,12 +121,33 @@ static int omap_target(struct cpufreq_policy *policy, | ||
87 | * CONFIG_SMP enabled. Below code is added only to manage that | ||
88 | * scenario | ||
89 | */ | ||
90 | - if (!is_smp()) | ||
91 | + freqs.new = omap_getspeed(policy->cpu); | ||
92 | + if (!is_smp()) { | ||
93 | loops_per_jiffy = | ||
94 | cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); | ||
95 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
96 | + goto skip_lpj; | ||
97 | + } | ||
98 | |||
99 | - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
100 | +#ifdef CONFIG_SMP | ||
101 | + /* | ||
102 | + * Note that loops_per_jiffy is not updated on SMP systems in | ||
103 | + * cpufreq driver. So, update the per-CPU loops_per_jiffy value | ||
104 | + * on frequency transition. We need to update all dependent CPUs. | ||
105 | + */ | ||
106 | + for_each_cpu(i, policy->cpus) | ||
107 | + per_cpu(cpu_data, i).loops_per_jiffy = | ||
108 | + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, | ||
109 | + freqs.old, freqs.new); | ||
110 | +#endif | ||
111 | |||
112 | + /* notifiers */ | ||
113 | + for_each_cpu(i, policy->cpus) { | ||
114 | + freqs.cpu = i; | ||
115 | + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
116 | + } | ||
117 | + | ||
118 | +skip_lpj: | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | @@ -118,6 +155,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
123 | { | ||
124 | int result = 0; | ||
125 | struct device *mpu_dev; | ||
126 | + static cpumask_var_t cpumask; | ||
127 | |||
128 | if (cpu_is_omap24xx()) | ||
129 | mpu_clk = clk_get(NULL, "virt_prcm_set"); | ||
130 | @@ -129,12 +167,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
131 | if (IS_ERR(mpu_clk)) | ||
132 | return PTR_ERR(mpu_clk); | ||
133 | |||
134 | - if (policy->cpu != 0) | ||
135 | + if (policy->cpu >= NR_CPUS) | ||
136 | return -EINVAL; | ||
137 | |||
138 | - policy->cur = policy->min = policy->max = omap_getspeed(0); | ||
139 | - | ||
140 | + policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); | ||
141 | mpu_dev = omap2_get_mpuss_device(); | ||
142 | + | ||
143 | if (!mpu_dev) { | ||
144 | pr_warning("%s: unable to get the mpu device\n", __func__); | ||
145 | return -EINVAL; | ||
146 | @@ -154,7 +192,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) | ||
147 | |||
148 | policy->min = policy->cpuinfo.min_freq; | ||
149 | policy->max = policy->cpuinfo.max_freq; | ||
150 | - policy->cur = omap_getspeed(0); | ||
151 | + policy->cur = omap_getspeed(policy->cpu); | ||
152 | + | ||
153 | + /* | ||
154 | + * On OMAP SMP configuartion, both processors share the voltage | ||
155 | + * and clock. So both CPUs needs to be scaled together and hence | ||
156 | + * needs software co-ordination. Use cpufreq affected_cpus | ||
157 | + * interface to handle this scenario. Additional is_smp() check | ||
158 | + * is to keep SMP_ON_UP build working. | ||
159 | + */ | ||
160 | + if (is_smp()) { | ||
161 | + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; | ||
162 | + cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask); | ||
163 | + cpumask_copy(policy->cpus, cpumask); | ||
164 | + } | ||
165 | |||
166 | /* FIXME: what's the actual transition time? */ | ||
167 | policy->cpuinfo.transition_latency = 300 * 1000; | ||
168 | -- | ||
169 | 1.6.6.1 | ||
170 | |||