linux/drivers/macintosh/windfarm_rm31.c
<<
>>
Prefs
   1/*
   2 * Windfarm PowerMac thermal control.
   3 * Control loops for RackMack3,1 (Xserve G5)
   4 *
   5 * Copyright (C) 2012 Benjamin Herrenschmidt, IBM Corp.
   6 *
   7 * Use and redistribute under the terms of the GNU GPL v2.
   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 <asm/prom.h>
  16#include <asm/smu.h>
  17
  18#include "windfarm.h"
  19#include "windfarm_pid.h"
  20#include "windfarm_mpu.h"
  21
  22#define VERSION "1.0"
  23
  24#undef DEBUG
  25#undef LOTSA_DEBUG
  26
  27#ifdef DEBUG
  28#define DBG(args...)    printk(args)
  29#else
  30#define DBG(args...)    do { } while(0)
  31#endif
  32
  33#ifdef LOTSA_DEBUG
  34#define DBG_LOTS(args...)       printk(args)
  35#else
  36#define DBG_LOTS(args...)       do { } while(0)
  37#endif
  38
  39/* define this to force CPU overtemp to 60 degree, useful for testing
  40 * the overtemp code
  41 */
  42#undef HACKED_OVERTEMP
  43
  44/* We currently only handle 2 chips */
  45#define NR_CHIPS        2
  46#define NR_CPU_FANS     3 * NR_CHIPS
  47
  48/* Controls and sensors */
  49static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
  50static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
  51static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
  52static struct wf_sensor *backside_temp;
  53static struct wf_sensor *slots_temp;
  54static struct wf_sensor *dimms_temp;
  55
  56static struct wf_control *cpu_fans[NR_CHIPS][3];
  57static struct wf_control *backside_fan;
  58static struct wf_control *slots_fan;
  59static struct wf_control *cpufreq_clamp;
  60
  61/* We keep a temperature history for average calculation of 180s */
  62#define CPU_TEMP_HIST_SIZE      180
  63
  64/* PID loop state */
  65static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
  66static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
  67static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
  68static int cpu_thist_pt;
  69static s64 cpu_thist_total;
  70static s32 cpu_all_tmax = 100 << 16;
  71static struct wf_pid_state backside_pid;
  72static int backside_tick;
  73static struct wf_pid_state slots_pid;
  74static int slots_tick;
  75static int slots_speed;
  76static struct wf_pid_state dimms_pid;
  77static int dimms_output_clamp;
  78
  79static int nr_chips;
  80static bool have_all_controls;
  81static bool have_all_sensors;
  82static bool started;
  83
  84static int failure_state;
  85#define FAILURE_SENSOR          1
  86#define FAILURE_FAN             2
  87#define FAILURE_PERM            4
  88#define FAILURE_LOW_OVERTEMP    8
  89#define FAILURE_HIGH_OVERTEMP   16
  90
  91/* Overtemp values */
  92#define LOW_OVER_AVERAGE        0
  93#define LOW_OVER_IMMEDIATE      (10 << 16)
  94#define LOW_OVER_CLEAR          ((-10) << 16)
  95#define HIGH_OVER_IMMEDIATE     (14 << 16)
  96#define HIGH_OVER_AVERAGE       (10 << 16)
  97#define HIGH_OVER_IMMEDIATE     (14 << 16)
  98
  99
 100static void cpu_max_all_fans(void)
 101{
 102        int i;
 103
 104        /* We max all CPU fans in case of a sensor error. We also do the
 105         * cpufreq clamping now, even if it's supposedly done later by the
 106         * generic code anyway, we do it earlier here to react faster
 107         */
 108        if (cpufreq_clamp)
 109                wf_control_set_max(cpufreq_clamp);
 110        for (i = 0; i < nr_chips; i++) {
 111                if (cpu_fans[i][0])
 112                        wf_control_set_max(cpu_fans[i][0]);
 113                if (cpu_fans[i][1])
 114                        wf_control_set_max(cpu_fans[i][1]);
 115                if (cpu_fans[i][2])
 116                        wf_control_set_max(cpu_fans[i][2]);
 117        }
 118}
 119
 120static int cpu_check_overtemp(s32 temp)
 121{
 122        int new_state = 0;
 123        s32 t_avg, t_old;
 124        static bool first = true;
 125
 126        /* First check for immediate overtemps */
 127        if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
 128                new_state |= FAILURE_LOW_OVERTEMP;
 129                if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
 130                        printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
 131                               " temperature !\n");
 132        }
 133        if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
 134                new_state |= FAILURE_HIGH_OVERTEMP;
 135                if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
 136                        printk(KERN_ERR "windfarm: Critical overtemp due to"
 137                               " immediate CPU temperature !\n");
 138        }
 139
 140        /*
 141         * The first time around, initialize the array with the first
 142         * temperature reading
 143         */
 144        if (first) {
 145                int i;
 146
 147                cpu_thist_total = 0;
 148                for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
 149                        cpu_thist[i] = temp;
 150                        cpu_thist_total += temp;
 151                }
 152                first = false;
 153        }
 154
 155        /*
 156         * We calculate a history of max temperatures and use that for the
 157         * overtemp management
 158         */
 159        t_old = cpu_thist[cpu_thist_pt];
 160        cpu_thist[cpu_thist_pt] = temp;
 161        cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
 162        cpu_thist_total -= t_old;
 163        cpu_thist_total += temp;
 164        t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
 165
 166        DBG_LOTS("  t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
 167                 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
 168
 169        /* Now check for average overtemps */
 170        if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
 171                new_state |= FAILURE_LOW_OVERTEMP;
 172                if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
 173                        printk(KERN_ERR "windfarm: Overtemp due to average CPU"
 174                               " temperature !\n");
 175        }
 176        if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
 177                new_state |= FAILURE_HIGH_OVERTEMP;
 178                if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
 179                        printk(KERN_ERR "windfarm: Critical overtemp due to"
 180                               " average CPU temperature !\n");
 181        }
 182
 183        /* Now handle overtemp conditions. We don't currently use the windfarm
 184         * overtemp handling core as it's not fully suited to the needs of those
 185         * new machine. This will be fixed later.
 186         */
 187        if (new_state) {
 188                /* High overtemp -> immediate shutdown */
 189                if (new_state & FAILURE_HIGH_OVERTEMP)
 190                        machine_power_off();
 191                if ((failure_state & new_state) != new_state)
 192                        cpu_max_all_fans();
 193                failure_state |= new_state;
 194        } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
 195                   (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
 196                printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
 197                failure_state &= ~FAILURE_LOW_OVERTEMP;
 198        }
 199
 200        return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
 201}
 202
 203static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
 204{
 205        s32 dtemp, volts, amps;
 206        int rc;
 207
 208        /* Get diode temperature */
 209        rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
 210        if (rc) {
 211                DBG("  CPU%d: temp reading error !\n", cpu);
 212                return -EIO;
 213        }
 214        DBG_LOTS("  CPU%d: temp   = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
 215        *temp = dtemp;
 216
 217        /* Get voltage */
 218        rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
 219        if (rc) {
 220                DBG("  CPU%d, volts reading error !\n", cpu);
 221                return -EIO;
 222        }
 223        DBG_LOTS("  CPU%d: volts  = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
 224
 225        /* Get current */
 226        rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
 227        if (rc) {
 228                DBG("  CPU%d, current reading error !\n", cpu);
 229                return -EIO;
 230        }
 231        DBG_LOTS("  CPU%d: amps   = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
 232
 233        /* Calculate power */
 234
 235        /* Scale voltage and current raw sensor values according to fixed scales
 236         * obtained in Darwin and calculate power from I and V
 237         */
 238        *power = (((u64)volts) * ((u64)amps)) >> 16;
 239
 240        DBG_LOTS("  CPU%d: power  = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
 241
 242        return 0;
 243
 244}
 245
 246static void cpu_fans_tick(void)
 247{
 248        int err, cpu, i;
 249        s32 speed, temp, power, t_max = 0;
 250
 251        DBG_LOTS("* cpu fans_tick_split()\n");
 252
 253        for (cpu = 0; cpu < nr_chips; ++cpu) {
 254                struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
 255
 256                /* Read current speed */
 257                wf_control_get(cpu_fans[cpu][0], &sp->target);
 258
 259                err = read_one_cpu_vals(cpu, &temp, &power);
 260                if (err) {
 261                        failure_state |= FAILURE_SENSOR;
 262                        cpu_max_all_fans();
 263                        return;
 264                }
 265
 266                /* Keep track of highest temp */
 267                t_max = max(t_max, temp);
 268
 269                /* Handle possible overtemps */
 270                if (cpu_check_overtemp(t_max))
 271                        return;
 272
 273                /* Run PID */
 274                wf_cpu_pid_run(sp, power, temp);
 275
 276                DBG_LOTS("  CPU%d: target = %d RPM\n", cpu, sp->target);
 277
 278                /* Apply DIMMs clamp */
 279                speed = max(sp->target, dimms_output_clamp);
 280
 281                /* Apply result to all cpu fans */
 282                for (i = 0; i < 3; i++) {
 283                        err = wf_control_set(cpu_fans[cpu][i], speed);
 284                        if (err) {
 285                                pr_warning("wf_rm31: Fan %s reports error %d\n",
 286                                           cpu_fans[cpu][i]->name, err);
 287                                failure_state |= FAILURE_FAN;
 288                        }
 289                }
 290        }
 291}
 292
 293/* Implementation... */
 294static int cpu_setup_pid(int cpu)
 295{
 296        struct wf_cpu_pid_param pid;
 297        const struct mpu_data *mpu = cpu_mpu_data[cpu];
 298        s32 tmax, ttarget, ptarget;
 299        int fmin, fmax, hsize;
 300
 301        /* Get PID params from the appropriate MPU EEPROM */
 302        tmax = mpu->tmax << 16;
 303        ttarget = mpu->ttarget << 16;
 304        ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
 305
 306        DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
 307            cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
 308
 309        /* We keep a global tmax for overtemp calculations */
 310        if (tmax < cpu_all_tmax)
 311                cpu_all_tmax = tmax;
 312
 313        /* Set PID min/max by using the rear fan min/max */
 314        fmin = wf_control_get_min(cpu_fans[cpu][0]);
 315        fmax = wf_control_get_max(cpu_fans[cpu][0]);
 316        DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
 317
 318        /* History size */
 319        hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
 320        DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
 321
 322        /* Initialize PID loop */
 323        pid.interval    = 1;    /* seconds */
 324        pid.history_len = hsize;
 325        pid.gd          = mpu->pid_gd;
 326        pid.gp          = mpu->pid_gp;
 327        pid.gr          = mpu->pid_gr;
 328        pid.tmax        = tmax;
 329        pid.ttarget     = ttarget;
 330        pid.pmaxadj     = ptarget;
 331        pid.min         = fmin;
 332        pid.max         = fmax;
 333
 334        wf_cpu_pid_init(&cpu_pid[cpu], &pid);
 335        cpu_pid[cpu].target = 4000;
 336        
 337        return 0;
 338}
 339
 340/* Backside/U3 fan */
 341static struct wf_pid_param backside_param = {
 342        .interval       = 1,
 343        .history_len    = 2,
 344        .gd             = 0x00500000,
 345        .gp             = 0x0004cccc,
 346        .gr             = 0,
 347        .itarget        = 70 << 16,
 348        .additive       = 0,
 349        .min            = 20,
 350        .max            = 100,
 351};
 352
 353/* DIMMs temperature (clamp the backside fan) */
 354static struct wf_pid_param dimms_param = {
 355        .interval       = 1,
 356        .history_len    = 20,
 357        .gd             = 0,
 358        .gp             = 0,
 359        .gr             = 0x06553600,
 360        .itarget        = 50 << 16,
 361        .additive       = 0,
 362        .min            = 4000,
 363        .max            = 14000,
 364};
 365
 366static void backside_fan_tick(void)
 367{
 368        s32 temp, dtemp;
 369        int speed, dspeed, fan_min;
 370        int err;
 371
 372        if (!backside_fan || !backside_temp || !dimms_temp || !backside_tick)
 373                return;
 374        if (--backside_tick > 0)
 375                return;
 376        backside_tick = backside_pid.param.interval;
 377
 378        DBG_LOTS("* backside fans tick\n");
 379
 380        /* Update fan speed from actual fans */
 381        err = wf_control_get(backside_fan, &speed);
 382        if (!err)
 383                backside_pid.target = speed;
 384
 385        err = wf_sensor_get(backside_temp, &temp);
 386        if (err) {
 387                printk(KERN_WARNING "windfarm: U3 temp sensor error %d\n",
 388                       err);
 389                failure_state |= FAILURE_SENSOR;
 390                wf_control_set_max(backside_fan);
 391                return;
 392        }
 393        speed = wf_pid_run(&backside_pid, temp);
 394
 395        DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
 396                 FIX32TOPRINT(temp), speed);
 397
 398        err = wf_sensor_get(dimms_temp, &dtemp);
 399        if (err) {
 400                printk(KERN_WARNING "windfarm: DIMMs temp sensor error %d\n",
 401                       err);
 402                failure_state |= FAILURE_SENSOR;
 403                wf_control_set_max(backside_fan);
 404                return;
 405        }
 406        dspeed = wf_pid_run(&dimms_pid, dtemp);
 407        dimms_output_clamp = dspeed;
 408
 409        fan_min = (dspeed * 100) / 14000;
 410        fan_min = max(fan_min, backside_param.min);
 411        speed = max(speed, fan_min);
 412
 413        err = wf_control_set(backside_fan, speed);
 414        if (err) {
 415                printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
 416                failure_state |= FAILURE_FAN;
 417        }
 418}
 419
 420static void backside_setup_pid(void)
 421{
 422        /* first time initialize things */
 423        s32 fmin = wf_control_get_min(backside_fan);
 424        s32 fmax = wf_control_get_max(backside_fan);
 425        struct wf_pid_param param;
 426
 427        param = backside_param;
 428        param.min = max(param.min, fmin);
 429        param.max = min(param.max, fmax);
 430        wf_pid_init(&backside_pid, &param);
 431
 432        param = dimms_param;
 433        wf_pid_init(&dimms_pid, &param);
 434
 435        backside_tick = 1;
 436
 437        pr_info("wf_rm31: Backside control loop started.\n");
 438}
 439
 440/* Slots fan */
 441static const struct wf_pid_param slots_param = {
 442        .interval       = 5,
 443        .history_len    = 2,
 444        .gd             = 30 << 20,
 445        .gp             = 5 << 20,
 446        .gr             = 0,
 447        .itarget        = 40 << 16,
 448        .additive       = 1,
 449        .min            = 300,
 450        .max            = 4000,
 451};
 452
 453static void slots_fan_tick(void)
 454{
 455        s32 temp;
 456        int speed;
 457        int err;
 458
 459        if (!slots_fan || !slots_temp || !slots_tick)
 460                return;
 461        if (--slots_tick > 0)
 462                return;
 463        slots_tick = slots_pid.param.interval;
 464
 465        DBG_LOTS("* slots fans tick\n");
 466
 467        err = wf_sensor_get(slots_temp, &temp);
 468        if (err) {
 469                pr_warning("wf_rm31: slots temp sensor error %d\n", err);
 470                failure_state |= FAILURE_SENSOR;
 471                wf_control_set_max(slots_fan);
 472                return;
 473        }
 474        speed = wf_pid_run(&slots_pid, temp);
 475
 476        DBG_LOTS("slots PID temp=%d.%.3d speed=%d\n",
 477                 FIX32TOPRINT(temp), speed);
 478
 479        slots_speed = speed;
 480        err = wf_control_set(slots_fan, speed);
 481        if (err) {
 482                printk(KERN_WARNING "windfarm: slots bay fan error %d\n", err);
 483                failure_state |= FAILURE_FAN;
 484        }
 485}
 486
 487static void slots_setup_pid(void)
 488{
 489        /* first time initialize things */
 490        s32 fmin = wf_control_get_min(slots_fan);
 491        s32 fmax = wf_control_get_max(slots_fan);
 492        struct wf_pid_param param = slots_param;
 493
 494        param.min = max(param.min, fmin);
 495        param.max = min(param.max, fmax);
 496        wf_pid_init(&slots_pid, &param);
 497        slots_tick = 1;
 498
 499        pr_info("wf_rm31: Slots control loop started.\n");
 500}
 501
 502static void set_fail_state(void)
 503{
 504        cpu_max_all_fans();
 505
 506        if (backside_fan)
 507                wf_control_set_max(backside_fan);
 508        if (slots_fan)
 509                wf_control_set_max(slots_fan);
 510}
 511
 512static void rm31_tick(void)
 513{
 514        int i, last_failure;
 515
 516        if (!started) {
 517                started = 1;
 518                printk(KERN_INFO "windfarm: CPUs control loops started.\n");
 519                for (i = 0; i < nr_chips; ++i) {
 520                        if (cpu_setup_pid(i) < 0) {
 521                                failure_state = FAILURE_PERM;
 522                                set_fail_state();
 523                                break;
 524                        }
 525                }
 526                DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
 527
 528                backside_setup_pid();
 529                slots_setup_pid();
 530
 531#ifdef HACKED_OVERTEMP
 532                cpu_all_tmax = 60 << 16;
 533#endif
 534        }
 535
 536        /* Permanent failure, bail out */
 537        if (failure_state & FAILURE_PERM)
 538                return;
 539
 540        /*
 541         * Clear all failure bits except low overtemp which will be eventually
 542         * cleared by the control loop itself
 543         */
 544        last_failure = failure_state;
 545        failure_state &= FAILURE_LOW_OVERTEMP;
 546        backside_fan_tick();
 547        slots_fan_tick();
 548
 549        /* We do CPUs last because they can be clamped high by
 550         * DIMM temperature
 551         */
 552        cpu_fans_tick();
 553
 554        DBG_LOTS("  last_failure: 0x%x, failure_state: %x\n",
 555                 last_failure, failure_state);
 556
 557        /* Check for failures. Any failure causes cpufreq clamping */
 558        if (failure_state && last_failure == 0 && cpufreq_clamp)
 559                wf_control_set_max(cpufreq_clamp);
 560        if (failure_state == 0 && last_failure && cpufreq_clamp)
 561                wf_control_set_min(cpufreq_clamp);
 562
 563        /* That's it for now, we might want to deal with other failures
 564         * differently in the future though
 565         */
 566}
 567
 568static void rm31_new_control(struct wf_control *ct)
 569{
 570        bool all_controls;
 571
 572        if (!strcmp(ct->name, "cpu-fan-a-0"))
 573                cpu_fans[0][0] = ct;
 574        else if (!strcmp(ct->name, "cpu-fan-b-0"))
 575                cpu_fans[0][1] = ct;
 576        else if (!strcmp(ct->name, "cpu-fan-c-0"))
 577                cpu_fans[0][2] = ct;
 578        else if (!strcmp(ct->name, "cpu-fan-a-1"))
 579                cpu_fans[1][0] = ct;
 580        else if (!strcmp(ct->name, "cpu-fan-b-1"))
 581                cpu_fans[1][1] = ct;
 582        else if (!strcmp(ct->name, "cpu-fan-c-1"))
 583                cpu_fans[1][2] = ct;
 584        else if (!strcmp(ct->name, "backside-fan"))
 585                backside_fan = ct;
 586        else if (!strcmp(ct->name, "slots-fan"))
 587                slots_fan = ct;
 588        else if (!strcmp(ct->name, "cpufreq-clamp"))
 589                cpufreq_clamp = ct;
 590
 591        all_controls =
 592                cpu_fans[0][0] &&
 593                cpu_fans[0][1] &&
 594                cpu_fans[0][2] &&
 595                backside_fan &&
 596                slots_fan;
 597        if (nr_chips > 1)
 598                all_controls &=
 599                        cpu_fans[1][0] &&
 600                        cpu_fans[1][1] &&
 601                        cpu_fans[1][2];
 602        have_all_controls = all_controls;
 603}
 604
 605
 606static void rm31_new_sensor(struct wf_sensor *sr)
 607{
 608        bool all_sensors;
 609
 610        if (!strcmp(sr->name, "cpu-diode-temp-0"))
 611                sens_cpu_temp[0] = sr;
 612        else if (!strcmp(sr->name, "cpu-diode-temp-1"))
 613                sens_cpu_temp[1] = sr;
 614        else if (!strcmp(sr->name, "cpu-voltage-0"))
 615                sens_cpu_volts[0] = sr;
 616        else if (!strcmp(sr->name, "cpu-voltage-1"))
 617                sens_cpu_volts[1] = sr;
 618        else if (!strcmp(sr->name, "cpu-current-0"))
 619                sens_cpu_amps[0] = sr;
 620        else if (!strcmp(sr->name, "cpu-current-1"))
 621                sens_cpu_amps[1] = sr;
 622        else if (!strcmp(sr->name, "backside-temp"))
 623                backside_temp = sr;
 624        else if (!strcmp(sr->name, "slots-temp"))
 625                slots_temp = sr;
 626        else if (!strcmp(sr->name, "dimms-temp"))
 627                dimms_temp = sr;
 628
 629        all_sensors =
 630                sens_cpu_temp[0] &&
 631                sens_cpu_volts[0] &&
 632                sens_cpu_amps[0] &&
 633                backside_temp &&
 634                slots_temp &&
 635                dimms_temp;
 636        if (nr_chips > 1)
 637                all_sensors &=
 638                        sens_cpu_temp[1] &&
 639                        sens_cpu_volts[1] &&
 640                        sens_cpu_amps[1];
 641
 642        have_all_sensors = all_sensors;
 643}
 644
 645static int rm31_wf_notify(struct notifier_block *self,
 646                          unsigned long event, void *data)
 647{
 648        switch (event) {
 649        case WF_EVENT_NEW_SENSOR:
 650                rm31_new_sensor(data);
 651                break;
 652        case WF_EVENT_NEW_CONTROL:
 653                rm31_new_control(data);
 654                break;
 655        case WF_EVENT_TICK:
 656                if (have_all_controls && have_all_sensors)
 657                        rm31_tick();
 658        }
 659        return 0;
 660}
 661
 662static struct notifier_block rm31_events = {
 663        .notifier_call = rm31_wf_notify,
 664};
 665
 666static int wf_rm31_probe(struct platform_device *dev)
 667{
 668        wf_register_client(&rm31_events);
 669        return 0;
 670}
 671
 672static int wf_rm31_remove(struct platform_device *dev)
 673{
 674        wf_unregister_client(&rm31_events);
 675
 676        /* should release all sensors and controls */
 677        return 0;
 678}
 679
 680static struct platform_driver wf_rm31_driver = {
 681        .probe  = wf_rm31_probe,
 682        .remove = wf_rm31_remove,
 683        .driver = {
 684                .name = "windfarm",
 685                .owner  = THIS_MODULE,
 686        },
 687};
 688
 689static int __init wf_rm31_init(void)
 690{
 691        struct device_node *cpu;
 692        int i;
 693
 694        if (!of_machine_is_compatible("RackMac3,1"))
 695                return -ENODEV;
 696
 697        /* Count the number of CPU cores */
 698        nr_chips = 0;
 699        for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
 700                ++nr_chips;
 701        if (nr_chips > NR_CHIPS)
 702                nr_chips = NR_CHIPS;
 703
 704        pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
 705                nr_chips);
 706
 707        /* Get MPU data for each CPU */
 708        for (i = 0; i < nr_chips; i++) {
 709                cpu_mpu_data[i] = wf_get_mpu(i);
 710                if (!cpu_mpu_data[i]) {
 711                        pr_err("wf_rm31: Failed to find MPU data for CPU %d\n", i);
 712                        return -ENXIO;
 713                }
 714        }
 715
 716#ifdef MODULE
 717        request_module("windfarm_fcu_controls");
 718        request_module("windfarm_lm75_sensor");
 719        request_module("windfarm_lm87_sensor");
 720        request_module("windfarm_ad7417_sensor");
 721        request_module("windfarm_max6690_sensor");
 722        request_module("windfarm_cpufreq_clamp");
 723#endif /* MODULE */
 724
 725        platform_driver_register(&wf_rm31_driver);
 726        return 0;
 727}
 728
 729static void __exit wf_rm31_exit(void)
 730{
 731        platform_driver_unregister(&wf_rm31_driver);
 732}
 733
 734module_init(wf_rm31_init);
 735module_exit(wf_rm31_exit);
 736
 737MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 738MODULE_DESCRIPTION("Thermal control for Xserve G5");
 739MODULE_LICENSE("GPL");
 740MODULE_ALIAS("platform:windfarm");
 741
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.