Root/drivers/macintosh/windfarm_pm72.c

1/*
2 * Windfarm PowerMac thermal control.
3 * Control loops for PowerMac7,2 and 7,3
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 *drives_temp;
54
55static struct wf_control *cpu_front_fans[NR_CHIPS];
56static struct wf_control *cpu_rear_fans[NR_CHIPS];
57static struct wf_control *cpu_pumps[NR_CHIPS];
58static struct wf_control *backside_fan;
59static struct wf_control *drives_fan;
60static struct wf_control *slots_fan;
61static struct wf_control *cpufreq_clamp;
62
63/* We keep a temperature history for average calculation of 180s */
64#define CPU_TEMP_HIST_SIZE 180
65
66/* Fixed speed for slot fan */
67#define SLOTS_FAN_DEFAULT_PWM 40
68
69/* Scale value for CPU intake fans */
70#define CPU_INTAKE_SCALE 0x0000f852
71
72/* PID loop state */
73static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
74static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
75static bool cpu_pid_combined;
76static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
77static int cpu_thist_pt;
78static s64 cpu_thist_total;
79static s32 cpu_all_tmax = 100 << 16;
80static struct wf_pid_state backside_pid;
81static int backside_tick;
82static struct wf_pid_state drives_pid;
83static int drives_tick;
84
85static int nr_chips;
86static bool have_all_controls;
87static bool have_all_sensors;
88static bool started;
89
90static int failure_state;
91#define FAILURE_SENSOR 1
92#define FAILURE_FAN 2
93#define FAILURE_PERM 4
94#define FAILURE_LOW_OVERTEMP 8
95#define FAILURE_HIGH_OVERTEMP 16
96
97/* Overtemp values */
98#define LOW_OVER_AVERAGE 0
99#define LOW_OVER_IMMEDIATE (10 << 16)
100#define LOW_OVER_CLEAR ((-10) << 16)
101#define HIGH_OVER_IMMEDIATE (14 << 16)
102#define HIGH_OVER_AVERAGE (10 << 16)
103#define HIGH_OVER_IMMEDIATE (14 << 16)
104
105
106static void cpu_max_all_fans(void)
107{
108    int i;
109
110    /* We max all CPU fans in case of a sensor error. We also do the
111     * cpufreq clamping now, even if it's supposedly done later by the
112     * generic code anyway, we do it earlier here to react faster
113     */
114    if (cpufreq_clamp)
115        wf_control_set_max(cpufreq_clamp);
116    for (i = 0; i < nr_chips; i++) {
117        if (cpu_front_fans[i])
118            wf_control_set_max(cpu_front_fans[i]);
119        if (cpu_rear_fans[i])
120            wf_control_set_max(cpu_rear_fans[i]);
121        if (cpu_pumps[i])
122            wf_control_set_max(cpu_pumps[i]);
123    }
124}
125
126static int cpu_check_overtemp(s32 temp)
127{
128    int new_state = 0;
129    s32 t_avg, t_old;
130    static bool first = true;
131
132    /* First check for immediate overtemps */
133    if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
134        new_state |= FAILURE_LOW_OVERTEMP;
135        if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
136            printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
137                   " temperature !\n");
138    }
139    if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
140        new_state |= FAILURE_HIGH_OVERTEMP;
141        if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
142            printk(KERN_ERR "windfarm: Critical overtemp due to"
143                   " immediate CPU temperature !\n");
144    }
145
146    /*
147     * The first time around, initialize the array with the first
148     * temperature reading
149     */
150    if (first) {
151        int i;
152
153        cpu_thist_total = 0;
154        for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
155            cpu_thist[i] = temp;
156            cpu_thist_total += temp;
157        }
158        first = false;
159    }
160
161    /*
162     * We calculate a history of max temperatures and use that for the
163     * overtemp management
164     */
165    t_old = cpu_thist[cpu_thist_pt];
166    cpu_thist[cpu_thist_pt] = temp;
167    cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
168    cpu_thist_total -= t_old;
169    cpu_thist_total += temp;
170    t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
171
172    DBG_LOTS(" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
173         FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
174
175    /* Now check for average overtemps */
176    if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
177        new_state |= FAILURE_LOW_OVERTEMP;
178        if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
179            printk(KERN_ERR "windfarm: Overtemp due to average CPU"
180                   " temperature !\n");
181    }
182    if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
183        new_state |= FAILURE_HIGH_OVERTEMP;
184        if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
185            printk(KERN_ERR "windfarm: Critical overtemp due to"
186                   " average CPU temperature !\n");
187    }
188
189    /* Now handle overtemp conditions. We don't currently use the windfarm
190     * overtemp handling core as it's not fully suited to the needs of those
191     * new machine. This will be fixed later.
192     */
193    if (new_state) {
194        /* High overtemp -> immediate shutdown */
195        if (new_state & FAILURE_HIGH_OVERTEMP)
196            machine_power_off();
197        if ((failure_state & new_state) != new_state)
198            cpu_max_all_fans();
199        failure_state |= new_state;
200    } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
201           (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
202        printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
203        failure_state &= ~FAILURE_LOW_OVERTEMP;
204    }
205
206    return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
207}
208
209static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
210{
211    s32 dtemp, volts, amps;
212    int rc;
213
214    /* Get diode temperature */
215    rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
216    if (rc) {
217        DBG(" CPU%d: temp reading error !\n", cpu);
218        return -EIO;
219    }
220    DBG_LOTS(" CPU%d: temp = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
221    *temp = dtemp;
222
223    /* Get voltage */
224    rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
225    if (rc) {
226        DBG(" CPU%d, volts reading error !\n", cpu);
227        return -EIO;
228    }
229    DBG_LOTS(" CPU%d: volts = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
230
231    /* Get current */
232    rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
233    if (rc) {
234        DBG(" CPU%d, current reading error !\n", cpu);
235        return -EIO;
236    }
237    DBG_LOTS(" CPU%d: amps = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
238
239    /* Calculate power */
240
241    /* Scale voltage and current raw sensor values according to fixed scales
242     * obtained in Darwin and calculate power from I and V
243     */
244    *power = (((u64)volts) * ((u64)amps)) >> 16;
245
246    DBG_LOTS(" CPU%d: power = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
247
248    return 0;
249
250}
251
252static void cpu_fans_tick_split(void)
253{
254    int err, cpu;
255    s32 intake, temp, power, t_max = 0;
256
257    DBG_LOTS("* cpu fans_tick_split()\n");
258
259    for (cpu = 0; cpu < nr_chips; ++cpu) {
260        struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
261
262        /* Read current speed */
263        wf_control_get(cpu_rear_fans[cpu], &sp->target);
264
265        DBG_LOTS(" CPU%d: cur_target = %d RPM\n", cpu, sp->target);
266
267        err = read_one_cpu_vals(cpu, &temp, &power);
268        if (err) {
269            failure_state |= FAILURE_SENSOR;
270            cpu_max_all_fans();
271            return;
272        }
273
274        /* Keep track of highest temp */
275        t_max = max(t_max, temp);
276
277        /* Handle possible overtemps */
278        if (cpu_check_overtemp(t_max))
279            return;
280
281        /* Run PID */
282        wf_cpu_pid_run(sp, power, temp);
283
284        DBG_LOTS(" CPU%d: target = %d RPM\n", cpu, sp->target);
285
286        /* Apply result directly to exhaust fan */
287        err = wf_control_set(cpu_rear_fans[cpu], sp->target);
288        if (err) {
289            pr_warning("wf_pm72: Fan %s reports error %d\n",
290                   cpu_rear_fans[cpu]->name, err);
291            failure_state |= FAILURE_FAN;
292            break;
293        }
294
295        /* Scale result for intake fan */
296        intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
297        DBG_LOTS(" CPU%d: intake = %d RPM\n", cpu, intake);
298        err = wf_control_set(cpu_front_fans[cpu], intake);
299        if (err) {
300            pr_warning("wf_pm72: Fan %s reports error %d\n",
301                   cpu_front_fans[cpu]->name, err);
302            failure_state |= FAILURE_FAN;
303            break;
304        }
305    }
306}
307
308static void cpu_fans_tick_combined(void)
309{
310    s32 temp0, power0, temp1, power1, t_max = 0;
311    s32 temp, power, intake, pump;
312    struct wf_control *pump0, *pump1;
313    struct wf_cpu_pid_state *sp = &cpu_pid[0];
314    int err, cpu;
315
316    DBG_LOTS("* cpu fans_tick_combined()\n");
317
318    /* Read current speed from cpu 0 */
319    wf_control_get(cpu_rear_fans[0], &sp->target);
320
321    DBG_LOTS(" CPUs: cur_target = %d RPM\n", sp->target);
322
323    /* Read values for both CPUs */
324    err = read_one_cpu_vals(0, &temp0, &power0);
325    if (err) {
326        failure_state |= FAILURE_SENSOR;
327        cpu_max_all_fans();
328        return;
329    }
330    err = read_one_cpu_vals(1, &temp1, &power1);
331    if (err) {
332        failure_state |= FAILURE_SENSOR;
333        cpu_max_all_fans();
334        return;
335    }
336
337    /* Keep track of highest temp */
338    t_max = max(t_max, max(temp0, temp1));
339
340    /* Handle possible overtemps */
341    if (cpu_check_overtemp(t_max))
342        return;
343
344    /* Use the max temp & power of both */
345    temp = max(temp0, temp1);
346    power = max(power0, power1);
347
348    /* Run PID */
349    wf_cpu_pid_run(sp, power, temp);
350
351    /* Scale result for intake fan */
352    intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
353
354    /* Same deal with pump speed */
355    pump0 = cpu_pumps[0];
356    pump1 = cpu_pumps[1];
357    if (!pump0) {
358        pump0 = pump1;
359        pump1 = NULL;
360    }
361    pump = (sp->target * wf_control_get_max(pump0)) /
362        cpu_mpu_data[0]->rmaxn_exhaust_fan;
363
364    DBG_LOTS(" CPUs: target = %d RPM\n", sp->target);
365    DBG_LOTS(" CPUs: intake = %d RPM\n", intake);
366    DBG_LOTS(" CPUs: pump = %d RPM\n", pump);
367
368    for (cpu = 0; cpu < nr_chips; cpu++) {
369        err = wf_control_set(cpu_rear_fans[cpu], sp->target);
370        if (err) {
371            pr_warning("wf_pm72: Fan %s reports error %d\n",
372                   cpu_rear_fans[cpu]->name, err);
373            failure_state |= FAILURE_FAN;
374        }
375        err = wf_control_set(cpu_front_fans[cpu], intake);
376        if (err) {
377            pr_warning("wf_pm72: Fan %s reports error %d\n",
378                   cpu_front_fans[cpu]->name, err);
379            failure_state |= FAILURE_FAN;
380        }
381        err = 0;
382        if (cpu_pumps[cpu])
383            err = wf_control_set(cpu_pumps[cpu], pump);
384        if (err) {
385            pr_warning("wf_pm72: Pump %s reports error %d\n",
386                   cpu_pumps[cpu]->name, err);
387            failure_state |= FAILURE_FAN;
388        }
389    }
390}
391
392/* Implementation... */
393static int cpu_setup_pid(int cpu)
394{
395    struct wf_cpu_pid_param pid;
396    const struct mpu_data *mpu = cpu_mpu_data[cpu];
397    s32 tmax, ttarget, ptarget;
398    int fmin, fmax, hsize;
399
400    /* Get PID params from the appropriate MPU EEPROM */
401    tmax = mpu->tmax << 16;
402    ttarget = mpu->ttarget << 16;
403    ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
404
405    DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
406        cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
407
408    /* We keep a global tmax for overtemp calculations */
409    if (tmax < cpu_all_tmax)
410        cpu_all_tmax = tmax;
411
412    /* Set PID min/max by using the rear fan min/max */
413    fmin = wf_control_get_min(cpu_rear_fans[cpu]);
414    fmax = wf_control_get_max(cpu_rear_fans[cpu]);
415    DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
416
417    /* History size */
418    hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
419    DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
420
421    /* Initialize PID loop */
422    pid.interval = 1; /* seconds */
423    pid.history_len = hsize;
424    pid.gd = mpu->pid_gd;
425    pid.gp = mpu->pid_gp;
426    pid.gr = mpu->pid_gr;
427    pid.tmax = tmax;
428    pid.ttarget = ttarget;
429    pid.pmaxadj = ptarget;
430    pid.min = fmin;
431    pid.max = fmax;
432
433    wf_cpu_pid_init(&cpu_pid[cpu], &pid);
434    cpu_pid[cpu].target = 1000;
435
436    return 0;
437}
438
439/* Backside/U3 fan */
440static struct wf_pid_param backside_u3_param = {
441    .interval = 5,
442    .history_len = 2,
443    .gd = 40 << 20,
444    .gp = 5 << 20,
445    .gr = 0,
446    .itarget = 65 << 16,
447    .additive = 1,
448    .min = 20,
449    .max = 100,
450};
451
452static struct wf_pid_param backside_u3h_param = {
453    .interval = 5,
454    .history_len = 2,
455    .gd = 20 << 20,
456    .gp = 5 << 20,
457    .gr = 0,
458    .itarget = 75 << 16,
459    .additive = 1,
460    .min = 20,
461    .max = 100,
462};
463
464static void backside_fan_tick(void)
465{
466    s32 temp;
467    int speed;
468    int err;
469
470    if (!backside_fan || !backside_temp || !backside_tick)
471        return;
472    if (--backside_tick > 0)
473        return;
474    backside_tick = backside_pid.param.interval;
475
476    DBG_LOTS("* backside fans tick\n");
477
478    /* Update fan speed from actual fans */
479    err = wf_control_get(backside_fan, &speed);
480    if (!err)
481        backside_pid.target = speed;
482
483    err = wf_sensor_get(backside_temp, &temp);
484    if (err) {
485        printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
486               err);
487        failure_state |= FAILURE_SENSOR;
488        wf_control_set_max(backside_fan);
489        return;
490    }
491    speed = wf_pid_run(&backside_pid, temp);
492
493    DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
494         FIX32TOPRINT(temp), speed);
495
496    err = wf_control_set(backside_fan, speed);
497    if (err) {
498        printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
499        failure_state |= FAILURE_FAN;
500    }
501}
502
503static void backside_setup_pid(void)
504{
505    /* first time initialize things */
506    s32 fmin = wf_control_get_min(backside_fan);
507    s32 fmax = wf_control_get_max(backside_fan);
508    struct wf_pid_param param;
509    struct device_node *u3;
510    int u3h = 1; /* conservative by default */
511
512    u3 = of_find_node_by_path("/u3@0,f8000000");
513    if (u3 != NULL) {
514        const u32 *vers = of_get_property(u3, "device-rev", NULL);
515        if (vers)
516            if (((*vers) & 0x3f) < 0x34)
517                u3h = 0;
518        of_node_put(u3);
519    }
520
521    param = u3h ? backside_u3h_param : backside_u3_param;
522
523    param.min = max(param.min, fmin);
524    param.max = min(param.max, fmax);
525    wf_pid_init(&backside_pid, &param);
526    backside_tick = 1;
527
528    pr_info("wf_pm72: Backside control loop started.\n");
529}
530
531/* Drive bay fan */
532static const struct wf_pid_param drives_param = {
533    .interval = 5,
534    .history_len = 2,
535    .gd = 30 << 20,
536    .gp = 5 << 20,
537    .gr = 0,
538    .itarget = 40 << 16,
539    .additive = 1,
540    .min = 300,
541    .max = 4000,
542};
543
544static void drives_fan_tick(void)
545{
546    s32 temp;
547    int speed;
548    int err;
549
550    if (!drives_fan || !drives_temp || !drives_tick)
551        return;
552    if (--drives_tick > 0)
553        return;
554    drives_tick = drives_pid.param.interval;
555
556    DBG_LOTS("* drives fans tick\n");
557
558    /* Update fan speed from actual fans */
559    err = wf_control_get(drives_fan, &speed);
560    if (!err)
561        drives_pid.target = speed;
562
563    err = wf_sensor_get(drives_temp, &temp);
564    if (err) {
565        pr_warning("wf_pm72: drive bay temp sensor error %d\n", err);
566        failure_state |= FAILURE_SENSOR;
567        wf_control_set_max(drives_fan);
568        return;
569    }
570    speed = wf_pid_run(&drives_pid, temp);
571
572    DBG_LOTS("drives PID temp=%d.%.3d speed=%d\n",
573         FIX32TOPRINT(temp), speed);
574
575    err = wf_control_set(drives_fan, speed);
576    if (err) {
577        printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
578        failure_state |= FAILURE_FAN;
579    }
580}
581
582static void drives_setup_pid(void)
583{
584    /* first time initialize things */
585    s32 fmin = wf_control_get_min(drives_fan);
586    s32 fmax = wf_control_get_max(drives_fan);
587    struct wf_pid_param param = drives_param;
588
589    param.min = max(param.min, fmin);
590    param.max = min(param.max, fmax);
591    wf_pid_init(&drives_pid, &param);
592    drives_tick = 1;
593
594    pr_info("wf_pm72: Drive bay control loop started.\n");
595}
596
597static void set_fail_state(void)
598{
599    cpu_max_all_fans();
600
601    if (backside_fan)
602        wf_control_set_max(backside_fan);
603    if (slots_fan)
604        wf_control_set_max(slots_fan);
605    if (drives_fan)
606        wf_control_set_max(drives_fan);
607}
608
609static void pm72_tick(void)
610{
611    int i, last_failure;
612
613    if (!started) {
614        started = 1;
615        printk(KERN_INFO "windfarm: CPUs control loops started.\n");
616        for (i = 0; i < nr_chips; ++i) {
617            if (cpu_setup_pid(i) < 0) {
618                failure_state = FAILURE_PERM;
619                set_fail_state();
620                break;
621            }
622        }
623        DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
624
625        backside_setup_pid();
626        drives_setup_pid();
627
628        /*
629         * We don't have the right stuff to drive the PCI fan
630         * so we fix it to a default value
631         */
632        wf_control_set(slots_fan, SLOTS_FAN_DEFAULT_PWM);
633
634#ifdef HACKED_OVERTEMP
635        cpu_all_tmax = 60 << 16;
636#endif
637    }
638
639    /* Permanent failure, bail out */
640    if (failure_state & FAILURE_PERM)
641        return;
642
643    /*
644     * Clear all failure bits except low overtemp which will be eventually
645     * cleared by the control loop itself
646     */
647    last_failure = failure_state;
648    failure_state &= FAILURE_LOW_OVERTEMP;
649    if (cpu_pid_combined)
650        cpu_fans_tick_combined();
651    else
652        cpu_fans_tick_split();
653    backside_fan_tick();
654    drives_fan_tick();
655
656    DBG_LOTS(" last_failure: 0x%x, failure_state: %x\n",
657         last_failure, failure_state);
658
659    /* Check for failures. Any failure causes cpufreq clamping */
660    if (failure_state && last_failure == 0 && cpufreq_clamp)
661        wf_control_set_max(cpufreq_clamp);
662    if (failure_state == 0 && last_failure && cpufreq_clamp)
663        wf_control_set_min(cpufreq_clamp);
664
665    /* That's it for now, we might want to deal with other failures
666     * differently in the future though
667     */
668}
669
670static void pm72_new_control(struct wf_control *ct)
671{
672    bool all_controls;
673    bool had_pump = cpu_pumps[0] || cpu_pumps[1];
674
675    if (!strcmp(ct->name, "cpu-front-fan-0"))
676        cpu_front_fans[0] = ct;
677    else if (!strcmp(ct->name, "cpu-front-fan-1"))
678        cpu_front_fans[1] = ct;
679    else if (!strcmp(ct->name, "cpu-rear-fan-0"))
680        cpu_rear_fans[0] = ct;
681    else if (!strcmp(ct->name, "cpu-rear-fan-1"))
682        cpu_rear_fans[1] = ct;
683    else if (!strcmp(ct->name, "cpu-pump-0"))
684        cpu_pumps[0] = ct;
685    else if (!strcmp(ct->name, "cpu-pump-1"))
686        cpu_pumps[1] = ct;
687    else if (!strcmp(ct->name, "backside-fan"))
688        backside_fan = ct;
689    else if (!strcmp(ct->name, "slots-fan"))
690        slots_fan = ct;
691    else if (!strcmp(ct->name, "drive-bay-fan"))
692        drives_fan = ct;
693    else if (!strcmp(ct->name, "cpufreq-clamp"))
694        cpufreq_clamp = ct;
695
696    all_controls =
697        cpu_front_fans[0] &&
698        cpu_rear_fans[0] &&
699        backside_fan &&
700        slots_fan &&
701        drives_fan;
702    if (nr_chips > 1)
703        all_controls &=
704            cpu_front_fans[1] &&
705            cpu_rear_fans[1];
706    have_all_controls = all_controls;
707
708    if ((cpu_pumps[0] || cpu_pumps[1]) && !had_pump) {
709        pr_info("wf_pm72: Liquid cooling pump(s) detected,"
710            " using new algorithm !\n");
711        cpu_pid_combined = true;
712    }
713}
714
715
716static void pm72_new_sensor(struct wf_sensor *sr)
717{
718    bool all_sensors;
719
720    if (!strcmp(sr->name, "cpu-diode-temp-0"))
721        sens_cpu_temp[0] = sr;
722    else if (!strcmp(sr->name, "cpu-diode-temp-1"))
723        sens_cpu_temp[1] = sr;
724    else if (!strcmp(sr->name, "cpu-voltage-0"))
725        sens_cpu_volts[0] = sr;
726    else if (!strcmp(sr->name, "cpu-voltage-1"))
727        sens_cpu_volts[1] = sr;
728    else if (!strcmp(sr->name, "cpu-current-0"))
729        sens_cpu_amps[0] = sr;
730    else if (!strcmp(sr->name, "cpu-current-1"))
731        sens_cpu_amps[1] = sr;
732    else if (!strcmp(sr->name, "backside-temp"))
733        backside_temp = sr;
734    else if (!strcmp(sr->name, "hd-temp"))
735        drives_temp = sr;
736
737    all_sensors =
738        sens_cpu_temp[0] &&
739        sens_cpu_volts[0] &&
740        sens_cpu_amps[0] &&
741        backside_temp &&
742        drives_temp;
743    if (nr_chips > 1)
744        all_sensors &=
745            sens_cpu_temp[1] &&
746            sens_cpu_volts[1] &&
747            sens_cpu_amps[1];
748
749    have_all_sensors = all_sensors;
750}
751
752static int pm72_wf_notify(struct notifier_block *self,
753              unsigned long event, void *data)
754{
755    switch (event) {
756    case WF_EVENT_NEW_SENSOR:
757        pm72_new_sensor(data);
758        break;
759    case WF_EVENT_NEW_CONTROL:
760        pm72_new_control(data);
761        break;
762    case WF_EVENT_TICK:
763        if (have_all_controls && have_all_sensors)
764            pm72_tick();
765    }
766    return 0;
767}
768
769static struct notifier_block pm72_events = {
770    .notifier_call = pm72_wf_notify,
771};
772
773static int wf_pm72_probe(struct platform_device *dev)
774{
775    wf_register_client(&pm72_events);
776    return 0;
777}
778
779static int __devexit wf_pm72_remove(struct platform_device *dev)
780{
781    wf_unregister_client(&pm72_events);
782
783    /* should release all sensors and controls */
784    return 0;
785}
786
787static struct platform_driver wf_pm72_driver = {
788    .probe = wf_pm72_probe,
789    .remove = wf_pm72_remove,
790    .driver = {
791        .name = "windfarm",
792        .owner = THIS_MODULE,
793    },
794};
795
796static int __init wf_pm72_init(void)
797{
798    struct device_node *cpu;
799    int i;
800
801    if (!of_machine_is_compatible("PowerMac7,2") &&
802        !of_machine_is_compatible("PowerMac7,3"))
803        return -ENODEV;
804
805    /* Count the number of CPU cores */
806    nr_chips = 0;
807    for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
808        ++nr_chips;
809    if (nr_chips > NR_CHIPS)
810        nr_chips = NR_CHIPS;
811
812    pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
813        nr_chips);
814
815    /* Get MPU data for each CPU */
816    for (i = 0; i < nr_chips; i++) {
817        cpu_mpu_data[i] = wf_get_mpu(i);
818        if (!cpu_mpu_data[i]) {
819            pr_err("wf_pm72: Failed to find MPU data for CPU %d\n", i);
820            return -ENXIO;
821        }
822    }
823
824#ifdef MODULE
825    request_module("windfarm_fcu_controls");
826    request_module("windfarm_lm75_sensor");
827    request_module("windfarm_ad7417_sensor");
828    request_module("windfarm_max6690_sensor");
829    request_module("windfarm_cpufreq_clamp");
830#endif /* MODULE */
831
832    platform_driver_register(&wf_pm72_driver);
833    return 0;
834}
835
836static void __exit wf_pm72_exit(void)
837{
838    platform_driver_unregister(&wf_pm72_driver);
839}
840
841module_init(wf_pm72_init);
842module_exit(wf_pm72_exit);
843
844MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
845MODULE_DESCRIPTION("Thermal control for AGP PowerMac G5s");
846MODULE_LICENSE("GPL");
847MODULE_ALIAS("platform:windfarm");
848

Archive Download this file



interactive