aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh/windfarm_pm72.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-04-29 11:42:27 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-04-30 01:37:25 -0400
commit6cd3209967469f6e89d329deda6bb0b4700e7b62 (patch)
tree35f099b364bf811b44fa11c7d71eaa7b22d264a1 /drivers/macintosh/windfarm_pm72.c
parenta78a4a03a75466ff859d989a1a00110ebd0165b0 (diff)
powerpc/powermac: New windfarm driver for PowerMac G5 (AGP) and Xserve G5
This replaces the old therm_pm72 using the same windfarm infrastructure that was used for other PowerMac G5 models. The fan speeds and sensors should now be visible in the same location in sysfs. The driver is split into separate core modules for PowerMac7,2 (and 7,3) and RackMac3,1, with a lot of the shared code now in the separate sensor and control modules. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/macintosh/windfarm_pm72.c')
-rw-r--r--drivers/macintosh/windfarm_pm72.c847
1 files changed, 847 insertions, 0 deletions
diff --git a/drivers/macintosh/windfarm_pm72.c b/drivers/macintosh/windfarm_pm72.c
new file mode 100644
index 000000000000..84ac913d7e3a
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm72.c
@@ -0,0 +1,847 @@
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");