This source file includes following definitions.
- pm121_correct
- pm121_connect
- pm121_create_sys_fans
- pm121_sys_fans_tick
- pm121_create_cpu_fans
- pm121_cpu_fans_tick
- pm121_tick
- pm121_register_control
- pm121_new_control
- pm121_register_sensor
- pm121_new_sensor
- pm121_notify
- pm121_init_pm
- pm121_probe
- pm121_remove
- pm121_init
- pm121_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 
 126 
 127 
 128 
 129 
 130 
 131 
 132 
 133 
 134 
 135 
 136 
 137 
 138 
 139 
 140 
 141 
 142 
 143 
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 
 152 
 153 
 154 
 155 
 156 
 157 
 158 
 159 
 160 
 161 
 162 
 163 
 164 
 165 
 166 
 167 
 168 
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 
 177 
 178 
 179 
 180 
 181 
 182 
 183 
 184 
 185 
 186 
 187 
 188 
 189 
 190 
 191 #undef  DEBUG
 192 
 193 #include <linux/types.h>
 194 #include <linux/errno.h>
 195 #include <linux/kernel.h>
 196 #include <linux/delay.h>
 197 #include <linux/slab.h>
 198 #include <linux/init.h>
 199 #include <linux/spinlock.h>
 200 #include <linux/wait.h>
 201 #include <linux/kmod.h>
 202 #include <linux/device.h>
 203 #include <linux/platform_device.h>
 204 #include <asm/prom.h>
 205 #include <asm/machdep.h>
 206 #include <asm/io.h>
 207 #include <asm/sections.h>
 208 #include <asm/smu.h>
 209 
 210 #include "windfarm.h"
 211 #include "windfarm_pid.h"
 212 
 213 #define VERSION "0.3"
 214 
 215 static int pm121_mach_model;    
 216 
 217 
 218 static struct wf_sensor *sensor_cpu_power;
 219 static struct wf_sensor *sensor_cpu_temp;
 220 static struct wf_sensor *sensor_cpu_voltage;
 221 static struct wf_sensor *sensor_cpu_current;
 222 static struct wf_sensor *sensor_gpu_temp;
 223 static struct wf_sensor *sensor_north_bridge_temp;
 224 static struct wf_sensor *sensor_hard_drive_temp;
 225 static struct wf_sensor *sensor_optical_drive_temp;
 226 static struct wf_sensor *sensor_incoming_air_temp; 
 227 
 228 enum {
 229         FAN_CPU,
 230         FAN_HD,
 231         FAN_OD,
 232         CPUFREQ,
 233         N_CONTROLS
 234 };
 235 static struct wf_control *controls[N_CONTROLS] = {};
 236 
 237 
 238 static int pm121_all_controls_ok, pm121_all_sensors_ok;
 239 static bool pm121_started;
 240 
 241 enum {
 242         FAILURE_FAN             = 1 << 0,
 243         FAILURE_SENSOR          = 1 << 1,
 244         FAILURE_OVERTEMP        = 1 << 2
 245 };
 246 
 247 
 248 
 249 enum {
 250         LOOP_GPU,               
 251 
 252         LOOP_HD,                
 253         LOOP_KODIAK,            
 254         LOOP_OD,                
 255         N_LOOPS
 256 };
 257 
 258 static const char *loop_names[N_LOOPS] = {
 259         "GPU",
 260         "HD",
 261         "KODIAK",
 262         "OD",
 263 };
 264 
 265 #define PM121_NUM_CONFIGS       2
 266 
 267 static unsigned int pm121_failure_state;
 268 static int pm121_readjust, pm121_skipping;
 269 static bool pm121_overtemp;
 270 static s32 average_power;
 271 
 272 struct pm121_correction {
 273         int     offset;
 274         int     slope;
 275 };
 276 
 277 static struct pm121_correction corrections[N_CONTROLS][PM121_NUM_CONFIGS] = {
 278         
 279         {
 280                 
 281                 { .offset       = -19563152,
 282                   .slope        =  1956315
 283                 },
 284                 
 285                 { .offset       = -15650652,
 286                   .slope        =  1565065
 287                 },
 288         },
 289         
 290         {
 291                 
 292                 { .offset       = -15650652,
 293                   .slope        =  1565065
 294                 },
 295                 
 296                 { .offset       = -19563152,
 297                   .slope        =  1956315
 298                 },
 299         },
 300         
 301         {
 302                 
 303                 { .offset       = -25431900,
 304                   .slope        =  2543190
 305                 },
 306                 
 307                 { .offset       = -15650652,
 308                   .slope        =  1565065
 309                 },
 310         },
 311         
 312 };
 313 
 314 struct pm121_connection {
 315         unsigned int    control_id;
 316         unsigned int    ref_id;
 317         struct pm121_correction correction;
 318 };
 319 
 320 static struct pm121_connection pm121_connections[] = {
 321         
 322         { .control_id   = FAN_CPU,
 323           .ref_id       = FAN_OD,
 324           { .offset     = -32768000,
 325             .slope      =  65536
 326           }
 327         },
 328         
 329         { .control_id   = FAN_OD,
 330           .ref_id       = FAN_HD,
 331           { .offset     = -32768000,
 332             .slope      =  65536
 333           }
 334         },
 335 };
 336 
 337 
 338 static struct pm121_connection *pm121_connection;
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 struct pm121_sys_param {
 351         
 352         int                     model_id;
 353         struct wf_sensor        **sensor; 
 354         s32                     gp, itarget;
 355         unsigned int            control_id;
 356 };
 357 
 358 static struct pm121_sys_param
 359 pm121_sys_all_params[N_LOOPS][PM121_NUM_CONFIGS] = {
 360         
 361         {
 362                 { .model_id     = 2,
 363                   .sensor       = &sensor_gpu_temp,
 364                   .gp           = 0x002A6666,
 365                   .itarget      = 0x5A0000,
 366                   .control_id   = FAN_HD,
 367                 },
 368                 { .model_id     = 3,
 369                   .sensor       = &sensor_gpu_temp,
 370                   .gp           = 0x0010CCCC,
 371                   .itarget      = 0x500000,
 372                   .control_id   = FAN_CPU,
 373                 },
 374         },
 375         
 376         {
 377                 { .model_id     = 2,
 378                   .sensor       = &sensor_hard_drive_temp,
 379                   .gp           = 0x002D70A3,
 380                   .itarget      = 0x370000,
 381                   .control_id   = FAN_HD,
 382                 },
 383                 { .model_id     = 3,
 384                   .sensor       = &sensor_hard_drive_temp,
 385                   .gp           = 0x002170A3,
 386                   .itarget      = 0x370000,
 387                   .control_id   = FAN_HD,
 388                 },
 389         },
 390         
 391         {
 392                 { .model_id     = 2,
 393                   .sensor       = &sensor_north_bridge_temp,
 394                   .gp           = 0x003BD70A,
 395                   .itarget      = 0x550000,
 396                   .control_id   = FAN_OD,
 397                 },
 398                 { .model_id     = 3,
 399                   .sensor       = &sensor_north_bridge_temp,
 400                   .gp           = 0x0030F5C2,
 401                   .itarget      = 0x550000,
 402                   .control_id   = FAN_HD,
 403                 },
 404         },
 405         
 406         {
 407                 { .model_id     = 2,
 408                   .sensor       = &sensor_optical_drive_temp,
 409                   .gp           = 0x001FAE14,
 410                   .itarget      = 0x320000,
 411                   .control_id   = FAN_OD,
 412                 },
 413                 { .model_id     = 3,
 414                   .sensor       = &sensor_optical_drive_temp,
 415                   .gp           = 0x001FAE14,
 416                   .itarget      = 0x320000,
 417                   .control_id   = FAN_OD,
 418                 },
 419         },
 420 };
 421 
 422 
 423 #define PM121_SYS_GD            0x00000000
 424 #define PM121_SYS_GR            0x00019999
 425 #define PM121_SYS_HISTORY_SIZE  2
 426 #define PM121_SYS_INTERVAL      5
 427 
 428 
 429 
 430 struct pm121_sys_state {
 431         int                     ticks;
 432         s32                     setpoint;
 433         struct wf_pid_state     pid;
 434 };
 435 
 436 struct pm121_sys_state *pm121_sys_state[N_LOOPS] = {};
 437 
 438 
 439 
 440 
 441 
 442 
 443 #define PM121_CPU_INTERVAL      1
 444 
 445 
 446 
 447 struct pm121_cpu_state {
 448         int                     ticks;
 449         s32                     setpoint;
 450         struct wf_cpu_pid_state pid;
 451 };
 452 
 453 static struct pm121_cpu_state *pm121_cpu_state;
 454 
 455 
 456 
 457 
 458 
 459 
 460 
 461 
 462 
 463 static s32 pm121_correct(s32 new_setpoint,
 464                          unsigned int control_id,
 465                          s32 min)
 466 {
 467         s32 new_min;
 468         struct pm121_correction *correction;
 469         correction = &corrections[control_id][pm121_mach_model - 2];
 470 
 471         new_min = (average_power * correction->slope) >> 16;
 472         new_min += correction->offset;
 473         new_min = (new_min >> 16) + min;
 474 
 475         return max3(new_setpoint, new_min, 0);
 476 }
 477 
 478 static s32 pm121_connect(unsigned int control_id, s32 setpoint)
 479 {
 480         s32 new_min, value, new_setpoint;
 481 
 482         if (pm121_connection->control_id == control_id) {
 483                 controls[control_id]->ops->get_value(controls[control_id],
 484                                                      &value);
 485                 new_min = value * pm121_connection->correction.slope;
 486                 new_min += pm121_connection->correction.offset;
 487                 if (new_min > 0) {
 488                         new_setpoint = max(setpoint, (new_min >> 16));
 489                         if (new_setpoint != setpoint) {
 490                                 pr_debug("pm121: %s depending on %s, "
 491                                          "corrected from %d to %d RPM\n",
 492                                          controls[control_id]->name,
 493                                          controls[pm121_connection->ref_id]->name,
 494                                          (int) setpoint, (int) new_setpoint);
 495                         }
 496                 } else
 497                         new_setpoint = setpoint;
 498         }
 499         
 500         else
 501                 new_setpoint = setpoint;
 502 
 503         return new_setpoint;
 504 }
 505 
 506 
 507 static void pm121_create_sys_fans(int loop_id)
 508 {
 509         struct pm121_sys_param *param = NULL;
 510         struct wf_pid_param pid_param;
 511         struct wf_control *control = NULL;
 512         int i;
 513 
 514         
 515         for (i = 0; i < PM121_NUM_CONFIGS; i++) {
 516                 if (pm121_sys_all_params[loop_id][i].model_id == pm121_mach_model) {
 517                         param = &(pm121_sys_all_params[loop_id][i]);
 518                         break;
 519                 }
 520         }
 521 
 522         
 523         if (param == NULL) {
 524                 printk(KERN_WARNING "pm121: %s fan config not found "
 525                        " for this machine model\n",
 526                        loop_names[loop_id]);
 527                 goto fail;
 528         }
 529 
 530         control = controls[param->control_id];
 531 
 532         
 533         pm121_sys_state[loop_id] = kmalloc(sizeof(struct pm121_sys_state),
 534                                            GFP_KERNEL);
 535         if (pm121_sys_state[loop_id] == NULL) {
 536                 printk(KERN_WARNING "pm121: Memory allocation error\n");
 537                 goto fail;
 538         }
 539         pm121_sys_state[loop_id]->ticks = 1;
 540 
 541         
 542         pid_param.gd            = PM121_SYS_GD;
 543         pid_param.gp            = param->gp;
 544         pid_param.gr            = PM121_SYS_GR;
 545         pid_param.interval      = PM121_SYS_INTERVAL;
 546         pid_param.history_len   = PM121_SYS_HISTORY_SIZE;
 547         pid_param.itarget       = param->itarget;
 548         if(control)
 549         {
 550                 pid_param.min           = control->ops->get_min(control);
 551                 pid_param.max           = control->ops->get_max(control);
 552         } else {
 553                 
 554 
 555 
 556 
 557                 pid_param.min           = 0;
 558                 pid_param.max           = 0;
 559         }
 560 
 561         wf_pid_init(&pm121_sys_state[loop_id]->pid, &pid_param);
 562 
 563         pr_debug("pm121: %s Fan control loop initialized.\n"
 564                  "       itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
 565                  loop_names[loop_id], FIX32TOPRINT(pid_param.itarget),
 566                  pid_param.min, pid_param.max);
 567         return;
 568 
 569  fail:
 570         
 571 
 572         printk(KERN_WARNING "pm121: failed to set up %s loop "
 573                "setting \"%s\" to max speed.\n",
 574                loop_names[loop_id], control ? control->name : "uninitialized value");
 575 
 576         if (control)
 577                 wf_control_set_max(control);
 578 }
 579 
 580 static void pm121_sys_fans_tick(int loop_id)
 581 {
 582         struct pm121_sys_param *param;
 583         struct pm121_sys_state *st;
 584         struct wf_sensor *sensor;
 585         struct wf_control *control;
 586         s32 temp, new_setpoint;
 587         int rc;
 588 
 589         param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
 590         st = pm121_sys_state[loop_id];
 591         sensor = *(param->sensor);
 592         control = controls[param->control_id];
 593 
 594         if (--st->ticks != 0) {
 595                 if (pm121_readjust)
 596                         goto readjust;
 597                 return;
 598         }
 599         st->ticks = PM121_SYS_INTERVAL;
 600 
 601         rc = sensor->ops->get_value(sensor, &temp);
 602         if (rc) {
 603                 printk(KERN_WARNING "windfarm: %s sensor error %d\n",
 604                        sensor->name, rc);
 605                 pm121_failure_state |= FAILURE_SENSOR;
 606                 return;
 607         }
 608 
 609         pr_debug("pm121: %s Fan tick ! %s: %d.%03d\n",
 610                  loop_names[loop_id], sensor->name,
 611                  FIX32TOPRINT(temp));
 612 
 613         new_setpoint = wf_pid_run(&st->pid, temp);
 614 
 615         
 616         new_setpoint = pm121_correct(new_setpoint,
 617                                      param->control_id,
 618                                      st->pid.param.min);
 619         
 620         new_setpoint = pm121_connect(param->control_id, new_setpoint);
 621 
 622         if (new_setpoint == st->setpoint)
 623                 return;
 624         st->setpoint = new_setpoint;
 625         pr_debug("pm121: %s corrected setpoint: %d RPM\n",
 626                  control->name, (int)new_setpoint);
 627  readjust:
 628         if (control && pm121_failure_state == 0) {
 629                 rc = control->ops->set_value(control, st->setpoint);
 630                 if (rc) {
 631                         printk(KERN_WARNING "windfarm: %s fan error %d\n",
 632                                control->name, rc);
 633                         pm121_failure_state |= FAILURE_FAN;
 634                 }
 635         }
 636 }
 637 
 638 
 639 
 640 static void pm121_create_cpu_fans(void)
 641 {
 642         struct wf_cpu_pid_param pid_param;
 643         const struct smu_sdbp_header *hdr;
 644         struct smu_sdbp_cpupiddata *piddata;
 645         struct smu_sdbp_fvt *fvt;
 646         struct wf_control *fan_cpu;
 647         s32 tmax, tdelta, maxpow, powadj;
 648 
 649         fan_cpu = controls[FAN_CPU];
 650 
 651         
 652         hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
 653         if (hdr == 0) {
 654                 printk(KERN_WARNING "pm121: CPU PID fan config not found.\n");
 655                 goto fail;
 656         }
 657         piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
 658 
 659         
 660 
 661 
 662         hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
 663         if (hdr) {
 664                 fvt = (struct smu_sdbp_fvt *)&hdr[1];
 665                 tmax = ((s32)fvt->maxtemp) << 16;
 666         } else
 667                 tmax = 0x5e0000; 
 668 
 669         
 670         pm121_cpu_state = kmalloc(sizeof(struct pm121_cpu_state),
 671                                   GFP_KERNEL);
 672         if (pm121_cpu_state == NULL)
 673                 goto fail;
 674         pm121_cpu_state->ticks = 1;
 675 
 676         
 677         pid_param.interval = PM121_CPU_INTERVAL;
 678         pid_param.history_len = piddata->history_len;
 679         if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
 680                 printk(KERN_WARNING "pm121: History size overflow on "
 681                        "CPU control loop (%d)\n", piddata->history_len);
 682                 pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
 683         }
 684         pid_param.gd = piddata->gd;
 685         pid_param.gp = piddata->gp;
 686         pid_param.gr = piddata->gr / pid_param.history_len;
 687 
 688         tdelta = ((s32)piddata->target_temp_delta) << 16;
 689         maxpow = ((s32)piddata->max_power) << 16;
 690         powadj = ((s32)piddata->power_adj) << 16;
 691 
 692         pid_param.tmax = tmax;
 693         pid_param.ttarget = tmax - tdelta;
 694         pid_param.pmaxadj = maxpow - powadj;
 695 
 696         pid_param.min = fan_cpu->ops->get_min(fan_cpu);
 697         pid_param.max = fan_cpu->ops->get_max(fan_cpu);
 698 
 699         wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param);
 700 
 701         pr_debug("pm121: CPU Fan control initialized.\n");
 702         pr_debug("       ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
 703                  FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
 704                  pid_param.min, pid_param.max);
 705 
 706         return;
 707 
 708  fail:
 709         printk(KERN_WARNING "pm121: CPU fan config not found, max fan speed\n");
 710 
 711         if (controls[CPUFREQ])
 712                 wf_control_set_max(controls[CPUFREQ]);
 713         if (fan_cpu)
 714                 wf_control_set_max(fan_cpu);
 715 }
 716 
 717 
 718 static void pm121_cpu_fans_tick(struct pm121_cpu_state *st)
 719 {
 720         s32 new_setpoint, temp, power;
 721         struct wf_control *fan_cpu = NULL;
 722         int rc;
 723 
 724         if (--st->ticks != 0) {
 725                 if (pm121_readjust)
 726                         goto readjust;
 727                 return;
 728         }
 729         st->ticks = PM121_CPU_INTERVAL;
 730 
 731         fan_cpu = controls[FAN_CPU];
 732 
 733         rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
 734         if (rc) {
 735                 printk(KERN_WARNING "pm121: CPU temp sensor error %d\n",
 736                        rc);
 737                 pm121_failure_state |= FAILURE_SENSOR;
 738                 return;
 739         }
 740 
 741         rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
 742         if (rc) {
 743                 printk(KERN_WARNING "pm121: CPU power sensor error %d\n",
 744                        rc);
 745                 pm121_failure_state |= FAILURE_SENSOR;
 746                 return;
 747         }
 748 
 749         pr_debug("pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
 750                  FIX32TOPRINT(temp), FIX32TOPRINT(power));
 751 
 752         if (temp > st->pid.param.tmax)
 753                 pm121_failure_state |= FAILURE_OVERTEMP;
 754 
 755         new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
 756 
 757         
 758         new_setpoint = pm121_correct(new_setpoint,
 759                                      FAN_CPU,
 760                                      st->pid.param.min);
 761 
 762         
 763         new_setpoint = pm121_connect(FAN_CPU, new_setpoint);
 764 
 765         if (st->setpoint == new_setpoint)
 766                 return;
 767         st->setpoint = new_setpoint;
 768         pr_debug("pm121: CPU corrected setpoint: %d RPM\n", (int)new_setpoint);
 769 
 770  readjust:
 771         if (fan_cpu && pm121_failure_state == 0) {
 772                 rc = fan_cpu->ops->set_value(fan_cpu, st->setpoint);
 773                 if (rc) {
 774                         printk(KERN_WARNING "pm121: %s fan error %d\n",
 775                                fan_cpu->name, rc);
 776                         pm121_failure_state |= FAILURE_FAN;
 777                 }
 778         }
 779 }
 780 
 781 
 782 
 783 
 784 
 785 
 786 static void pm121_tick(void)
 787 {
 788         unsigned int last_failure = pm121_failure_state;
 789         unsigned int new_failure;
 790         s32 total_power;
 791         int i;
 792 
 793         if (!pm121_started) {
 794                 pr_debug("pm121: creating control loops !\n");
 795                 for (i = 0; i < N_LOOPS; i++)
 796                         pm121_create_sys_fans(i);
 797 
 798                 pm121_create_cpu_fans();
 799                 pm121_started = true;
 800         }
 801 
 802         
 803         if (pm121_skipping && --pm121_skipping)
 804                 return;
 805 
 806         
 807         total_power = 0;
 808         for (i = 0; i < pm121_cpu_state->pid.param.history_len; i++)
 809                 total_power += pm121_cpu_state->pid.powers[i];
 810 
 811         average_power = total_power / pm121_cpu_state->pid.param.history_len;
 812 
 813 
 814         pm121_failure_state = 0;
 815         for (i = 0 ; i < N_LOOPS; i++) {
 816                 if (pm121_sys_state[i])
 817                         pm121_sys_fans_tick(i);
 818         }
 819 
 820         if (pm121_cpu_state)
 821                 pm121_cpu_fans_tick(pm121_cpu_state);
 822 
 823         pm121_readjust = 0;
 824         new_failure = pm121_failure_state & ~last_failure;
 825 
 826         
 827 
 828 
 829         if (pm121_failure_state && !last_failure) {
 830                 for (i = 0; i < N_CONTROLS; i++) {
 831                         if (controls[i])
 832                                 wf_control_set_max(controls[i]);
 833                 }
 834         }
 835 
 836         
 837 
 838 
 839         if (!pm121_failure_state && last_failure) {
 840                 if (controls[CPUFREQ])
 841                         wf_control_set_min(controls[CPUFREQ]);
 842                 pm121_readjust = 1;
 843         }
 844 
 845         
 846 
 847 
 848         if (new_failure & FAILURE_OVERTEMP) {
 849                 wf_set_overtemp();
 850                 pm121_skipping = 2;
 851                 pm121_overtemp = true;
 852         }
 853 
 854         
 855 
 856 
 857 
 858 
 859 
 860         if (!pm121_failure_state && pm121_overtemp) {
 861                 wf_clear_overtemp();
 862                 pm121_overtemp = false;
 863         }
 864 }
 865 
 866 
 867 static struct wf_control* pm121_register_control(struct wf_control *ct,
 868                                                  const char *match,
 869                                                  unsigned int id)
 870 {
 871         if (controls[id] == NULL && !strcmp(ct->name, match)) {
 872                 if (wf_get_control(ct) == 0)
 873                         controls[id] = ct;
 874         }
 875         return controls[id];
 876 }
 877 
 878 static void pm121_new_control(struct wf_control *ct)
 879 {
 880         int all = 1;
 881 
 882         if (pm121_all_controls_ok)
 883                 return;
 884 
 885         all = pm121_register_control(ct, "optical-drive-fan", FAN_OD) && all;
 886         all = pm121_register_control(ct, "hard-drive-fan", FAN_HD) && all;
 887         all = pm121_register_control(ct, "cpu-fan", FAN_CPU) && all;
 888         all = pm121_register_control(ct, "cpufreq-clamp", CPUFREQ) && all;
 889 
 890         if (all)
 891                 pm121_all_controls_ok = 1;
 892 }
 893 
 894 
 895 
 896 
 897 static struct wf_sensor* pm121_register_sensor(struct wf_sensor *sensor,
 898                                                const char *match,
 899                                                struct wf_sensor **var)
 900 {
 901         if (*var == NULL && !strcmp(sensor->name, match)) {
 902                 if (wf_get_sensor(sensor) == 0)
 903                         *var = sensor;
 904         }
 905         return *var;
 906 }
 907 
 908 static void pm121_new_sensor(struct wf_sensor *sr)
 909 {
 910         int all = 1;
 911 
 912         if (pm121_all_sensors_ok)
 913                 return;
 914 
 915         all = pm121_register_sensor(sr, "cpu-temp",
 916                                     &sensor_cpu_temp) && all;
 917         all = pm121_register_sensor(sr, "cpu-current",
 918                                     &sensor_cpu_current) && all;
 919         all = pm121_register_sensor(sr, "cpu-voltage",
 920                                     &sensor_cpu_voltage) && all;
 921         all = pm121_register_sensor(sr, "cpu-power",
 922                                     &sensor_cpu_power) && all;
 923         all = pm121_register_sensor(sr, "hard-drive-temp",
 924                                     &sensor_hard_drive_temp) && all;
 925         all = pm121_register_sensor(sr, "optical-drive-temp",
 926                                     &sensor_optical_drive_temp) && all;
 927         all = pm121_register_sensor(sr, "incoming-air-temp",
 928                                     &sensor_incoming_air_temp) && all;
 929         all = pm121_register_sensor(sr, "north-bridge-temp",
 930                                     &sensor_north_bridge_temp) && all;
 931         all = pm121_register_sensor(sr, "gpu-temp",
 932                                     &sensor_gpu_temp) && all;
 933 
 934         if (all)
 935                 pm121_all_sensors_ok = 1;
 936 }
 937 
 938 
 939 
 940 static int pm121_notify(struct notifier_block *self,
 941                         unsigned long event, void *data)
 942 {
 943         switch (event) {
 944         case WF_EVENT_NEW_CONTROL:
 945                 pr_debug("pm121: new control %s detected\n",
 946                          ((struct wf_control *)data)->name);
 947                 pm121_new_control(data);
 948                 break;
 949         case WF_EVENT_NEW_SENSOR:
 950                 pr_debug("pm121: new sensor %s detected\n",
 951                          ((struct wf_sensor *)data)->name);
 952                 pm121_new_sensor(data);
 953                 break;
 954         case WF_EVENT_TICK:
 955                 if (pm121_all_controls_ok && pm121_all_sensors_ok)
 956                         pm121_tick();
 957                 break;
 958         }
 959 
 960         return 0;
 961 }
 962 
 963 static struct notifier_block pm121_events = {
 964         .notifier_call  = pm121_notify,
 965 };
 966 
 967 static int pm121_init_pm(void)
 968 {
 969         const struct smu_sdbp_header *hdr;
 970 
 971         hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
 972         if (hdr != 0) {
 973                 struct smu_sdbp_sensortree *st =
 974                         (struct smu_sdbp_sensortree *)&hdr[1];
 975                 pm121_mach_model = st->model_id;
 976         }
 977 
 978         pm121_connection = &pm121_connections[pm121_mach_model - 2];
 979 
 980         printk(KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
 981                pm121_mach_model);
 982 
 983         return 0;
 984 }
 985 
 986 
 987 static int pm121_probe(struct platform_device *ddev)
 988 {
 989         wf_register_client(&pm121_events);
 990 
 991         return 0;
 992 }
 993 
 994 static int pm121_remove(struct platform_device *ddev)
 995 {
 996         wf_unregister_client(&pm121_events);
 997         return 0;
 998 }
 999 
