Contents of /trunk/kernel26-magellan/patches-2.6.21-r13/0156-2.6.21-linux-phc-0.2.10.patch
Parent Directory | Revision Log
Revision 319 -
(show annotations)
(download)
Sun Aug 19 18:14:21 2007 UTC (17 years, 1 month ago) by niro
File size: 36051 byte(s)
Sun Aug 19 18:14:21 2007 UTC (17 years, 1 month ago) by niro
File size: 36051 byte(s)
-2.6.21-magellan-r13
1 | diff --new-file -a --unified=5 --recursive --exclude-from=diff.excludes linux.org/arch/i386/kernel/cpu/cpufreq/Kconfig linux.phc/arch/i386/kernel/cpu/cpufreq/Kconfig |
2 | --- linux.org/arch/i386/kernel/cpu/cpufreq/Kconfig 2007-05-12 15:41:54.000000000 +0200 |
3 | +++ linux.phc/arch/i386/kernel/cpu/cpufreq/Kconfig 2007-05-12 16:21:52.000000000 +0200 |
4 | @@ -1,9 +1,12 @@ |
5 | # |
6 | # CPU Frequency scaling |
7 | # |
8 | |
9 | +# This file has been patched with Linux PHC: https://www.dedigentoo.org/trac/linux-phc |
10 | +# Patch version: linux-phc-0.2.10-kernel-vanilla-2.6.21.patch |
11 | + |
12 | menu "CPU Frequency scaling" |
13 | |
14 | source "drivers/cpufreq/Kconfig" |
15 | |
16 | if CPU_FREQ |
17 | @@ -95,11 +98,10 @@ |
18 | depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m) |
19 | default y |
20 | |
21 | config X86_GX_SUSPMOD |
22 | tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" |
23 | - depends on PCI |
24 | help |
25 | This add the CPUFreq driver for NatSemi Geode processors which |
26 | support suspend modulation. |
27 | |
28 | For details, take a look at <file:Documentation/cpu-freq/>. |
29 | @@ -107,45 +109,122 @@ |
30 | If in doubt, say N. |
31 | |
32 | config X86_SPEEDSTEP_CENTRINO |
33 | tristate "Intel Enhanced SpeedStep" |
34 | select CPU_FREQ_TABLE |
35 | - select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI) |
36 | + select X86_SPEEDSTEP_CENTRINO_ACPI if (!X86_SPEEDSTEP_CENTRINO_BUILTIN || (!X86_SPEEDSTEP_CENTRINO_BUILTIN_BANIAS && !X86_SPEEDSTEP_CENTRINO_BUILTIN_DOTHAN && !X86_SPEEDSTEP_CENTRINO_BUILTIN_SONOMA )) |
37 | help |
38 | This adds the CPUFreq driver for Enhanced SpeedStep enabled |
39 | mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However, |
40 | - you also need to say Y to "Use ACPI tables to decode..." below |
41 | - [which might imply enabling ACPI] if you want to use this driver |
42 | - on non-Banias CPUs. |
43 | + you also need to say Y below to at least one of the following options: |
44 | + - "Use ACPI tables to decode..." [which might imply enabling ACPI] |
45 | + - "Built-in Tables for ... CPUs" |
46 | + |
47 | + You can also say yes to all of these options. In this configuration the |
48 | + driver will first try to use ACPI. Then if it fails it will try to use |
49 | + a built-in table if there is one matching the CPU. |
50 | + |
51 | + For details, take a look at <file:Documentation/cpu-freq/>. |
52 | + |
53 | + If in doubt, say N. |
54 | + |
55 | +config X86_SPEEDSTEP_CENTRINO_SYSFS |
56 | + bool "Userspace control of CPU frequency/voltage table" |
57 | + depends on X86_SPEEDSTEP_CENTRINO |
58 | + depends on SYSFS |
59 | + depends on (X86_SPEEDSTEP_CENTRINO_BUILTIN && (X86_SPEEDSTEP_CENTRINO_BUILTIN_BANIAS || X86_SPEEDSTEP_CENTRINO_BUILTIN_DOTHAN || X86_SPEEDSTEP_CENTRINO_BUILTIN_SONOMA )) || X86_SPEEDSTEP_CENTRINO_ACPI || X86_SPEEDSTEP_CENTRINO_DEFAULT |
60 | + default y |
61 | + help |
62 | + Add support for user space control of the CPU frequency/voltage |
63 | + operating points table through a sysfs interface. |
64 | + |
65 | + If you say Y here files will be created in |
66 | + /sys/devices/system/cpu/cpu*/cpufreq/op_points_table |
67 | + allowing reading and writing of the current table values as well as |
68 | + adding or removing operating points. |
69 | |
70 | For details, take a look at <file:Documentation/cpu-freq/>. |
71 | |
72 | If in doubt, say N. |
73 | |
74 | config X86_SPEEDSTEP_CENTRINO_ACPI |
75 | - bool "Use ACPI tables to decode valid frequency/voltage (deprecated)" |
76 | + bool "Use ACPI tables to decode valid frequency/voltage pairs (deprecated)" |
77 | depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR |
78 | depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m) |
79 | + default y |
80 | help |
81 | This is deprecated and this functionality is now merged into |
82 | acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of |
83 | speedstep_centrino. |
84 | Use primarily the information provided in the BIOS ACPI tables |
85 | - to determine valid CPU frequency and voltage pairings. It is |
86 | - required for the driver to work on non-Banias CPUs. |
87 | + to determine valid CPU frequency and voltage pairings. |
88 | + It is required for the driver to work on CPUs with no built-in |
89 | + table available |
90 | + |
91 | + (this option adds around 3 kB to the kernel size) |
92 | |
93 | If in doubt, say Y. |
94 | |
95 | -config X86_SPEEDSTEP_CENTRINO_TABLE |
96 | - bool "Built-in tables for Banias CPUs" |
97 | +config X86_SPEEDSTEP_CENTRINO_BUILTIN |
98 | + bool "Built-in tables" |
99 | depends on X86_SPEEDSTEP_CENTRINO |
100 | default y |
101 | help |
102 | - Use built-in tables for Banias CPUs if ACPI encoding |
103 | + Use "hard coded" built-in tables if ACPI decoding |
104 | is not available. |
105 | |
106 | - If in doubt, say N. |
107 | + If you say Y here you must select at least one of the CPU below. |
108 | + |
109 | + If you are not sure of your exact CPU model you can select several CPU |
110 | + models or all of them. The driver will only use the table that match |
111 | + the exact CPU name and family/model/stepping numbers. |
112 | + Selecting all the built-in tables will only add a small size overhead |
113 | + to the kernel and an insignificant extra time to intialize the driver. |
114 | + |
115 | + If both ACPI and built-in tables support are enabled then built-in |
116 | + tables will be used only if ACPI table decoding fails. |
117 | + |
118 | + If you want to force usage of built-in tables over ACPI you need to say |
119 | + Y here and N to X86_SPEEDSTEP_CENTRINO_ACPI. |
120 | + |
121 | + (this option adds from 2.5 to 4.5 kB to the kernel size, depending on |
122 | + the selected built-in tables) |
123 | + |
124 | + If in doubt, say Y. |
125 | + |
126 | +config X86_SPEEDSTEP_CENTRINO_BUILTIN_BANIAS |
127 | + bool "Built-in tables for Banias CPUs" |
128 | + depends on X86_SPEEDSTEP_CENTRINO_BUILTIN |
129 | + default y |
130 | + help |
131 | + Use built-in tables for Banias CPUs if ACPI encoding is not available. |
132 | + Banias CPUs are the first generation of Pentium-M, with a 1 MB L2 cache |
133 | + and 400 MHz FSB manufactured on 0.13 micron process. |
134 | + |
135 | + If in doubt, say Y. |
136 | + |
137 | +config X86_SPEEDSTEP_CENTRINO_BUILTIN_DOTHAN |
138 | + bool "Built-in tables for Dothan CPUs" |
139 | + depends on X86_SPEEDSTEP_CENTRINO_BUILTIN |
140 | + default y |
141 | + help |
142 | + Use built-in tables for Dothan CPUs if ACPI encoding is not available. |
143 | + Dothan CPUs are the second generation of Pentium-M, with a 2 MB L2 |
144 | + cache and 400 MHz FSB manufactured on 90 nm process. |
145 | + |
146 | + If in doubt, say Y. |
147 | + |
148 | +config X86_SPEEDSTEP_CENTRINO_BUILTIN_SONOMA |
149 | + bool "Built-in tables for Sonoma CPUs" |
150 | + depends on X86_SPEEDSTEP_CENTRINO_BUILTIN |
151 | + default y |
152 | + help |
153 | + Use built-in tables for Sonoma CPUs if ACPI encoding is not available. |
154 | + Sonoma CPUs are the third generation of Pentium-M, with a 2 MB L2 cache |
155 | + and 533 MHz FSB manufactured on 90 nm process. |
156 | + |
157 | + If in doubt, say Y. |
158 | |
159 | config X86_SPEEDSTEP_ICH |
160 | tristate "Intel Speedstep on ICH-M chipsets (ioport interface)" |
161 | select CPU_FREQ_TABLE |
162 | help |
163 | diff --new-file -a --unified=5 --recursive --exclude-from=diff.excludes linux.org/arch/i386/kernel/cpu/cpufreq/Makefile linux.phc/arch/i386/kernel/cpu/cpufreq/Makefile |
164 | --- linux.org/arch/i386/kernel/cpu/cpufreq/Makefile 2007-05-12 15:41:54.000000000 +0200 |
165 | +++ linux.phc/arch/i386/kernel/cpu/cpufreq/Makefile 2007-05-12 16:26:41.000000000 +0200 |
166 | @@ -6,11 +6,11 @@ |
167 | obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o |
168 | obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o |
169 | obj-$(CONFIG_X86_LONGRUN) += longrun.o |
170 | obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o |
171 | obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o |
172 | +obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o |
173 | obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o |
174 | obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o |
175 | obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o |
176 | -obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o |
177 | obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o |
178 | obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o |
179 | diff --new-file -a --unified=5 --recursive --exclude-from=diff.excludes linux.org/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c linux.phc/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c |
180 | --- linux.org/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 2007-05-12 15:41:54.000000000 +0200 |
181 | +++ linux.phc/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 2007-05-13 19:08:51.000000000 +0200 |
182 | @@ -11,10 +11,15 @@ |
183 | * Modelled on speedstep.c |
184 | * |
185 | * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org> |
186 | */ |
187 | |
188 | +/* |
189 | + * This file has been patched with Linux PHC: https://www.dedigentoo.org/trac/linux-phc |
190 | + * Patch version: linux-phc-0.2.10-kernel-vanilla-2.6.21.patch |
191 | + */ |
192 | + |
193 | #include <linux/kernel.h> |
194 | #include <linux/module.h> |
195 | #include <linux/init.h> |
196 | #include <linux/cpufreq.h> |
197 | #include <linux/sched.h> /* current */ |
198 | @@ -48,41 +53,45 @@ |
199 | enum { |
200 | CPU_BANIAS, |
201 | CPU_DOTHAN_A1, |
202 | CPU_DOTHAN_A2, |
203 | CPU_DOTHAN_B0, |
204 | + CPU_DOTHAN_C0, |
205 | CPU_MP4HT_D0, |
206 | CPU_MP4HT_E0, |
207 | }; |
208 | |
209 | static const struct cpu_id cpu_ids[] = { |
210 | [CPU_BANIAS] = { 6, 9, 5 }, |
211 | [CPU_DOTHAN_A1] = { 6, 13, 1 }, |
212 | [CPU_DOTHAN_A2] = { 6, 13, 2 }, |
213 | [CPU_DOTHAN_B0] = { 6, 13, 6 }, |
214 | + [CPU_DOTHAN_C0] = { 6, 13, 8 }, |
215 | [CPU_MP4HT_D0] = {15, 3, 4 }, |
216 | [CPU_MP4HT_E0] = {15, 4, 1 }, |
217 | }; |
218 | #define N_IDS ARRAY_SIZE(cpu_ids) |
219 | |
220 | struct cpu_model |
221 | { |
222 | const struct cpu_id *cpu_id; |
223 | const char *model_name; |
224 | unsigned max_freq; /* max clock in kHz */ |
225 | - |
226 | struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ |
227 | + unsigned base_freq; /* base frequency used to convert between clock rates and MSR: FSB/4 in kHz */ |
228 | }; |
229 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x); |
230 | |
231 | /* Operating points for current CPU */ |
232 | static struct cpu_model *centrino_model[NR_CPUS]; |
233 | static const struct cpu_id *centrino_cpu[NR_CPUS]; |
234 | |
235 | static struct cpufreq_driver centrino_driver; |
236 | |
237 | -#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE |
238 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN |
239 | + |
240 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_BANIAS |
241 | |
242 | /* Computes the correct form for IA32_PERF_CTL MSR for a particular |
243 | frequency/voltage operating point; frequency in MHz, volts in mV. |
244 | This is stored as "index" in the structure. */ |
245 | #define OP(mhz, mv) \ |
246 | @@ -126,11 +135,10 @@ |
247 | OP(1000, 1164), |
248 | OP(1100, 1180), |
249 | { .frequency = CPUFREQ_TABLE_END } |
250 | }; |
251 | |
252 | - |
253 | /* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */ |
254 | static struct cpufreq_frequency_table banias_1200[] = |
255 | { |
256 | OP( 600, 956), |
257 | OP( 800, 1004), |
258 | @@ -203,38 +211,301 @@ |
259 | #define _BANIAS(cpuid, max, name) \ |
260 | { .cpu_id = cpuid, \ |
261 | .model_name = "Intel(R) Pentium(R) M processor " name "MHz", \ |
262 | .max_freq = (max)*1000, \ |
263 | .op_points = banias_##max, \ |
264 | + .base_freq = 100000, \ |
265 | } |
266 | #define BANIAS(max) _BANIAS(&cpu_ids[CPU_BANIAS], max, #max) |
267 | |
268 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_BANIAS */ |
269 | + |
270 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_DOTHAN |
271 | +/* Dothan processor datasheet 30218903.pdf defines 4 voltages for each |
272 | + frequency (VID#A through VID#D) - this macro allows us to define all |
273 | + of these but we only use the VID#A voltages at compile time - this may |
274 | + need some work if we want to select the voltage profile at runtime. */ |
275 | + |
276 | +#define OP(mhz, mva, mvb, mvc, mvd) \ |
277 | + { \ |
278 | + .frequency = (mhz) * 1000, \ |
279 | + .index = (((mhz)/100) << 8) | ((mva - 700) / 16) \ |
280 | + } |
281 | + |
282 | +/* Intel Pentium M processor 733 / 1.10GHz (Dothan) */ |
283 | +static struct cpufreq_frequency_table dothan_1100[] = |
284 | +{ |
285 | + OP( 600, 700, 700, 700, 700), |
286 | + OP( 800, 748, 748, 748, 748), |
287 | + OP( 900, 764, 764, 764, 764), |
288 | + OP(1000, 812, 812, 812, 812), |
289 | + OP(1100, 844, 844, 844, 844), |
290 | + { .frequency = CPUFREQ_TABLE_END } |
291 | +}; |
292 | + |
293 | +/* Intel Pentium M processor 710 / 1.40GHz (Dothan) */ |
294 | +static struct cpufreq_frequency_table dothan_1400[] = |
295 | +{ |
296 | + |
297 | + OP( 600, 988, 988, 988, 988), |
298 | + OP( 800, 1068, 1068, 1068, 1052), |
299 | + OP(1000, 1148, 1148, 1132, 1116), |
300 | + OP(1200, 1228, 1212, 1212, 1180), |
301 | + OP(1400, 1340, 1324, 1308, 1276), |
302 | + { .frequency = CPUFREQ_TABLE_END } |
303 | +}; |
304 | + |
305 | +/* Intel Pentium M processor 715 / 1.50GHz (Dothan) */ |
306 | +static struct cpufreq_frequency_table dothan_1500[] = |
307 | +{ |
308 | + OP( 600, 988, 988, 988, 988), |
309 | + OP( 800, 1068, 1068, 1068, 1052), |
310 | + OP(1000, 1148, 1148, 1132, 1116), |
311 | + OP(1200, 1228, 1212, 1212, 1180), |
312 | + OP(1500, 1340, 1324, 1308, 1276), |
313 | + { .frequency = CPUFREQ_TABLE_END } |
314 | +}; |
315 | + |
316 | +/* Intel Pentium M processor 725 / 1.60GHz (Dothan) */ |
317 | +static struct cpufreq_frequency_table dothan_1600[] = |
318 | +{ |
319 | + OP( 600, 988, 988, 988, 988), |
320 | + OP( 800, 1068, 1068, 1052, 1052), |
321 | + OP(1000, 1132, 1132, 1116, 1116), |
322 | + OP(1200, 1212, 1196, 1180, 1164), |
323 | + OP(1400, 1276, 1260, 1244, 1228), |
324 | + OP(1600, 1340, 1324, 1308, 1276), |
325 | + { .frequency = CPUFREQ_TABLE_END } |
326 | +}; |
327 | + |
328 | +/* Intel Pentium M processor 735 / 1.70GHz (Dothan) */ |
329 | +static struct cpufreq_frequency_table dothan_1700[] = |
330 | +{ |
331 | + OP( 600, 988, 988, 988, 988), |
332 | + OP( 800, 1052, 1052, 1052, 1052), |
333 | + OP(1000, 1116, 1116, 1116, 1100), |
334 | + OP(1200, 1180, 1180, 1164, 1148), |
335 | + OP(1400, 1244, 1244, 1228, 1212), |
336 | + OP(1700, 1340, 1324, 1308, 1276), |
337 | + { .frequency = CPUFREQ_TABLE_END } |
338 | +}; |
339 | + |
340 | +/* Intel Pentium M processor 745 / 1.80GHz (Dothan) */ |
341 | +static struct cpufreq_frequency_table dothan_1800[] = |
342 | +{ |
343 | + OP( 600, 988, 988, 988, 988), |
344 | + OP( 800, 1052, 1052, 1052, 1036), |
345 | + OP(1000, 1116, 1100, 1100, 1084), |
346 | + OP(1200, 1164, 1164, 1148, 1132), |
347 | + OP(1400, 1228, 1212, 1212, 1180), |
348 | + OP(1600, 1292, 1276, 1260, 1228), |
349 | + OP(1800, 1340, 1324, 1308, 1276), |
350 | + { .frequency = CPUFREQ_TABLE_END } |
351 | +}; |
352 | + |
353 | +/* Intel Pentium M processor 755 / 2.00GHz (Dothan) */ |
354 | +static struct cpufreq_frequency_table dothan_2000[] = |
355 | +{ |
356 | + OP( 600, 988, 988, 988, 988), |
357 | + OP( 800, 1052, 1036, 1036, 1036), |
358 | + OP(1000, 1100, 1084, 1084, 1084), |
359 | + OP(1200, 1148, 1132, 1132, 1116), |
360 | + OP(1400, 1196, 1180, 1180, 1164), |
361 | + OP(1600, 1244, 1228, 1228, 1196), |
362 | + OP(1800, 1292, 1276, 1276, 1244), |
363 | + OP(2000, 1340, 1324, 1308, 1276), |
364 | + { .frequency = CPUFREQ_TABLE_END } |
365 | +}; |
366 | + |
367 | +#undef OP |
368 | + |
369 | +#define DOTHAN(cpuid, max, name) \ |
370 | +{ .cpu_id = cpuid, \ |
371 | + .model_name = "Intel(R) Pentium(R) M processor " name "GHz", \ |
372 | + .max_freq = (max)*1000, \ |
373 | + .op_points = dothan_##max, \ |
374 | + .base_freq = 100000, \ |
375 | +} |
376 | + |
377 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_DOTHAN */ |
378 | + |
379 | + |
380 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_SONOMA |
381 | + |
382 | +/* Intel datasheets 30526202.pdf define voltages only for highest and |
383 | + lowest frequency modes (HFM and LFM). |
384 | + For LFM the datasheet gives one typical voltage: LFMVccTyp. |
385 | + For HFM the datasheet gives a min and a max voltage: HFMVccMin and HFMVccMax. |
386 | + The tables below are using HFMVccMax for the highest frequency to be on |
387 | + the safe side. The voltages of the intermediate frequencies are linearly |
388 | + interpolated from LFMVccTyp and HFMVccMax as it is what I have observed |
389 | + to be used by the ACPI tables of my laptop and of some other's one. |
390 | + |
391 | + LFMVccTyp is 988 mv for all models |
392 | + HFMVccMin is 1260 mv for all models |
393 | + HFMVccMax is 1356 mv for models 730, 740, 750 and 760. |
394 | + HFMVccMax is 1372 mv for model 770. |
395 | + HFMVccMax is 1404 mv for model 780. |
396 | + |
397 | + As only the first voltage of each row of the tables are used I have put |
398 | + there the values interpolated from HFMVccMax rounded to the next higher 16 mV step |
399 | + For reference I have put in the other 3 columns: |
400 | + values interpolated from HFMVccMax rounded to the nearest 1 mv |
401 | + values interpolated from HFMVccMin rounded to the next higher 16 mv step |
402 | + values interpolated from HFMVccMin rounded to the nearest 1 mv |
403 | +*/ |
404 | + |
405 | +#define OPEX(mhz, base, mva, mvb, mvc, mvd) \ |
406 | +{ \ |
407 | + .frequency = (mhz) * 1000, \ |
408 | + .index = (((mhz)/(base)) << 8) | ((mva - 700) / 16) \ |
409 | +} |
410 | + |
411 | +/* Intel Pentium M processor 730 / 1.60 GHz (Sonoma) */ |
412 | +static struct cpufreq_frequency_table sonoma_1596[] = |
413 | +{ |
414 | + OPEX( 798, 133, 988, 988, 988, 988), |
415 | + OPEX(1064, 133, 1116, 1111, 1084, 1079), |
416 | + OPEX(1330, 133, 1244, 1233, 1180, 1169), |
417 | + OPEX(1596, 133, 1356, 1356, 1260, 1260), |
418 | + { .frequency = CPUFREQ_TABLE_END } |
419 | +}; |
420 | + |
421 | +/* Intel Pentium M processor 740 / 1.73 GHz (Sonoma) */ |
422 | +static struct cpufreq_frequency_table sonoma_1729[] = |
423 | +{ |
424 | + OPEX( 798, 133, 988, 988, 988, 988), |
425 | + OPEX(1064, 133, 1100, 1093, 1068, 1066), |
426 | + OPEX(1330, 133, 1212, 1198, 1148, 1143), |
427 | + OPEX(1729, 133, 1356, 1356, 1260, 1260), |
428 | + { .frequency = CPUFREQ_TABLE_END } |
429 | +}; |
430 | + |
431 | +/* Intel Pentium M processor 750 / 1.86 GHz (Sonoma) */ |
432 | +static struct cpufreq_frequency_table sonoma_1862[] = |
433 | +{ |
434 | + OPEX( 798, 133, 988, 988, 988, 988), |
435 | + OPEX(1064, 133, 1084, 1080, 1068, 1056), |
436 | + OPEX(1330, 133, 1180, 1172, 1132, 1124), |
437 | + OPEX(1596, 133, 1276, 1264, 1196, 1192), |
438 | + OPEX(1862, 133, 1356, 1356, 1260, 1260), |
439 | + { .frequency = CPUFREQ_TABLE_END } |
440 | +}; |
441 | + |
442 | +/* Intel Pentium M processor 760 / 2.00 GHz (Sonoma) */ |
443 | +static struct cpufreq_frequency_table sonoma_1995[] = |
444 | +{ |
445 | + OPEX( 798, 133, 988, 988, 988, 988), |
446 | + OPEX(1064, 133, 1084, 1070, 1052, 1048), |
447 | + OPEX(1330, 133, 1164, 1152, 1116, 1109), |
448 | + OPEX(1596, 133, 1244, 1233, 1180, 1169), |
449 | + OPEX(1995, 133, 1356, 1356, 1260, 1260), |
450 | + { .frequency = CPUFREQ_TABLE_END } |
451 | +}; |
452 | + |
453 | +/* Intel Pentium M processor 770 / 2.13 GHz (Sonoma) */ |
454 | +static struct cpufreq_frequency_table sonoma_2128[] = |
455 | +{ |
456 | + OPEX( 798, 133, 988, 988, 988, 988), |
457 | + OPEX(1064, 133, 1068, 1065, 1052, 1042), |
458 | + OPEX(1330, 133, 1148, 1142, 1100, 1097), |
459 | + OPEX(1596, 133, 1228, 1218, 1164, 1151), |
460 | + OPEX(1862, 133, 1308, 1295, 1212, 1206), |
461 | + OPEX(2128, 133, 1372, 1372, 1260, 1260), |
462 | + { .frequency = CPUFREQ_TABLE_END } |
463 | +}; |
464 | + |
465 | +/* Intel Pentium M processor 780 / 2.26 GHz (Sonoma) */ |
466 | +static struct cpufreq_frequency_table sonoma_2261[] = |
467 | +{ |
468 | + OPEX( 798, 133, 988, 988, 988, 988), |
469 | + OPEX(1064, 133, 1068, 1064, 1052, 1037), |
470 | + OPEX(1330, 133, 1148, 1139, 1100, 1087), |
471 | + OPEX(1596, 133, 1228, 1215, 1148, 1136), |
472 | + OPEX(1862, 133, 1292, 1291, 1196, 1186), |
473 | + OPEX(2261, 133, 1404, 1404, 1260, 1260), |
474 | + { .frequency = CPUFREQ_TABLE_END } |
475 | +}; |
476 | + |
477 | +#undef OPEX |
478 | + |
479 | +#define SONOMA(cpuid, max, base, name) \ |
480 | +{ .cpu_id = cpuid, \ |
481 | + .model_name = "Intel(R) Pentium(R) M processor " name "GHz", \ |
482 | + .max_freq = (max)*1000, \ |
483 | + .op_points = sonoma_##max, \ |
484 | + .base_freq = (base)*1000, \ |
485 | +} |
486 | + |
487 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_SONOMA */ |
488 | + |
489 | + |
490 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_YONAH |
491 | +// To Do |
492 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_YONAH */ |
493 | + |
494 | + |
495 | /* CPU models, their operating frequency range, and freq/voltage |
496 | operating points */ |
497 | static struct cpu_model models[] = |
498 | { |
499 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_BANIAS |
500 | + /* Builtin tables for Banias CPUs */ |
501 | _BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"), |
502 | BANIAS(1000), |
503 | BANIAS(1100), |
504 | BANIAS(1200), |
505 | BANIAS(1300), |
506 | BANIAS(1400), |
507 | BANIAS(1500), |
508 | BANIAS(1600), |
509 | BANIAS(1700), |
510 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_BANIAS */ |
511 | |
512 | - /* NULL model_name is a wildcard */ |
513 | - { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL }, |
514 | - { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL }, |
515 | - { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL }, |
516 | - { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL }, |
517 | - { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL }, |
518 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_DOTHAN |
519 | + /* Builtin tables for Dothan B0 CPUs */ |
520 | + DOTHAN(&cpu_ids[CPU_DOTHAN_B0], 1100, "1.10"), |
521 | + DOTHAN(&cpu_ids[CPU_DOTHAN_B0], 1400, "1.40"), |
522 | + DOTHAN(&cpu_ids[CPU_DOTHAN_B0], 1500, "1.50"), |
523 | + DOTHAN(&cpu_ids[CPU_DOTHAN_B0], 1600, "1.60"), |
524 | + DOTHAN(&cpu_ids[CPU_DOTHAN_B0], 1700, "1.70"), |
525 | + DOTHAN(&cpu_ids[CPU_DOTHAN_B0], 1800, "1.80"), |
526 | + DOTHAN(&cpu_ids[CPU_DOTHAN_B0], 2000, "2.00"), |
527 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_DOTHAN */ |
528 | + |
529 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_SONOMA |
530 | + /* Builtin tables for Dothan C0 CPUs, a.k.a Sonoma */ |
531 | + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1596, 133, "1.60"), |
532 | + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1729, 133, "1.73"), |
533 | + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1862, 133, "1.86"), |
534 | + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1995, 133, "2.00"), |
535 | + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 2128, 133, "2.13"), |
536 | + SONOMA(&cpu_ids[CPU_DOTHAN_C0], 2261, 133, "2.26"), |
537 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_SONOMA */ |
538 | + |
539 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_YONAH |
540 | + /* Builtin tables for Yonah CPUs */ |
541 | + // To Do |
542 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN_YONAH */ |
543 | + |
544 | + /* NULL model_name is a wildcard to catch known CPU IDs for which |
545 | + * we don't have any builtin table */ |
546 | + { &cpu_ids[CPU_BANIAS], NULL, 0, NULL, 0 }, |
547 | + { &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL, 0 }, |
548 | + { &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL, 0 }, |
549 | + { &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL, 0 }, |
550 | + { &cpu_ids[CPU_DOTHAN_C0], NULL, 0, NULL, 0 }, |
551 | + { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL, 0 }, |
552 | + { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL, 0 }, |
553 | |
554 | + /* End of the table */ |
555 | { NULL, } |
556 | }; |
557 | #undef _BANIAS |
558 | #undef BANIAS |
559 | +#undef DOTHAN |
560 | +#undef SONOMA |
561 | |
562 | static int centrino_cpu_init_table(struct cpufreq_policy *policy) |
563 | { |
564 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; |
565 | struct cpu_model *model; |
566 | @@ -271,11 +542,11 @@ |
567 | return 0; |
568 | } |
569 | |
570 | #else |
571 | static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; } |
572 | -#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ |
573 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_BUILTIN */ |
574 | |
575 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x) |
576 | { |
577 | if ((c->x86 == x->x86) && |
578 | (c->x86_model == x->x86_model) && |
579 | @@ -292,10 +563,17 @@ |
580 | /* |
581 | * Extract clock in kHz from PERF_CTL value |
582 | * for centrino, as some DSDTs are buggy. |
583 | * Ideally, this can be done using the acpi_data structure. |
584 | */ |
585 | + |
586 | + if ((centrino_model[cpu]) && (centrino_model[cpu]->base_freq != 0)) |
587 | + { |
588 | + msr = (msr >> 8) & 0xff; |
589 | + return msr * centrino_model[cpu]->base_freq; |
590 | + } |
591 | + |
592 | if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) || |
593 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) || |
594 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) { |
595 | msr = (msr >> 8) & 0xff; |
596 | return msr * 100000; |
597 | @@ -508,10 +786,11 @@ |
598 | i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index); |
599 | } |
600 | centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END; |
601 | |
602 | cur_freq = get_cur_freq(cpu); |
603 | + centrino_model[cpu]->base_freq = 0; |
604 | |
605 | for (i=0; i<p->state_count; i++) { |
606 | if (!p->states[i].core_frequency) { |
607 | dprintk("skipping state %u\n", i); |
608 | centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID; |
609 | @@ -519,12 +798,12 @@ |
610 | } |
611 | |
612 | if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) != |
613 | (centrino_model[cpu]->op_points[i].frequency)) { |
614 | dprintk("Invalid encoded frequency (%u vs. %u)\n", |
615 | - extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0), |
616 | - centrino_model[cpu]->op_points[i].frequency); |
617 | + extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0), |
618 | + centrino_model[cpu]->op_points[i].frequency); |
619 | result = -EINVAL; |
620 | goto err_kfree_all; |
621 | } |
622 | |
623 | if (cur_freq == centrino_model[cpu]->op_points[i].frequency) |
624 | @@ -551,10 +830,463 @@ |
625 | #else |
626 | static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; } |
627 | static inline int centrino_cpu_early_init_acpi(void) { return 0; } |
628 | #endif |
629 | |
630 | +static int centrino_target (struct cpufreq_policy *policy, |
631 | + unsigned int target_freq, |
632 | + unsigned int relation); |
633 | + |
634 | + |
635 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_SYSFS |
636 | +/************************** sysfs interface for user defined voltage table ************************/ |
637 | + |
638 | +static struct cpufreq_frequency_table **original_table = NULL; |
639 | + |
640 | +static void check_origial_table (unsigned int cpu) |
641 | +{ |
642 | + int i; |
643 | + |
644 | + if (!original_table) |
645 | + { |
646 | + original_table = kmalloc(sizeof(struct cpufreq_frequency_table *)*NR_CPUS, GFP_KERNEL); |
647 | + for (i=0; i < NR_CPUS; i++) |
648 | + { |
649 | + original_table[i] = NULL; |
650 | + } |
651 | + } |
652 | + |
653 | + if (!original_table[cpu]) |
654 | + { |
655 | + /* Count number of frequencies and allocate memory for a copy */ |
656 | + for (i=0; centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++); |
657 | + /* Allocate memory to store the copy */ |
658 | + original_table[cpu] = (struct cpufreq_frequency_table*) kmalloc(sizeof(struct cpufreq_frequency_table)*(i+1), GFP_KERNEL); |
659 | + /* Make copy of frequency/voltage pairs */ |
660 | + for (i=0; centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) |
661 | + { |
662 | + original_table[cpu][i].frequency = centrino_model[cpu]->op_points[i].frequency; |
663 | + original_table[cpu][i].index = centrino_model[cpu]->op_points[i].index; |
664 | + } |
665 | + original_table[cpu][i].frequency = CPUFREQ_TABLE_END; |
666 | + } |
667 | +} |
668 | + |
669 | + |
670 | +static ssize_t show_user_voltage (struct cpufreq_policy *policy, char *buf) |
671 | +{ |
672 | + ssize_t bytes_written = 0; |
673 | + unsigned int cpu = policy->cpu; |
674 | + unsigned int op_index = 0; |
675 | + unsigned int op_count = 0; |
676 | + unsigned int voltage = 0; |
677 | + unsigned int frequency = 0; |
678 | + |
679 | + //dprintk("showing user voltage table in sysfs\n"); |
680 | + |
681 | + while ( (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END) |
682 | + && (bytes_written<PAGE_SIZE-16) ) |
683 | + { |
684 | + //dprintk("getting state %i \n", op_index); |
685 | + frequency = centrino_model[cpu]->op_points[op_index].frequency; |
686 | + if (frequency != CPUFREQ_ENTRY_INVALID) |
687 | + { |
688 | + op_count++; |
689 | + if (op_count>1) |
690 | + bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE-bytes_written-1, ","); |
691 | + voltage = centrino_model[cpu]->op_points[op_index].index; |
692 | + voltage = 700 + ((voltage & 0xFF) << 4); |
693 | + //dprintk("writing voltage %i: %u mV \n", op_index, voltage); |
694 | + bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE-bytes_written-1, "%u",voltage); |
695 | + } |
696 | + else |
697 | + { |
698 | + // This operating point of the table is invalid, ignoring it. |
699 | + dprintk("Ignoring invalid operating point %i \n", op_index); |
700 | + } |
701 | + op_index++; |
702 | + } |
703 | + bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE-bytes_written-1, "\n"); |
704 | + buf[PAGE_SIZE-1] = 0; |
705 | + return bytes_written; |
706 | +} |
707 | + |
708 | +static ssize_t |
709 | +store_user_voltage (struct cpufreq_policy *policy, const char *buf, size_t count) |
710 | +{ |
711 | + unsigned int cpu; |
712 | + const char *curr_buf; |
713 | + unsigned int curr_freq; |
714 | + unsigned int op_index; |
715 | + int isok; |
716 | + char *next_buf; |
717 | + unsigned int op_point; |
718 | + ssize_t retval; |
719 | + unsigned int voltage; |
720 | + |
721 | + if (!policy) |
722 | + return -ENODEV; |
723 | + cpu = policy->cpu; |
724 | + if (!centrino_model[cpu] || !centrino_model[cpu]->op_points) |
725 | + return -ENODEV; |
726 | + |
727 | + check_origial_table(cpu); |
728 | + |
729 | + op_index = 0; |
730 | + curr_buf = buf; |
731 | + next_buf = NULL; |
732 | + isok = 1; |
733 | + |
734 | + while ((centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END) |
735 | + && (isok)) |
736 | + { |
737 | + if (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_ENTRY_INVALID) |
738 | + { |
739 | + voltage = simple_strtoul(curr_buf, &next_buf, 10); |
740 | + if ((next_buf != curr_buf) && (next_buf != NULL)) |
741 | + { |
742 | + if ((voltage >= 700) && (voltage<=1600)) |
743 | + { |
744 | + voltage = ((voltage - 700) >> 4) & 0xFF; |
745 | + op_point = (original_table[cpu])[op_index].index; |
746 | + if (voltage <= (op_point & 0xFF)) |
747 | + { |
748 | + //dprintk("setting control value %i to %04x\n", op_index, op_point); |
749 | + op_point = (op_point & 0xFFFFFF00) | voltage; |
750 | + centrino_model[cpu]->op_points[op_index].index = op_point; |
751 | + } |
752 | + else |
753 | + { |
754 | + op_point = (op_point & 0xFFFFFF00) | voltage; |
755 | + dprintk("not setting control value %i to %04x because requested voltage is not lower than the default value\n", op_index, op_point); |
756 | + //isok = 0; |
757 | + } |
758 | + } |
759 | + else |
760 | + { |
761 | + dprintk("voltage value %i is out of bounds: %u mV\n", op_index, voltage); |
762 | + isok = 0; |
763 | + } |
764 | + curr_buf = next_buf; |
765 | + if (*curr_buf==',') |
766 | + curr_buf++; |
767 | + next_buf = NULL; |
768 | + } |
769 | + else |
770 | + { |
771 | + dprintk("failed to parse voltage value %i\n", op_index); |
772 | + isok = 0; |
773 | + } |
774 | + } |
775 | + else |
776 | + { |
777 | + // This operating point of the table is invalid, ignoring it. |
778 | + dprintk("Ignoring invalid operating point %i \n", op_index); |
779 | + } |
780 | + op_index++; |
781 | + } |
782 | + |
783 | + if (isok) |
784 | + { |
785 | + retval = count; |
786 | + curr_freq = policy->cur; |
787 | + centrino_target(policy, curr_freq, CPUFREQ_RELATION_L); |
788 | + } |
789 | + else |
790 | + { |
791 | + retval = -EINVAL; |
792 | + } |
793 | + |
794 | + return retval; |
795 | +} |
796 | + |
797 | +static struct freq_attr centrino_freq_attr_voltage_table = |
798 | +{ |
799 | + .attr = { .name = "voltage_table", .mode = 0644, .owner = THIS_MODULE }, |
800 | + .show = show_user_voltage, |
801 | + .store = store_user_voltage, |
802 | +}; |
803 | + |
804 | + |
805 | +static ssize_t show_user_op_points (struct cpufreq_policy *policy, char *buf) |
806 | +{ |
807 | + ssize_t bytes_written = 0; |
808 | + unsigned int cpu = policy->cpu; |
809 | + unsigned int op_index = 0; |
810 | + unsigned int op_count = 0; |
811 | + unsigned int voltage = 0; |
812 | + unsigned int frequency = 0; |
813 | + |
814 | + //dprintk("showing user voltage table in sysfs\n"); |
815 | + |
816 | + while ( (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END) |
817 | + && (bytes_written<PAGE_SIZE-16) ) |
818 | + { |
819 | + //dprintk("getting state %i \n", i); |
820 | + frequency = centrino_model[cpu]->op_points[op_index].frequency; |
821 | + if (frequency != CPUFREQ_ENTRY_INVALID) |
822 | + { |
823 | + op_count++; |
824 | + if (op_count>1) |
825 | + bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE-bytes_written-1, ","); |
826 | + voltage = centrino_model[cpu]->op_points[op_index].index; |
827 | + voltage = 700 + ((voltage & 0xFF) << 4); |
828 | + //dprintk("writing voltage %i: %u mV \n", i, voltage); |
829 | + bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE-bytes_written-2, "%u:%u",frequency,voltage); |
830 | + } |
831 | + else |
832 | + { |
833 | + // This operating point of the table is invalid, ignoring it. |
834 | + dprintk("Ignoring invalid operating point %i \n", op_index); |
835 | + } |
836 | + op_index++; |
837 | + } |
838 | + bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE-bytes_written-1, "\n"); |
839 | + buf[PAGE_SIZE-1] = 0; |
840 | + return bytes_written; |
841 | +} |
842 | + |
843 | +static ssize_t |
844 | +store_user_op_points (struct cpufreq_policy *policy, const char *buf, size_t count) |
845 | +{ |
846 | + unsigned int cpu; |
847 | + const char *curr_buf; |
848 | + unsigned int curr_freq; |
849 | + unsigned int op_index; |
850 | + unsigned int op_count; |
851 | + int isok; |
852 | + char *next_buf; |
853 | + unsigned int op_point; |
854 | + ssize_t retval; |
855 | + unsigned int voltage; |
856 | + unsigned int frequency; |
857 | + int found; |
858 | + |
859 | + if (!policy) |
860 | + return -ENODEV; |
861 | + cpu = policy->cpu; |
862 | + if (!centrino_model[cpu] || !centrino_model[cpu]->op_points) |
863 | + return -ENODEV; |
864 | + |
865 | + check_origial_table(cpu); |
866 | + |
867 | + op_count = 0; |
868 | + curr_buf = buf; |
869 | + next_buf = NULL; |
870 | + isok = 1; |
871 | + |
872 | + while ( (isok) && (curr_buf != NULL) ) |
873 | + { |
874 | + op_count++; |
875 | + // Parse frequency |
876 | + frequency = simple_strtoul(curr_buf, &next_buf, 10); |
877 | + if ((next_buf != curr_buf) && (next_buf != NULL)) |
878 | + { |
879 | + // Parse separator between frequency and voltage |
880 | + curr_buf = next_buf; |
881 | + next_buf = NULL; |
882 | + if (*curr_buf==':') |
883 | + { |
884 | + curr_buf++; |
885 | + // Parse voltage |
886 | + voltage = simple_strtoul(curr_buf, &next_buf, 10); |
887 | + if ((next_buf != curr_buf) && (next_buf != NULL)) |
888 | + { |
889 | + if ((voltage >= 700) && (voltage<=1600)) |
890 | + { |
891 | + voltage = ((voltage - 700) >> 4) & 0xFF; |
892 | + op_index = 0; |
893 | + found = 0; |
894 | + while (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END) |
895 | + { |
896 | + if ((centrino_model[cpu]->op_points[op_index].frequency == frequency) |
897 | + && (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_ENTRY_INVALID)) |
898 | + { |
899 | + found = 1; |
900 | + op_point = (original_table[cpu])[op_index].index; |
901 | + if (voltage <= (op_point & 0xFF)) |
902 | + { |
903 | + //dprintk("setting control value %i to %04x\n", op_index, op_point); |
904 | + op_point = (op_point & 0xFFFFFF00) | voltage; |
905 | + centrino_model[cpu]->op_points[op_index].index = op_point; |
906 | + } |
907 | + else |
908 | + { |
909 | + op_point = (op_point & 0xFFFFFF00) | voltage; |
910 | + dprintk("not setting control value %i to %04x because requested voltage is not lower than the default value (%u MHz)\n", op_index, op_point, frequency); |
911 | + } |
912 | + } |
913 | + op_index++; |
914 | + } |
915 | + if (found == 0) |
916 | + { |
917 | + dprintk("operating point # %u not found: %u MHz\n", op_count, frequency); |
918 | + isok = 0; |
919 | + } |
920 | + } |
921 | + else |
922 | + { |
923 | + dprintk("operating point # %u voltage value is out of bounds: %u mV\n", op_count, voltage); |
924 | + isok = 0; |
925 | + } |
926 | + // Parse seprator before next operating point, if any |
927 | + curr_buf = next_buf; |
928 | + next_buf = NULL; |
929 | + if (*curr_buf==',') |
930 | + curr_buf++; |
931 | + else |
932 | + curr_buf = NULL; |
933 | + } |
934 | + else |
935 | + { |
936 | + dprintk("failed to parse operating point # %u voltage\n", op_count); |
937 | + isok = 0; |
938 | + } |
939 | + } |
940 | + else |
941 | + { |
942 | + dprintk("failed to parse operating point # %u\n", op_count); |
943 | + isok = 0; |
944 | + } |
945 | + } |
946 | + else |
947 | + { |
948 | + dprintk("failed to parse operating point # %u frequency\n", op_count); |
949 | + isok = 0; |
950 | + } |
951 | + } |
952 | + |
953 | + if (isok) |
954 | + { |
955 | + retval = count; |
956 | + curr_freq = policy->cur; |
957 | + centrino_target(policy, curr_freq, CPUFREQ_RELATION_L); |
958 | + } |
959 | + else |
960 | + { |
961 | + retval = -EINVAL; |
962 | + } |
963 | + |
964 | + return retval; |
965 | +} |
966 | + |
967 | +static struct freq_attr centrino_freq_attr_op_points_table = |
968 | +{ |
969 | + .attr = { .name = "op_points_table", .mode = 0644, .owner = THIS_MODULE }, |
970 | + .show = show_user_op_points, |
971 | + .store = store_user_op_points, |
972 | +}; |
973 | + |
974 | +unsigned long rounded_div(unsigned long x, unsigned long y) |
975 | +{ |
976 | + return (((x*2) / y)+1)/2; |
977 | +} |
978 | + |
979 | +static ssize_t show_FSB_base_freq (struct cpufreq_policy *policy, char *buf) |
980 | +{ |
981 | + ssize_t bytes_written = 0; |
982 | + unsigned int cpu = policy->cpu; |
983 | + unsigned int frequency; |
984 | + unsigned int index; |
985 | + unsigned int op_index = 0; |
986 | + |
987 | + frequency = centrino_model[cpu]->base_freq; |
988 | + if (frequency!=0) |
989 | + { |
990 | + bytes_written += snprintf (buf, PAGE_SIZE-2, "User defined base FSB frequency:\n%u kHz\n",frequency); |
991 | + } |
992 | + |
993 | + bytes_written += snprintf (buf+bytes_written, PAGE_SIZE-bytes_written-2, |
994 | + "Base FSB frequency computed from operating points table:\n"); |
995 | + |
996 | + check_origial_table(cpu); |
997 | + while ((original_table[cpu][op_index].frequency != CPUFREQ_TABLE_END) |
998 | + && (bytes_written < PAGE_SIZE-3)) |
999 | + { |
1000 | + index = original_table[cpu][op_index].index; |
1001 | + index = (index >> 8) & 0xFF; |
1002 | + if (index > 0) |
1003 | + { |
1004 | + frequency = rounded_div((original_table[cpu][op_index].frequency), index); |
1005 | + bytes_written += snprintf (buf+bytes_written, PAGE_SIZE-bytes_written-2, "%u kHz (%u / %u)\n", |
1006 | + frequency, original_table[cpu][op_index].frequency, index); |
1007 | + } |
1008 | + op_index++; |
1009 | + } |
1010 | + |
1011 | + buf[PAGE_SIZE-1] = 0; |
1012 | + return bytes_written; |
1013 | +} |
1014 | + |
1015 | +static ssize_t |
1016 | +store_FSB_base_freq (struct cpufreq_policy *policy, const char *buf, size_t count) |
1017 | +{ |
1018 | + unsigned int cpu; |
1019 | + const char *curr_buf; |
1020 | + unsigned int curr_freq; |
1021 | + unsigned int frequency; |
1022 | + unsigned int index; |
1023 | + char *next_buf; |
1024 | + unsigned int op_index = 0; |
1025 | + ssize_t retval; |
1026 | + |
1027 | + if (!policy) |
1028 | + return -ENODEV; |
1029 | + cpu = policy->cpu; |
1030 | + if (!centrino_model[cpu] || !centrino_model[cpu]->op_points) |
1031 | + return -ENODEV; |
1032 | + |
1033 | + curr_buf = buf; |
1034 | + next_buf = NULL; |
1035 | + frequency = simple_strtoul(curr_buf, &next_buf, 10); |
1036 | + if ((next_buf != curr_buf) && (next_buf != NULL)) |
1037 | + { |
1038 | + if (centrino_model[cpu]->base_freq != frequency) |
1039 | + { |
1040 | + centrino_model[cpu]->base_freq = frequency; |
1041 | + |
1042 | + check_origial_table(cpu); |
1043 | + while (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END) |
1044 | + { |
1045 | + if (frequency>0) |
1046 | + { |
1047 | + index = original_table[cpu][op_index].index; |
1048 | + index = (index >> 8) & 0xFF; |
1049 | + if (index > 0) |
1050 | + { |
1051 | + centrino_model[cpu]->op_points[op_index].frequency = frequency * index; |
1052 | + } |
1053 | + } |
1054 | + else |
1055 | + { |
1056 | + centrino_model[cpu]->op_points[op_index].frequency = original_table[cpu][op_index].frequency; |
1057 | + } |
1058 | + op_index++; |
1059 | + } |
1060 | + } |
1061 | + |
1062 | + retval = count; |
1063 | + curr_freq = policy->cur; |
1064 | + centrino_target(policy, curr_freq, CPUFREQ_RELATION_L); |
1065 | + } |
1066 | + else |
1067 | + { |
1068 | + retval = -EINVAL; |
1069 | + } |
1070 | + |
1071 | + return retval; |
1072 | +} |
1073 | + |
1074 | +static struct freq_attr centrino_freq_attr_FSB_Base_Freq = |
1075 | +{ |
1076 | + .attr = { .name = "FSB_base_frequency", .mode = 0644, .owner = THIS_MODULE }, |
1077 | + .show = show_FSB_base_freq, |
1078 | + .store = store_FSB_base_freq, |
1079 | +}; |
1080 | + |
1081 | +#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_SYSFS */ |
1082 | + |
1083 | static int centrino_cpu_init(struct cpufreq_policy *policy) |
1084 | { |
1085 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; |
1086 | unsigned freq; |
1087 | unsigned l, h; |
1088 | @@ -802,10 +1534,15 @@ |
1089 | return 0; |
1090 | } |
1091 | |
1092 | static struct freq_attr* centrino_attr[] = { |
1093 | &cpufreq_freq_attr_scaling_available_freqs, |
1094 | +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_SYSFS |
1095 | + ¢rino_freq_attr_voltage_table, |
1096 | + ¢rino_freq_attr_op_points_table, |
1097 | + ¢rino_freq_attr_FSB_Base_Freq, |
1098 | +#endif |
1099 | NULL, |
1100 | }; |
1101 | |
1102 | static struct cpufreq_driver centrino_driver = { |
1103 | .name = "centrino", /* should be speedstep-centrino, |
1104 | @@ -866,5 +1603,6 @@ |
1105 | MODULE_DESCRIPTION ("Enhanced SpeedStep driver for Intel Pentium M processors."); |
1106 | MODULE_LICENSE ("GPL"); |
1107 | |
1108 | late_initcall(centrino_init); |
1109 | module_exit(centrino_exit); |
1110 | + |