Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

Linux/drivers/macintosh/windfarm_rm31.c

  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 */
 49 static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
 50 static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
 51 static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
 52 static struct wf_sensor *backside_temp;
 53 static struct wf_sensor *slots_temp;
 54 static struct wf_sensor *dimms_temp;
 55 
 56 static struct wf_control *cpu_fans[NR_CHIPS][3];
 57 static struct wf_control *backside_fan;
 58 static struct wf_control *slots_fan;
 59 static 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 */
 65 static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
 66 static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
 67 static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
 68 static int cpu_thist_pt;
 69 static s64 cpu_thist_total;
 70 static s32 cpu_all_tmax = 100 << 16;
 71 static struct wf_pid_state backside_pid;
 72 static int backside_tick;
 73 static struct wf_pid_state slots_pid;
 74 static int slots_tick;
 75 static int slots_speed;
 76 static struct wf_pid_state dimms_pid;
 77 static int dimms_output_clamp;
 78 
 79 static int nr_chips;
 80 static bool have_all_controls;
 81 static bool have_all_sensors;
 82 static bool started;
 83 
 84 static 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 
100 static 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 
120 static 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 
203 static 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 
246 static 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... */
294 static 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 */
341 static 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) */
354 static 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 
366 static 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 
420 static 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 */
441 static const struct wf_pid_param slots_param = {
442         .interval       = 1,
443         .history_len    = 20,
444         .gd             = 0,
445         .gp             = 0,
446         .gr             = 0x00100000,
447         .itarget        = 3200000,
448         .additive       = 0,
449         .min            = 20,
450         .max            = 100,
451 };
452 
453 static 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 
487 static 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 
502 static 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 
512 static 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 
568 static 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 
606 static 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 
645 static 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 
662 static struct notifier_block rm31_events = {
663         .notifier_call = rm31_wf_notify,
664 };
665 
666 static int wf_rm31_probe(struct platform_device *dev)
667 {
668         wf_register_client(&rm31_events);
669         return 0;
670 }
671 
672 static 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 
680 static 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 
689 static 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_each_node_by_type(cpu, "cpu")
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 
729 static void __exit wf_rm31_exit(void)
730 {
731         platform_driver_unregister(&wf_rm31_driver);
732 }
733 
734 module_init(wf_rm31_init);
735 module_exit(wf_rm31_exit);
736 
737 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
738 MODULE_DESCRIPTION("Thermal control for Xserve G5");
739 MODULE_LICENSE("GPL");
740 MODULE_ALIAS("platform:windfarm");
741 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us