windfarm_pm112.c (18460B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Windfarm PowerMac thermal control. 4 * Control loops for machines with SMU and PPC970MP processors. 5 * 6 * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org> 7 * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. 8 */ 9#include <linux/types.h> 10#include <linux/errno.h> 11#include <linux/kernel.h> 12#include <linux/device.h> 13#include <linux/platform_device.h> 14#include <linux/reboot.h> 15#include <linux/of.h> 16#include <linux/slab.h> 17 18#include <asm/smu.h> 19 20#include "windfarm.h" 21#include "windfarm_pid.h" 22 23#define VERSION "0.2" 24 25#define DEBUG 26#undef LOTSA_DEBUG 27 28#ifdef DEBUG 29#define DBG(args...) printk(args) 30#else 31#define DBG(args...) do { } while(0) 32#endif 33 34#ifdef LOTSA_DEBUG 35#define DBG_LOTS(args...) printk(args) 36#else 37#define DBG_LOTS(args...) do { } while(0) 38#endif 39 40/* define this to force CPU overtemp to 60 degree, useful for testing 41 * the overtemp code 42 */ 43#undef HACKED_OVERTEMP 44 45/* We currently only handle 2 chips, 4 cores... */ 46#define NR_CHIPS 2 47#define NR_CORES 4 48#define NR_CPU_FANS 3 * NR_CHIPS 49 50/* Controls and sensors */ 51static struct wf_sensor *sens_cpu_temp[NR_CORES]; 52static struct wf_sensor *sens_cpu_power[NR_CORES]; 53static struct wf_sensor *hd_temp; 54static struct wf_sensor *slots_power; 55static struct wf_sensor *u4_temp; 56 57static struct wf_control *cpu_fans[NR_CPU_FANS]; 58static char *cpu_fan_names[NR_CPU_FANS] = { 59 "cpu-rear-fan-0", 60 "cpu-rear-fan-1", 61 "cpu-front-fan-0", 62 "cpu-front-fan-1", 63 "cpu-pump-0", 64 "cpu-pump-1", 65}; 66static struct wf_control *cpufreq_clamp; 67 68/* Second pump isn't required (and isn't actually present) */ 69#define CPU_FANS_REQD (NR_CPU_FANS - 2) 70#define FIRST_PUMP 4 71#define LAST_PUMP 5 72 73/* We keep a temperature history for average calculation of 180s */ 74#define CPU_TEMP_HIST_SIZE 180 75 76/* Scale factor for fan speed, *100 */ 77static int cpu_fan_scale[NR_CPU_FANS] = { 78 100, 79 100, 80 97, /* inlet fans run at 97% of exhaust fan */ 81 97, 82 100, /* updated later */ 83 100, /* updated later */ 84}; 85 86static struct wf_control *backside_fan; 87static struct wf_control *slots_fan; 88static struct wf_control *drive_bay_fan; 89 90/* PID loop state */ 91static struct wf_cpu_pid_state cpu_pid[NR_CORES]; 92static u32 cpu_thist[CPU_TEMP_HIST_SIZE]; 93static int cpu_thist_pt; 94static s64 cpu_thist_total; 95static s32 cpu_all_tmax = 100 << 16; 96static int cpu_last_target; 97static struct wf_pid_state backside_pid; 98static int backside_tick; 99static struct wf_pid_state slots_pid; 100static bool slots_started; 101static struct wf_pid_state drive_bay_pid; 102static int drive_bay_tick; 103 104static int nr_cores; 105static int have_all_controls; 106static int have_all_sensors; 107static bool started; 108 109static int failure_state; 110#define FAILURE_SENSOR 1 111#define FAILURE_FAN 2 112#define FAILURE_PERM 4 113#define FAILURE_LOW_OVERTEMP 8 114#define FAILURE_HIGH_OVERTEMP 16 115 116/* Overtemp values */ 117#define LOW_OVER_AVERAGE 0 118#define LOW_OVER_IMMEDIATE (10 << 16) 119#define LOW_OVER_CLEAR ((-10) << 16) 120#define HIGH_OVER_IMMEDIATE (14 << 16) 121#define HIGH_OVER_AVERAGE (10 << 16) 122#define HIGH_OVER_IMMEDIATE (14 << 16) 123 124 125/* Implementation... */ 126static int create_cpu_loop(int cpu) 127{ 128 int chip = cpu / 2; 129 int core = cpu & 1; 130 struct smu_sdbp_header *hdr; 131 struct smu_sdbp_cpupiddata *piddata; 132 struct wf_cpu_pid_param pid; 133 struct wf_control *main_fan = cpu_fans[0]; 134 s32 tmax; 135 int fmin; 136 137 /* Get FVT params to get Tmax; if not found, assume default */ 138 hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL); 139 if (hdr) { 140 struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1]; 141 tmax = fvt->maxtemp << 16; 142 } else 143 tmax = 95 << 16; /* default to 95 degrees C */ 144 145 /* We keep a global tmax for overtemp calculations */ 146 if (tmax < cpu_all_tmax) 147 cpu_all_tmax = tmax; 148 149 kfree(hdr); 150 151 /* Get PID params from the appropriate SAT */ 152 hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL); 153 if (hdr == NULL) { 154 printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n"); 155 return -EINVAL; 156 } 157 piddata = (struct smu_sdbp_cpupiddata *)&hdr[1]; 158 159 /* 160 * Darwin has a minimum fan speed of 1000 rpm for the 4-way and 161 * 515 for the 2-way. That appears to be overkill, so for now, 162 * impose a minimum of 750 or 515. 163 */ 164 fmin = (nr_cores > 2) ? 750 : 515; 165 166 /* Initialize PID loop */ 167 pid.interval = 1; /* seconds */ 168 pid.history_len = piddata->history_len; 169 pid.gd = piddata->gd; 170 pid.gp = piddata->gp; 171 pid.gr = piddata->gr / piddata->history_len; 172 pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8); 173 pid.ttarget = tmax - (piddata->target_temp_delta << 16); 174 pid.tmax = tmax; 175 pid.min = main_fan->ops->get_min(main_fan); 176 pid.max = main_fan->ops->get_max(main_fan); 177 if (pid.min < fmin) 178 pid.min = fmin; 179 180 wf_cpu_pid_init(&cpu_pid[cpu], &pid); 181 182 kfree(hdr); 183 184 return 0; 185} 186 187static void cpu_max_all_fans(void) 188{ 189 int i; 190 191 /* We max all CPU fans in case of a sensor error. We also do the 192 * cpufreq clamping now, even if it's supposedly done later by the 193 * generic code anyway, we do it earlier here to react faster 194 */ 195 if (cpufreq_clamp) 196 wf_control_set_max(cpufreq_clamp); 197 for (i = 0; i < NR_CPU_FANS; ++i) 198 if (cpu_fans[i]) 199 wf_control_set_max(cpu_fans[i]); 200} 201 202static int cpu_check_overtemp(s32 temp) 203{ 204 int new_state = 0; 205 s32 t_avg, t_old; 206 207 /* First check for immediate overtemps */ 208 if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) { 209 new_state |= FAILURE_LOW_OVERTEMP; 210 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0) 211 printk(KERN_ERR "windfarm: Overtemp due to immediate CPU" 212 " temperature !\n"); 213 } 214 if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) { 215 new_state |= FAILURE_HIGH_OVERTEMP; 216 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0) 217 printk(KERN_ERR "windfarm: Critical overtemp due to" 218 " immediate CPU temperature !\n"); 219 } 220 221 /* We calculate a history of max temperatures and use that for the 222 * overtemp management 223 */ 224 t_old = cpu_thist[cpu_thist_pt]; 225 cpu_thist[cpu_thist_pt] = temp; 226 cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE; 227 cpu_thist_total -= t_old; 228 cpu_thist_total += temp; 229 t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE; 230 231 DBG_LOTS("t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n", 232 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp)); 233 234 /* Now check for average overtemps */ 235 if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) { 236 new_state |= FAILURE_LOW_OVERTEMP; 237 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0) 238 printk(KERN_ERR "windfarm: Overtemp due to average CPU" 239 " temperature !\n"); 240 } 241 if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) { 242 new_state |= FAILURE_HIGH_OVERTEMP; 243 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0) 244 printk(KERN_ERR "windfarm: Critical overtemp due to" 245 " average CPU temperature !\n"); 246 } 247 248 /* Now handle overtemp conditions. We don't currently use the windfarm 249 * overtemp handling core as it's not fully suited to the needs of those 250 * new machine. This will be fixed later. 251 */ 252 if (new_state) { 253 /* High overtemp -> immediate shutdown */ 254 if (new_state & FAILURE_HIGH_OVERTEMP) 255 machine_power_off(); 256 if ((failure_state & new_state) != new_state) 257 cpu_max_all_fans(); 258 failure_state |= new_state; 259 } else if ((failure_state & FAILURE_LOW_OVERTEMP) && 260 (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) { 261 printk(KERN_ERR "windfarm: Overtemp condition cleared !\n"); 262 failure_state &= ~FAILURE_LOW_OVERTEMP; 263 } 264 265 return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP); 266} 267 268static void cpu_fans_tick(void) 269{ 270 int err, cpu; 271 s32 greatest_delta = 0; 272 s32 temp, power, t_max = 0; 273 int i, t, target = 0; 274 struct wf_sensor *sr; 275 struct wf_control *ct; 276 struct wf_cpu_pid_state *sp; 277 278 DBG_LOTS(KERN_DEBUG); 279 for (cpu = 0; cpu < nr_cores; ++cpu) { 280 /* Get CPU core temperature */ 281 sr = sens_cpu_temp[cpu]; 282 err = sr->ops->get_value(sr, &temp); 283 if (err) { 284 DBG("\n"); 285 printk(KERN_WARNING "windfarm: CPU %d temperature " 286 "sensor error %d\n", cpu, err); 287 failure_state |= FAILURE_SENSOR; 288 cpu_max_all_fans(); 289 return; 290 } 291 292 /* Keep track of highest temp */ 293 t_max = max(t_max, temp); 294 295 /* Get CPU power */ 296 sr = sens_cpu_power[cpu]; 297 err = sr->ops->get_value(sr, &power); 298 if (err) { 299 DBG("\n"); 300 printk(KERN_WARNING "windfarm: CPU %d power " 301 "sensor error %d\n", cpu, err); 302 failure_state |= FAILURE_SENSOR; 303 cpu_max_all_fans(); 304 return; 305 } 306 307 /* Run PID */ 308 sp = &cpu_pid[cpu]; 309 t = wf_cpu_pid_run(sp, power, temp); 310 311 if (cpu == 0 || sp->last_delta > greatest_delta) { 312 greatest_delta = sp->last_delta; 313 target = t; 314 } 315 DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ", 316 cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp)); 317 } 318 DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max)); 319 320 /* Darwin limits decrease to 20 per iteration */ 321 if (target < (cpu_last_target - 20)) 322 target = cpu_last_target - 20; 323 cpu_last_target = target; 324 for (cpu = 0; cpu < nr_cores; ++cpu) 325 cpu_pid[cpu].target = target; 326 327 /* Handle possible overtemps */ 328 if (cpu_check_overtemp(t_max)) 329 return; 330 331 /* Set fans */ 332 for (i = 0; i < NR_CPU_FANS; ++i) { 333 ct = cpu_fans[i]; 334 if (ct == NULL) 335 continue; 336 err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100); 337 if (err) { 338 printk(KERN_WARNING "windfarm: fan %s reports " 339 "error %d\n", ct->name, err); 340 failure_state |= FAILURE_FAN; 341 break; 342 } 343 } 344} 345 346/* Backside/U4 fan */ 347static struct wf_pid_param backside_param = { 348 .interval = 5, 349 .history_len = 2, 350 .gd = 48 << 20, 351 .gp = 5 << 20, 352 .gr = 0, 353 .itarget = 64 << 16, 354 .additive = 1, 355}; 356 357static void backside_fan_tick(void) 358{ 359 s32 temp; 360 int speed; 361 int err; 362 363 if (!backside_fan || !u4_temp) 364 return; 365 if (!backside_tick) { 366 /* first time; initialize things */ 367 printk(KERN_INFO "windfarm: Backside control loop started.\n"); 368 backside_param.min = backside_fan->ops->get_min(backside_fan); 369 backside_param.max = backside_fan->ops->get_max(backside_fan); 370 wf_pid_init(&backside_pid, &backside_param); 371 backside_tick = 1; 372 } 373 if (--backside_tick > 0) 374 return; 375 backside_tick = backside_pid.param.interval; 376 377 err = u4_temp->ops->get_value(u4_temp, &temp); 378 if (err) { 379 printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n", 380 err); 381 failure_state |= FAILURE_SENSOR; 382 wf_control_set_max(backside_fan); 383 return; 384 } 385 speed = wf_pid_run(&backside_pid, temp); 386 DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n", 387 FIX32TOPRINT(temp), speed); 388 389 err = backside_fan->ops->set_value(backside_fan, speed); 390 if (err) { 391 printk(KERN_WARNING "windfarm: backside fan error %d\n", err); 392 failure_state |= FAILURE_FAN; 393 } 394} 395 396/* Drive bay fan */ 397static struct wf_pid_param drive_bay_prm = { 398 .interval = 5, 399 .history_len = 2, 400 .gd = 30 << 20, 401 .gp = 5 << 20, 402 .gr = 0, 403 .itarget = 40 << 16, 404 .additive = 1, 405}; 406 407static void drive_bay_fan_tick(void) 408{ 409 s32 temp; 410 int speed; 411 int err; 412 413 if (!drive_bay_fan || !hd_temp) 414 return; 415 if (!drive_bay_tick) { 416 /* first time; initialize things */ 417 printk(KERN_INFO "windfarm: Drive bay control loop started.\n"); 418 drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan); 419 drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan); 420 wf_pid_init(&drive_bay_pid, &drive_bay_prm); 421 drive_bay_tick = 1; 422 } 423 if (--drive_bay_tick > 0) 424 return; 425 drive_bay_tick = drive_bay_pid.param.interval; 426 427 err = hd_temp->ops->get_value(hd_temp, &temp); 428 if (err) { 429 printk(KERN_WARNING "windfarm: drive bay temp sensor " 430 "error %d\n", err); 431 failure_state |= FAILURE_SENSOR; 432 wf_control_set_max(drive_bay_fan); 433 return; 434 } 435 speed = wf_pid_run(&drive_bay_pid, temp); 436 DBG_LOTS("drive_bay PID temp=%d.%.3d speed=%d\n", 437 FIX32TOPRINT(temp), speed); 438 439 err = drive_bay_fan->ops->set_value(drive_bay_fan, speed); 440 if (err) { 441 printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err); 442 failure_state |= FAILURE_FAN; 443 } 444} 445 446/* PCI slots area fan */ 447/* This makes the fan speed proportional to the power consumed */ 448static struct wf_pid_param slots_param = { 449 .interval = 1, 450 .history_len = 2, 451 .gd = 0, 452 .gp = 0, 453 .gr = 0x1277952, 454 .itarget = 0, 455 .min = 1560, 456 .max = 3510, 457}; 458 459static void slots_fan_tick(void) 460{ 461 s32 power; 462 int speed; 463 int err; 464 465 if (!slots_fan || !slots_power) 466 return; 467 if (!slots_started) { 468 /* first time; initialize things */ 469 printk(KERN_INFO "windfarm: Slots control loop started.\n"); 470 wf_pid_init(&slots_pid, &slots_param); 471 slots_started = true; 472 } 473 474 err = slots_power->ops->get_value(slots_power, &power); 475 if (err) { 476 printk(KERN_WARNING "windfarm: slots power sensor error %d\n", 477 err); 478 failure_state |= FAILURE_SENSOR; 479 wf_control_set_max(slots_fan); 480 return; 481 } 482 speed = wf_pid_run(&slots_pid, power); 483 DBG_LOTS("slots PID power=%d.%.3d speed=%d\n", 484 FIX32TOPRINT(power), speed); 485 486 err = slots_fan->ops->set_value(slots_fan, speed); 487 if (err) { 488 printk(KERN_WARNING "windfarm: slots fan error %d\n", err); 489 failure_state |= FAILURE_FAN; 490 } 491} 492 493static void set_fail_state(void) 494{ 495 int i; 496 497 if (cpufreq_clamp) 498 wf_control_set_max(cpufreq_clamp); 499 for (i = 0; i < NR_CPU_FANS; ++i) 500 if (cpu_fans[i]) 501 wf_control_set_max(cpu_fans[i]); 502 if (backside_fan) 503 wf_control_set_max(backside_fan); 504 if (slots_fan) 505 wf_control_set_max(slots_fan); 506 if (drive_bay_fan) 507 wf_control_set_max(drive_bay_fan); 508} 509 510static void pm112_tick(void) 511{ 512 int i, last_failure; 513 514 if (!started) { 515 started = true; 516 printk(KERN_INFO "windfarm: CPUs control loops started.\n"); 517 for (i = 0; i < nr_cores; ++i) { 518 if (create_cpu_loop(i) < 0) { 519 failure_state = FAILURE_PERM; 520 set_fail_state(); 521 break; 522 } 523 } 524 DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax)); 525 526#ifdef HACKED_OVERTEMP 527 cpu_all_tmax = 60 << 16; 528#endif 529 } 530 531 /* Permanent failure, bail out */ 532 if (failure_state & FAILURE_PERM) 533 return; 534 /* Clear all failure bits except low overtemp which will be eventually 535 * cleared by the control loop itself 536 */ 537 last_failure = failure_state; 538 failure_state &= FAILURE_LOW_OVERTEMP; 539 cpu_fans_tick(); 540 backside_fan_tick(); 541 slots_fan_tick(); 542 drive_bay_fan_tick(); 543 544 DBG_LOTS("last_failure: 0x%x, failure_state: %x\n", 545 last_failure, failure_state); 546 547 /* Check for failures. Any failure causes cpufreq clamping */ 548 if (failure_state && last_failure == 0 && cpufreq_clamp) 549 wf_control_set_max(cpufreq_clamp); 550 if (failure_state == 0 && last_failure && cpufreq_clamp) 551 wf_control_set_min(cpufreq_clamp); 552 553 /* That's it for now, we might want to deal with other failures 554 * differently in the future though 555 */ 556} 557 558static void pm112_new_control(struct wf_control *ct) 559{ 560 int i, max_exhaust; 561 562 if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) { 563 if (wf_get_control(ct) == 0) 564 cpufreq_clamp = ct; 565 } 566 567 for (i = 0; i < NR_CPU_FANS; ++i) { 568 if (!strcmp(ct->name, cpu_fan_names[i])) { 569 if (cpu_fans[i] == NULL && wf_get_control(ct) == 0) 570 cpu_fans[i] = ct; 571 break; 572 } 573 } 574 if (i >= NR_CPU_FANS) { 575 /* not a CPU fan, try the others */ 576 if (!strcmp(ct->name, "backside-fan")) { 577 if (backside_fan == NULL && wf_get_control(ct) == 0) 578 backside_fan = ct; 579 } else if (!strcmp(ct->name, "slots-fan")) { 580 if (slots_fan == NULL && wf_get_control(ct) == 0) 581 slots_fan = ct; 582 } else if (!strcmp(ct->name, "drive-bay-fan")) { 583 if (drive_bay_fan == NULL && wf_get_control(ct) == 0) 584 drive_bay_fan = ct; 585 } 586 return; 587 } 588 589 for (i = 0; i < CPU_FANS_REQD; ++i) 590 if (cpu_fans[i] == NULL) 591 return; 592 593 /* work out pump scaling factors */ 594 max_exhaust = cpu_fans[0]->ops->get_max(cpu_fans[0]); 595 for (i = FIRST_PUMP; i <= LAST_PUMP; ++i) 596 if ((ct = cpu_fans[i]) != NULL) 597 cpu_fan_scale[i] = 598 ct->ops->get_max(ct) * 100 / max_exhaust; 599 600 have_all_controls = 1; 601} 602 603static void pm112_new_sensor(struct wf_sensor *sr) 604{ 605 unsigned int i; 606 607 if (!strncmp(sr->name, "cpu-temp-", 9)) { 608 i = sr->name[9] - '0'; 609 if (sr->name[10] == 0 && i < NR_CORES && 610 sens_cpu_temp[i] == NULL && wf_get_sensor(sr) == 0) 611 sens_cpu_temp[i] = sr; 612 613 } else if (!strncmp(sr->name, "cpu-power-", 10)) { 614 i = sr->name[10] - '0'; 615 if (sr->name[11] == 0 && i < NR_CORES && 616 sens_cpu_power[i] == NULL && wf_get_sensor(sr) == 0) 617 sens_cpu_power[i] = sr; 618 } else if (!strcmp(sr->name, "hd-temp")) { 619 if (hd_temp == NULL && wf_get_sensor(sr) == 0) 620 hd_temp = sr; 621 } else if (!strcmp(sr->name, "slots-power")) { 622 if (slots_power == NULL && wf_get_sensor(sr) == 0) 623 slots_power = sr; 624 } else if (!strcmp(sr->name, "backside-temp")) { 625 if (u4_temp == NULL && wf_get_sensor(sr) == 0) 626 u4_temp = sr; 627 } else 628 return; 629 630 /* check if we have all the sensors we need */ 631 for (i = 0; i < nr_cores; ++i) 632 if (sens_cpu_temp[i] == NULL || sens_cpu_power[i] == NULL) 633 return; 634 635 have_all_sensors = 1; 636} 637 638static int pm112_wf_notify(struct notifier_block *self, 639 unsigned long event, void *data) 640{ 641 switch (event) { 642 case WF_EVENT_NEW_SENSOR: 643 pm112_new_sensor(data); 644 break; 645 case WF_EVENT_NEW_CONTROL: 646 pm112_new_control(data); 647 break; 648 case WF_EVENT_TICK: 649 if (have_all_controls && have_all_sensors) 650 pm112_tick(); 651 } 652 return 0; 653} 654 655static struct notifier_block pm112_events = { 656 .notifier_call = pm112_wf_notify, 657}; 658 659static int wf_pm112_probe(struct platform_device *dev) 660{ 661 wf_register_client(&pm112_events); 662 return 0; 663} 664 665static int wf_pm112_remove(struct platform_device *dev) 666{ 667 wf_unregister_client(&pm112_events); 668 /* should release all sensors and controls */ 669 return 0; 670} 671 672static struct platform_driver wf_pm112_driver = { 673 .probe = wf_pm112_probe, 674 .remove = wf_pm112_remove, 675 .driver = { 676 .name = "windfarm", 677 }, 678}; 679 680static int __init wf_pm112_init(void) 681{ 682 struct device_node *cpu; 683 684 if (!of_machine_is_compatible("PowerMac11,2")) 685 return -ENODEV; 686 687 /* Count the number of CPU cores */ 688 nr_cores = 0; 689 for_each_node_by_type(cpu, "cpu") 690 ++nr_cores; 691 692 printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n"); 693 694#ifdef MODULE 695 request_module("windfarm_smu_controls"); 696 request_module("windfarm_smu_sensors"); 697 request_module("windfarm_smu_sat"); 698 request_module("windfarm_lm75_sensor"); 699 request_module("windfarm_max6690_sensor"); 700 request_module("windfarm_cpufreq_clamp"); 701 702#endif /* MODULE */ 703 704 platform_driver_register(&wf_pm112_driver); 705 return 0; 706} 707 708static void __exit wf_pm112_exit(void) 709{ 710 platform_driver_unregister(&wf_pm112_driver); 711} 712 713module_init(wf_pm112_init); 714module_exit(wf_pm112_exit); 715 716MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); 717MODULE_DESCRIPTION("Thermal control for PowerMac11,2"); 718MODULE_LICENSE("GPL"); 719MODULE_ALIAS("platform:windfarm");