1000 static struct platform_driver pm121_driver = {
1001         .probe = pm121_probe,
1002         .remove = pm121_remove,
1003         .driver = {
1004                 .name = "windfarm",
1005                 .bus = &platform_bus_type,
1006         },
1007 };
1008 
1009 
1010 static int __init pm121_init(void)
1011 {
1012         int rc = -ENODEV;
1013 
1014         if (of_machine_is_compatible("PowerMac12,1"))
1015                 rc = pm121_init_pm();
1016 
1017         if (rc == 0) {
1018                 request_module("windfarm_smu_controls");
1019                 request_module("windfarm_smu_sensors");
1020                 request_module("windfarm_smu_sat");
1021                 request_module("windfarm_lm75_sensor");
1022                 request_module("windfarm_max6690_sensor");
1023                 request_module("windfarm_cpufreq_clamp");
1024                 platform_driver_register(&pm121_driver);
1025         }
1026 
1027         return rc;
1028 }
1029 
1030 static void __exit pm121_exit(void)
1031 {
1032 
1033         platform_driver_unregister(&pm121_driver);
1034 }
1035 
1036 
1037 module_init(pm121_init);
1038 module_exit(pm121_exit);
1039 
1040 MODULE_AUTHOR("Étienne Bersac <bersace@gmail.com>");
1041 MODULE_DESCRIPTION("Thermal control logic for iMac G5 (iSight)");
1042 MODULE_LICENSE("GPL");
1043