1 /* 2 * Based on documentation provided by Dave Jones. Thanks! 3 * 4 * Licensed under the terms of the GNU GPL License version 2. 5 * 6 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* 7 */ 8 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/init.h> 12 #include <linux/cpufreq.h> 13 #include <linux/ioport.h> 14 #include <linux/slab.h> 15 #include <linux/timex.h> 16 #include <linux/io.h> 17 #include <linux/delay.h> 18 19 #include <asm/msr.h> 20 #include <asm/tsc.h> 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 27 #define EPS_BRAND_C7M 0 28 #define EPS_BRAND_C7 1 29 #define EPS_BRAND_EDEN 2 30 #define EPS_BRAND_C3 3 31 #define EPS_BRAND_C7D 4 32 33 struct eps_cpu_data { 34 u32 fsb; 35 #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE 36 u32 bios_limit; 37 #endif 38 struct cpufreq_frequency_table freq_table[]; 39 }; 40 41 static struct eps_cpu_data *eps_cpu[NR_CPUS]; 42 43 /* Module parameters */ 44 static int freq_failsafe_off; 45 static int voltage_failsafe_off; 46 static int set_max_voltage; 47 48 #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE 49 static int ignore_acpi_limit; 50 51 static struct acpi_processor_performance *eps_acpi_cpu_perf; 52 53 /* Minimum necessary to get acpi_processor_get_bios_limit() working */ 54 static int eps_acpi_init(void) 55 { 56 eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance), 57 GFP_KERNEL); 58 if (!eps_acpi_cpu_perf) 59 return -ENOMEM; 60 61 if (!zalloc_cpumask_var(&eps_acpi_cpu_perf->shared_cpu_map, 62 GFP_KERNEL)) { 63 kfree(eps_acpi_cpu_perf); 64 eps_acpi_cpu_perf = NULL; 65 return -ENOMEM; 66 } 67 68 if (acpi_processor_register_performance(eps_acpi_cpu_perf, 0)) { 69 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map); 70 kfree(eps_acpi_cpu_perf); 71 eps_acpi_cpu_perf = NULL; 72 return -EIO; 73 } 74 return 0; 75 } 76 77 static int eps_acpi_exit(struct cpufreq_policy *policy) 78 { 79 if (eps_acpi_cpu_perf) { 80 acpi_processor_unregister_performance(eps_acpi_cpu_perf, 0); 81 free_cpumask_var(eps_acpi_cpu_perf->shared_cpu_map); 82 kfree(eps_acpi_cpu_perf); 83 eps_acpi_cpu_perf = NULL; 84 } 85 return 0; 86 } 87 #endif 88 89 static unsigned int eps_get(unsigned int cpu) 90 { 91 struct eps_cpu_data *centaur; 92 u32 lo, hi; 93 94 if (cpu) 95 return 0; 96 centaur = eps_cpu[cpu]; 97 if (centaur == NULL) 98 return 0; 99 100 /* Return current frequency */ 101 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 102 return centaur->fsb * ((lo >> 8) & 0xff); 103 } 104 105 static int eps_set_state(struct eps_cpu_data *centaur, 106 unsigned int cpu, 107 u32 dest_state) 108 { 109 struct cpufreq_freqs freqs; 110 u32 lo, hi; 111 int err = 0; 112 int i; 113 114 freqs.old = eps_get(cpu); 115 freqs.new = centaur->fsb * ((dest_state >> 8) & 0xff); 116 freqs.cpu = cpu; 117 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); 118 119 /* Wait while CPU is busy */ 120 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 121 i = 0; 122 while (lo & ((1 << 16) | (1 << 17))) { 123 udelay(16); 124 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 125 i++; 126 if (unlikely(i > 64)) { 127 err = -ENODEV; 128 goto postchange; 129 } 130 } 131 /* Set new multiplier and voltage */ 132 wrmsr(MSR_IA32_PERF_CTL, dest_state & 0xffff, 0); 133 /* Wait until transition end */ 134 i = 0; 135 do { 136 udelay(16); 137 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 138 i++; 139 if (unlikely(i > 64)) { 140 err = -ENODEV; 141 goto postchange; 142 } 143 } while (lo & ((1 << 16) | (1 << 17))); 144 145 /* Return current frequency */ 146 postchange: 147 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 148 freqs.new = centaur->fsb * ((lo >> 8) & 0xff); 149 150 #ifdef DEBUG 151 { 152 u8 current_multiplier, current_voltage; 153 154 /* Print voltage and multiplier */ 155 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 156 current_voltage = lo & 0xff; 157 printk(KERN_INFO "eps: Current voltage = %dmV\n", 158 current_voltage * 16 + 700); 159 current_multiplier = (lo >> 8) & 0xff; 160 printk(KERN_INFO "eps: Current multiplier = %d\n", 161 current_multiplier); 162 } 163 #endif 164 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); 165 return err; 166 } 167 168 static int eps_target(struct cpufreq_policy *policy, 169 unsigned int target_freq, 170 unsigned int relation) 171 { 172 struct eps_cpu_data *centaur; 173 unsigned int newstate = 0; 174 unsigned int cpu = policy->cpu; 175 unsigned int dest_state; 176 int ret; 177 178 if (unlikely(eps_cpu[cpu] == NULL)) 179 return -ENODEV; 180 centaur = eps_cpu[cpu]; 181 182 if (unlikely(cpufreq_frequency_table_target(policy, 183 &eps_cpu[cpu]->freq_table[0], 184 target_freq, 185 relation, 186 &newstate))) { 187 return -EINVAL; 188 } 189 190 /* Make frequency transition */ 191 dest_state = centaur->freq_table[newstate].index & 0xffff; 192 ret = eps_set_state(centaur, cpu, dest_state); 193 if (ret) 194 printk(KERN_ERR "eps: Timeout!\n"); 195 return ret; 196 } 197 198 static int eps_verify(struct cpufreq_policy *policy) 199 { 200 return cpufreq_frequency_table_verify(policy, 201 &eps_cpu[policy->cpu]->freq_table[0]); 202 } 203 204 static int eps_cpu_init(struct cpufreq_policy *policy) 205 { 206 unsigned int i; 207 u32 lo, hi; 208 u64 val; 209 u8 current_multiplier, current_voltage; 210 u8 max_multiplier, max_voltage; 211 u8 min_multiplier, min_voltage; 212 u8 brand = 0; 213 u32 fsb; 214 struct eps_cpu_data *centaur; 215 struct cpuinfo_x86 *c = &cpu_data(0); 216 struct cpufreq_frequency_table *f_table; 217 int k, step, voltage; 218 int ret; 219 int states; 220 #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE 221 unsigned int limit; 222 #endif 223 224 if (policy->cpu != 0) 225 return -ENODEV; 226 227 /* Check brand */ 228 printk(KERN_INFO "eps: Detected VIA "); 229 230 switch (c->x86_model) { 231 case 10: 232 rdmsr(0x1153, lo, hi); 233 brand = (((lo >> 2) ^ lo) >> 18) & 3; 234 printk(KERN_CONT "Model A "); 235 break; 236 case 13: 237 rdmsr(0x1154, lo, hi); 238 brand = (((lo >> 4) ^ (lo >> 2))) & 0x000000ff; 239 printk(KERN_CONT "Model D "); 240 break; 241 } 242 243 switch (brand) { 244 case EPS_BRAND_C7M: 245 printk(KERN_CONT "C7-M\n"); 246 break; 247 case EPS_BRAND_C7: 248 printk(KERN_CONT "C7\n"); 249 break; 250 case EPS_BRAND_EDEN: 251 printk(KERN_CONT "Eden\n"); 252 break; 253 case EPS_BRAND_C7D: 254 printk(KERN_CONT "C7-D\n"); 255 break; 256 case EPS_BRAND_C3: 257 printk(KERN_CONT "C3\n"); 258 return -ENODEV; 259 break; 260 } 261 /* Enable Enhanced PowerSaver */ 262 rdmsrl(MSR_IA32_MISC_ENABLE, val); 263 if (!(val & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) { 264 val |= MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP; 265 wrmsrl(MSR_IA32_MISC_ENABLE, val); 266 /* Can be locked at 0 */ 267 rdmsrl(MSR_IA32_MISC_ENABLE, val); 268 if (!(val & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) { 269 printk(KERN_INFO "eps: Can't enable Enhanced PowerSaver\n"); 270 return -ENODEV; 271 } 272 } 273 274 /* Print voltage and multiplier */ 275 rdmsr(MSR_IA32_PERF_STATUS, lo, hi); 276 current_voltage = lo & 0xff; 277 printk(KERN_INFO "eps: Current voltage = %dmV\n", 278 current_voltage * 16 + 700); 279 current_multiplier = (lo >> 8) & 0xff; 280 printk(KERN_INFO "eps: Current multiplier = %d\n", current_multiplier); 281 282 /* Print limits */ 283 max_voltage = hi & 0xff; 284 printk(KERN_INFO "eps: Highest voltage = %dmV\n", 285 max_voltage * 16 + 700); 286 max_multiplier = (hi >> 8) & 0xff; 287 printk(KERN_INFO "eps: Highest multiplier = %d\n", max_multiplier); 288 min_voltage = (hi >> 16) & 0xff; 289 printk(KERN_INFO "eps: Lowest voltage = %dmV\n", 290 min_voltage * 16 + 700); 291 min_multiplier = (hi >> 24) & 0xff; 292 printk(KERN_INFO "eps: Lowest multiplier = %d\n", min_multiplier); 293 294 /* Sanity checks */ 295 if (current_multiplier == 0 || max_multiplier == 0 296 || min_multiplier == 0) 297 return -EINVAL; 298 if (current_multiplier > max_multiplier 299 || max_multiplier <= min_multiplier) 300 return -EINVAL; 301 if (current_voltage > 0x1f || max_voltage > 0x1f) 302 return -EINVAL; 303 if (max_voltage < min_voltage 304 || current_voltage < min_voltage 305 || current_voltage > max_voltage) 306 return -EINVAL; 307 308 /* Check for systems using underclocked CPU */ 309 if (!freq_failsafe_off && max_multiplier != current_multiplier) { 310 printk(KERN_INFO "eps: Your processor is running at different " 311 "frequency then its maximum. Aborting.\n"); 312 printk(KERN_INFO "eps: You can use freq_failsafe_off option " 313 "to disable this check.\n"); 314 return -EINVAL; 315 } 316 if (!voltage_failsafe_off && max_voltage != current_voltage) { 317 printk(KERN_INFO "eps: Your processor is running at different " 318 "voltage then its maximum. Aborting.\n"); 319 printk(KERN_INFO "eps: You can use voltage_failsafe_off " 320 "option to disable this check.\n"); 321 return -EINVAL; 322 } 323 324 /* Calc FSB speed */ 325 fsb = cpu_khz / current_multiplier; 326 327 #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE 328 /* Check for ACPI processor speed limit */ 329 if (!ignore_acpi_limit && !eps_acpi_init()) { 330 if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) { 331 printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n", 332 limit/1000000, 333 (limit%1000000)/10000); 334 eps_acpi_exit(policy); 335 /* Check if max_multiplier is in BIOS limits */ 336 if (limit && max_multiplier * fsb > limit) { 337 printk(KERN_INFO "eps: Aborting.\n"); 338 return -EINVAL; 339 } 340 } 341 } 342 #endif 343 344 /* Allow user to set lower maximum voltage then that reported 345 * by processor */ 346 if (brand == EPS_BRAND_C7M && set_max_voltage) { 347 u32 v; 348 349 /* Change mV to something hardware can use */ 350 v = (set_max_voltage - 700) / 16; 351 /* Check if voltage is within limits */ 352 if (v >= min_voltage && v <= max_voltage) { 353 printk(KERN_INFO "eps: Setting %dmV as maximum.\n", 354 v * 16 + 700); 355 max_voltage = v; 356 } 357 } 358 359 /* Calc number of p-states supported */ 360 if (brand == EPS_BRAND_C7M) 361 states = max_multiplier - min_multiplier + 1; 362 else 363 states = 2; 364 365 /* Allocate private data and frequency table for current cpu */ 366 centaur = kzalloc(sizeof(struct eps_cpu_data) 367 + (states + 1) * sizeof(struct cpufreq_frequency_table), 368 GFP_KERNEL); 369 if (!centaur) 370 return -ENOMEM; 371 eps_cpu[0] = centaur; 372 373 /* Copy basic values */ 374 centaur->fsb = fsb; 375 #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE 376 centaur->bios_limit = limit; 377 #endif 378 379 /* Fill frequency and MSR value table */ 380 f_table = ¢aur->freq_table[0]; 381 if (brand != EPS_BRAND_C7M) { 382 f_table[0].frequency = fsb * min_multiplier; 383 f_table[0].index = (min_multiplier << 8) | min_voltage; 384 f_table[1].frequency = fsb * max_multiplier; 385 f_table[1].index = (max_multiplier << 8) | max_voltage; 386 f_table[2].frequency = CPUFREQ_TABLE_END; 387 } else { 388 k = 0; 389 step = ((max_voltage - min_voltage) * 256) 390 / (max_multiplier - min_multiplier); 391 for (i = min_multiplier; i <= max_multiplier; i++) { 392 voltage = (k * step) / 256 + min_voltage; 393 f_table[k].frequency = fsb * i; 394 f_table[k].index = (i << 8) | voltage; 395 k++; 396 } 397 f_table[k].frequency = CPUFREQ_TABLE_END; 398 } 399 400 policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ 401 policy->cur = fsb * current_multiplier; 402 403 ret = cpufreq_frequency_table_cpuinfo(policy, ¢aur->freq_table[0]); 404 if (ret) { 405 kfree(centaur); 406 return ret; 407 } 408 409 cpufreq_frequency_table_get_attr(¢aur->freq_table[0], policy->cpu); 410 return 0; 411 } 412 413 static int eps_cpu_exit(struct cpufreq_policy *policy) 414 { 415 unsigned int cpu = policy->cpu; 416 417 /* Bye */ 418 cpufreq_frequency_table_put_attr(policy->cpu); 419 kfree(eps_cpu[cpu]); 420 eps_cpu[cpu] = NULL; 421 return 0; 422 } 423 424 static struct freq_attr *eps_attr[] = { 425 &cpufreq_freq_attr_scaling_available_freqs, 426 NULL, 427 }; 428 429 static struct cpufreq_driver eps_driver = { 430 .verify = eps_verify, 431 .target = eps_target, 432 .init = eps_cpu_init, 433 .exit = eps_cpu_exit, 434 .get = eps_get, 435 .name = "e_powersaver", 436 .owner = THIS_MODULE, 437 .attr = eps_attr, 438 }; 439 440 static int __init eps_init(void) 441 { 442 struct cpuinfo_x86 *c = &cpu_data(0); 443 444 /* This driver will work only on Centaur C7 processors with 445 * Enhanced SpeedStep/PowerSaver registers */ 446 if (c->x86_vendor != X86_VENDOR_CENTAUR 447 || c->x86 != 6 || c->x86_model < 10) 448 return -ENODEV; 449 if (!cpu_has(c, X86_FEATURE_EST)) 450 return -ENODEV; 451 452 if (cpufreq_register_driver(&eps_driver)) 453 return -EINVAL; 454 return 0; 455 } 456 457 static void __exit eps_exit(void) 458 { 459 cpufreq_unregister_driver(&eps_driver); 460 } 461 462 /* Allow user to overclock his machine or to change frequency to higher after 463 * unloading module */ 464 module_param(freq_failsafe_off, int, 0644); 465 MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check"); 466 module_param(voltage_failsafe_off, int, 0644); 467 MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check"); 468 #if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE 469 module_param(ignore_acpi_limit, int, 0644); 470 MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit"); 471 #endif 472 module_param(set_max_voltage, int, 0644); 473 MODULE_PARM_DESC(set_max_voltage, "Set maximum CPU voltage (mV) C7-M only"); 474 475 MODULE_AUTHOR("Rafal Bilski <rafalbilski@interia.pl>"); 476 MODULE_DESCRIPTION("Enhanced PowerSaver driver for VIA C7 CPU's."); 477 MODULE_LICENSE("GPL"); 478 479 module_init(eps_init); 480 module_exit(eps_exit); 481