aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/e_powersaver.c
diff options
context:
space:
mode:
authorRafał Bilski <rafalbilski@interia.pl>2011-07-21 17:11:29 -0400
committerDave Jones <davej@redhat.com>2011-10-26 17:19:46 -0400
commit27e954c241673d2437448bd8bf0eaa7cd81a4b15 (patch)
tree457008d9d5b8fa9dacb3a0c00ce81248e26c0cb6 /drivers/cpufreq/e_powersaver.c
parented361bf08033f165e0a004f254919e13f07df0ae (diff)
[CPUFREQ] e_powersaver: Check BIOS limit for CPU frequency
Call ACPI function to get BIOS limit for CPU frequency. Fail if processor would like to run at higher frequency. Allow user to ignore BIOS limit. eps: Detected VIA Model D C7-M eps: Current voltage = 1084mV eps: Current multiplier = 16 eps: Highest voltage = 1084mV eps: Highest multiplier = 16 eps: Lowest voltage = 844mV eps: Lowest multiplier = 4 eps: ACPI limit 1.60GHz Signed-off-by: Rafał Bilski <rafalbilski@interia.pl> Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'drivers/cpufreq/e_powersaver.c')
-rw-r--r--drivers/cpufreq/e_powersaver.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index 84661c54a74c..2882d40a3084 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -19,6 +19,11 @@
19#include <asm/msr.h> 19#include <asm/msr.h>
20#include <asm/tsc.h> 20#include <asm/tsc.h>
21 21
22#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
23#include <linux/acpi.h>
24#include <acpi/processor.h>
25#endif
26
22#define EPS_BRAND_C7M 0 27#define EPS_BRAND_C7M 0
23#define EPS_BRAND_C7 1 28#define EPS_BRAND_C7 1
24#define EPS_BRAND_EDEN 2 29#define EPS_BRAND_EDEN 2
@@ -27,6 +32,9 @@
27 32
28struct eps_cpu_data { 33struct eps_cpu_data {
29 u32 fsb; 34 u32 fsb;
35#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
36 u32 bios_limit;
37#endif
30 struct cpufreq_frequency_table freq_table[]; 38 struct cpufreq_frequency_table freq_table[];
31}; 39};
32 40
@@ -36,6 +44,46 @@ static struct eps_cpu_data *eps_cpu[NR_CPUS];
36static int freq_failsafe_off; 44static int freq_failsafe_off;
37static int voltage_failsafe_off; 45static int voltage_failsafe_off;
38 46
47#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
48static int ignore_acpi_limit;
49
50static struct acpi_processor_performance *eps_acpi_cpu_perf;
51
52/* Minimum necessary to get acpi_processor_get_bios_limit() working */
53static int eps_acpi_init(void)
54{
55 eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance),
56 GFP_KERNEL);
57 if (!eps_acpi_cpu_perf)
58 return -ENOMEM;
59
60 if (!zalloc_cpumask_var(&eps_acpi_cpu_perf->shared_cpu_map,
61 GFP_KERNEL)) {
62 kfree(eps_acpi_cpu_perf);
63 eps_acpi_cpu_perf = NULL;
64 return -ENOMEM;
65 }
66
67 if (acpi_processor_register_performance(eps_acpi_cpu_perf, 0)) {
68 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
69 kfree(eps_acpi_cpu_perf);
70 eps_acpi_cpu_perf = NULL;
71 return -EIO;
72 }
73 return 0;
74}
75
76static int eps_acpi_exit(struct cpufreq_policy *policy)
77{
78 if (eps_acpi_cpu_perf) {
79 acpi_processor_unregister_performance(eps_acpi_cpu_perf, 0);
80 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map);
81 kfree(eps_acpi_cpu_perf);
82 eps_acpi_cpu_perf = NULL;
83 }
84 return 0;
85}
86#endif
39 87
40static unsigned int eps_get(unsigned int cpu) 88static unsigned int eps_get(unsigned int cpu)
41{ 89{
@@ -168,6 +216,9 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
168 int k, step, voltage; 216 int k, step, voltage;
169 int ret; 217 int ret;
170 int states; 218 int states;
219#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
220 unsigned int limit;
221#endif
171 222
172 if (policy->cpu != 0) 223 if (policy->cpu != 0)
173 return -ENODEV; 224 return -ENODEV;
@@ -271,6 +322,24 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
271 322
272 /* Calc FSB speed */ 323 /* Calc FSB speed */
273 fsb = cpu_khz / current_multiplier; 324 fsb = cpu_khz / current_multiplier;
325
326#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
327 /* Check for ACPI processor speed limit */
328 if (!ignore_acpi_limit && !eps_acpi_init()) {
329 if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) {
330 printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n",
331 limit/1000000,
332 (limit%1000000)/10000);
333 eps_acpi_exit(policy);
334 /* Check if max_multiplier is in BIOS limits */
335 if (limit && max_multiplier * fsb > limit) {
336 printk(KERN_INFO "eps: Aborting.\n");
337 return -EINVAL;
338 }
339 }
340 }
341#endif
342
274 /* Calc number of p-states supported */ 343 /* Calc number of p-states supported */
275 if (brand == EPS_BRAND_C7M) 344 if (brand == EPS_BRAND_C7M)
276 states = max_multiplier - min_multiplier + 1; 345 states = max_multiplier - min_multiplier + 1;
@@ -287,6 +356,9 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
287 356
288 /* Copy basic values */ 357 /* Copy basic values */
289 centaur->fsb = fsb; 358 centaur->fsb = fsb;
359#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
360 centaur->bios_limit = limit;
361#endif
290 362
291 /* Fill frequency and MSR value table */ 363 /* Fill frequency and MSR value table */
292 f_table = &centaur->freq_table[0]; 364 f_table = &centaur->freq_table[0];
@@ -377,6 +449,10 @@ module_param(freq_failsafe_off, int, 0644);
377MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check"); 449MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check");
378module_param(voltage_failsafe_off, int, 0644); 450module_param(voltage_failsafe_off, int, 0644);
379MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check"); 451MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check");
452#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
453module_param(ignore_acpi_limit, int, 0644);
454MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit");
455#endif
380 456
381MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>"); 457MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>");
382MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's."); 458MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's.");