Annotation 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 -
(hide 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 | niro | 319 | 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 | + |