diff options
| -rw-r--r-- | drivers/cpufreq/e_powersaver.c | 76 |
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 | ||
| 28 | struct eps_cpu_data { | 33 | struct 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]; | |||
| 36 | static int freq_failsafe_off; | 44 | static int freq_failsafe_off; |
| 37 | static int voltage_failsafe_off; | 45 | static int voltage_failsafe_off; |
| 38 | 46 | ||
| 47 | #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE | ||
| 48 | static int ignore_acpi_limit; | ||
| 49 | |||
| 50 | static struct acpi_processor_performance *eps_acpi_cpu_perf; | ||
| 51 | |||
| 52 | /* Minimum necessary to get acpi_processor_get_bios_limit() working */ | ||
| 53 | static 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 | |||
| 76 | static 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 | ||
| 40 | static unsigned int eps_get(unsigned int cpu) | 88 | static 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 = ¢aur->freq_table[0]; | 364 | f_table = ¢aur->freq_table[0]; |
| @@ -377,6 +449,10 @@ module_param(freq_failsafe_off, int, 0644); | |||
| 377 | MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check"); | 449 | MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check"); |
| 378 | module_param(voltage_failsafe_off, int, 0644); | 450 | module_param(voltage_failsafe_off, int, 0644); |
| 379 | MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check"); | 451 | MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check"); |
| 452 | #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE | ||
| 453 | module_param(ignore_acpi_limit, int, 0644); | ||
| 454 | MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit"); | ||
| 455 | #endif | ||
| 380 | 456 | ||
| 381 | MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>"); | 457 | MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>"); |
| 382 | MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's."); | 458 | MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's."); |
