GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / macintosh / windfarm_pm91.c
1 /*
2  * Windfarm PowerMac thermal control. SMU based 1 CPU desktop control loops
3  *
4  * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
5  *                    <benh@kernel.crashing.org>
6  *
7  * Released under the term of the GNU GPL v2.
8  *
9  * The algorithm used is the PID control algorithm, used the same
10  * way the published Darwin code does, using the same values that
11  * are present in the Darwin 8.2 snapshot property lists (note however
12  * that none of the code has been re-used, it's a complete re-implementation
13  *
14  * The various control loops found in Darwin config file are:
15  *
16  * PowerMac9,1
17  * ===========
18  *
19  * Has 3 control loops: CPU fans is similar to PowerMac8,1 (though it doesn't
20  * try to play with other control loops fans). Drive bay is rather basic PID
21  * with one sensor and one fan. Slots area is a bit different as the Darwin
22  * driver is supposed to be capable of working in a special "AGP" mode which
23  * involves the presence of an AGP sensor and an AGP fan (possibly on the
24  * AGP card itself). I can't deal with that special mode as I don't have
25  * access to those additional sensor/fans for now (though ultimately, it would
26  * be possible to add sensor objects for them) so I'm only implementing the
27  * basic PCI slot control loop
28  */
29
30 #include <linux/types.h>
31 #include <linux/errno.h>
32 #include <linux/kernel.h>
33 #include <linux/delay.h>
34 #include <linux/slab.h>
35 #include <linux/init.h>
36 #include <linux/spinlock.h>
37 #include <linux/wait.h>
38 #include <linux/kmod.h>
39 #include <linux/device.h>
40 #include <linux/platform_device.h>
41 #include <asm/prom.h>
42 #include <asm/machdep.h>
43 #include <asm/io.h>
44 #include <asm/sections.h>
45 #include <asm/smu.h>
46
47 #include "windfarm.h"
48 #include "windfarm_pid.h"
49
50 #define VERSION "0.4"
51
52 #undef DEBUG
53
54 #ifdef DEBUG
55 #define DBG(args...)    printk(args)
56 #else
57 #define DBG(args...)    do { } while(0)
58 #endif
59
60 /* define this to force CPU overtemp to 74 degree, useful for testing
61  * the overtemp code
62  */
63 #undef HACKED_OVERTEMP
64
65 /* Controls & sensors */
66 static struct wf_sensor *sensor_cpu_power;
67 static struct wf_sensor *sensor_cpu_temp;
68 static struct wf_sensor *sensor_hd_temp;
69 static struct wf_sensor *sensor_slots_power;
70 static struct wf_control *fan_cpu_main;
71 static struct wf_control *fan_cpu_second;
72 static struct wf_control *fan_cpu_third;
73 static struct wf_control *fan_hd;
74 static struct wf_control *fan_slots;
75 static struct wf_control *cpufreq_clamp;
76
77 /* Set to kick the control loop into life */
78 static int wf_smu_all_controls_ok, wf_smu_all_sensors_ok;
79 static bool wf_smu_started;
80 static bool wf_smu_overtemp;
81
82 /* Failure handling.. could be nicer */
83 #define FAILURE_FAN             0x01
84 #define FAILURE_SENSOR          0x02
85 #define FAILURE_OVERTEMP        0x04
86
87 static unsigned int wf_smu_failure_state;
88 static int wf_smu_readjust, wf_smu_skipping;
89
90 /*
91  * ****** CPU Fans Control Loop ******
92  *
93  */
94
95
96 #define WF_SMU_CPU_FANS_INTERVAL        1
97 #define WF_SMU_CPU_FANS_MAX_HISTORY     16
98
99 /* State data used by the cpu fans control loop
100  */
101 struct wf_smu_cpu_fans_state {
102         int                     ticks;
103         s32                     cpu_setpoint;
104         struct wf_cpu_pid_state pid;
105 };
106
107 static struct wf_smu_cpu_fans_state *wf_smu_cpu_fans;
108
109
110
111 /*
112  * ****** Drive Fan Control Loop ******
113  *
114  */
115
116 struct wf_smu_drive_fans_state {
117         int                     ticks;
118         s32                     setpoint;
119         struct wf_pid_state     pid;
120 };
121
122 static struct wf_smu_drive_fans_state *wf_smu_drive_fans;
123
124 /*
125  * ****** Slots Fan Control Loop ******
126  *
127  */
128
129 struct wf_smu_slots_fans_state {
130         int                     ticks;
131         s32                     setpoint;
132         struct wf_pid_state     pid;
133 };
134
135 static struct wf_smu_slots_fans_state *wf_smu_slots_fans;
136
137 /*
138  * ***** Implementation *****
139  *
140  */
141
142
143 static void wf_smu_create_cpu_fans(void)
144 {
145         struct wf_cpu_pid_param pid_param;
146         const struct smu_sdbp_header *hdr;
147         struct smu_sdbp_cpupiddata *piddata;
148         struct smu_sdbp_fvt *fvt;
149         s32 tmax, tdelta, maxpow, powadj;
150
151         /* First, locate the PID params in SMU SBD */
152         hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
153         if (hdr == 0) {
154                 printk(KERN_WARNING "windfarm: CPU PID fan config not found "
155                        "max fan speed\n");
156                 goto fail;
157         }
158         piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
159
160         /* Get the FVT params for operating point 0 (the only supported one
161          * for now) in order to get tmax
162          */
163         hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
164         if (hdr) {
165                 fvt = (struct smu_sdbp_fvt *)&hdr[1];
166                 tmax = ((s32)fvt->maxtemp) << 16;
167         } else
168                 tmax = 0x5e0000; /* 94 degree default */
169
170         /* Alloc & initialize state */
171         wf_smu_cpu_fans = kmalloc(sizeof(struct wf_smu_cpu_fans_state),
172                                   GFP_KERNEL);
173         if (wf_smu_cpu_fans == NULL)
174                 goto fail;
175         wf_smu_cpu_fans->ticks = 1;
176
177         /* Fill PID params */
178         pid_param.interval = WF_SMU_CPU_FANS_INTERVAL;
179         pid_param.history_len = piddata->history_len;
180         if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
181                 printk(KERN_WARNING "windfarm: History size overflow on "
182                        "CPU control loop (%d)\n", piddata->history_len);
183                 pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
184         }
185         pid_param.gd = piddata->gd;
186         pid_param.gp = piddata->gp;
187         pid_param.gr = piddata->gr / pid_param.history_len;
188
189         tdelta = ((s32)piddata->target_temp_delta) << 16;
190         maxpow = ((s32)piddata->max_power) << 16;
191         powadj = ((s32)piddata->power_adj) << 16;
192
193         pid_param.tmax = tmax;
194         pid_param.ttarget = tmax - tdelta;
195         pid_param.pmaxadj = maxpow - powadj;
196
197         pid_param.min = wf_control_get_min(fan_cpu_main);
198         pid_param.max = wf_control_get_max(fan_cpu_main);
199
200         wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param);
201
202         DBG("wf: CPU Fan control initialized.\n");
203         DBG("    ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n",
204             FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
205             pid_param.min, pid_param.max);
206
207         return;
208
209  fail:
210         printk(KERN_WARNING "windfarm: CPU fan config not found\n"
211                "for this machine model, max fan speed\n");
212
213         if (cpufreq_clamp)
214                 wf_control_set_max(cpufreq_clamp);
215         if (fan_cpu_main)
216                 wf_control_set_max(fan_cpu_main);
217 }
218
219 static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
220 {
221         s32 new_setpoint, temp, power;
222         int rc;
223
224         if (--st->ticks != 0) {
225                 if (wf_smu_readjust)
226                         goto readjust;
227                 return;
228         }
229         st->ticks = WF_SMU_CPU_FANS_INTERVAL;
230
231         rc = wf_sensor_get(sensor_cpu_temp, &temp);
232         if (rc) {
233                 printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n",
234                        rc);
235                 wf_smu_failure_state |= FAILURE_SENSOR;
236                 return;
237         }
238
239         rc = wf_sensor_get(sensor_cpu_power, &power);
240         if (rc) {
241                 printk(KERN_WARNING "windfarm: CPU power sensor error %d\n",
242                        rc);
243                 wf_smu_failure_state |= FAILURE_SENSOR;
244                 return;
245         }
246
247         DBG("wf_smu: CPU Fans tick ! CPU temp: %d.%03d, power: %d.%03d\n",
248             FIX32TOPRINT(temp), FIX32TOPRINT(power));
249
250 #ifdef HACKED_OVERTEMP
251         if (temp > 0x4a0000)
252                 wf_smu_failure_state |= FAILURE_OVERTEMP;
253 #else
254         if (temp > st->pid.param.tmax)
255                 wf_smu_failure_state |= FAILURE_OVERTEMP;
256 #endif
257         new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
258
259         DBG("wf_smu: new_setpoint: %d RPM\n", (int)new_setpoint);
260
261         if (st->cpu_setpoint == new_setpoint)
262                 return;
263         st->cpu_setpoint = new_setpoint;
264  readjust:
265         if (fan_cpu_main && wf_smu_failure_state == 0) {
266                 rc = wf_control_set(fan_cpu_main, st->cpu_setpoint);
267                 if (rc) {
268                         printk(KERN_WARNING "windfarm: CPU main fan"
269                                " error %d\n", rc);
270                         wf_smu_failure_state |= FAILURE_FAN;
271                 }
272         }
273         if (fan_cpu_second && wf_smu_failure_state == 0) {
274                 rc = wf_control_set(fan_cpu_second, st->cpu_setpoint);
275                 if (rc) {
276                         printk(KERN_WARNING "windfarm: CPU second fan"
277                                " error %d\n", rc);
278                         wf_smu_failure_state |= FAILURE_FAN;
279                 }
280         }
281         if (fan_cpu_third && wf_smu_failure_state == 0) {
282                 rc = wf_control_set(fan_cpu_third, st->cpu_setpoint);
283                 if (rc) {
284                         printk(KERN_WARNING "windfarm: CPU third fan"
285                                " error %d\n", rc);
286                         wf_smu_failure_state |= FAILURE_FAN;
287                 }
288         }
289 }
290
291 static void wf_smu_create_drive_fans(void)
292 {
293         struct wf_pid_param param = {
294                 .interval       = 5,
295                 .history_len    = 2,
296                 .gd             = 0x01e00000,
297                 .gp             = 0x00500000,
298                 .gr             = 0x00000000,
299                 .itarget        = 0x00200000,
300         };
301
302         /* Alloc & initialize state */
303         wf_smu_drive_fans = kmalloc(sizeof(struct wf_smu_drive_fans_state),
304                                         GFP_KERNEL);
305         if (wf_smu_drive_fans == NULL) {
306                 printk(KERN_WARNING "windfarm: Memory allocation error"
307                        " max fan speed\n");
308                 goto fail;
309         }
310         wf_smu_drive_fans->ticks = 1;
311
312         /* Fill PID params */
313         param.additive = (fan_hd->type == WF_CONTROL_RPM_FAN);
314         param.min = wf_control_get_min(fan_hd);
315         param.max = wf_control_get_max(fan_hd);
316         wf_pid_init(&wf_smu_drive_fans->pid, &param);
317
318         DBG("wf: Drive Fan control initialized.\n");
319         DBG("    itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
320             FIX32TOPRINT(param.itarget), param.min, param.max);
321         return;
322
323  fail:
324         if (fan_hd)
325                 wf_control_set_max(fan_hd);
326 }
327
328 static void wf_smu_drive_fans_tick(struct wf_smu_drive_fans_state *st)
329 {
330         s32 new_setpoint, temp;
331         int rc;
332
333         if (--st->ticks != 0) {
334                 if (wf_smu_readjust)
335                         goto readjust;
336                 return;
337         }
338         st->ticks = st->pid.param.interval;
339
340         rc = wf_sensor_get(sensor_hd_temp, &temp);
341         if (rc) {
342                 printk(KERN_WARNING "windfarm: HD temp sensor error %d\n",
343                        rc);
344                 wf_smu_failure_state |= FAILURE_SENSOR;
345                 return;
346         }
347
348         DBG("wf_smu: Drive Fans tick ! HD temp: %d.%03d\n",
349             FIX32TOPRINT(temp));
350
351         if (temp > (st->pid.param.itarget + 0x50000))
352                 wf_smu_failure_state |= FAILURE_OVERTEMP;
353
354         new_setpoint = wf_pid_run(&st->pid, temp);
355
356         DBG("wf_smu: new_setpoint: %d\n", (int)new_setpoint);
357
358         if (st->setpoint == new_setpoint)
359                 return;
360         st->setpoint = new_setpoint;
361  readjust:
362         if (fan_hd && wf_smu_failure_state == 0) {
363                 rc = wf_control_set(fan_hd, st->setpoint);
364                 if (rc) {
365                         printk(KERN_WARNING "windfarm: HD fan error %d\n",
366                                rc);
367                         wf_smu_failure_state |= FAILURE_FAN;
368                 }
369         }
370 }
371
372 static void wf_smu_create_slots_fans(void)
373 {
374         struct wf_pid_param param = {
375                 .interval       = 1,
376                 .history_len    = 8,
377                 .gd             = 0x00000000,
378                 .gp             = 0x00000000,
379                 .gr             = 0x00020000,
380                 .itarget        = 0x00000000
381         };
382
383         /* Alloc & initialize state */
384         wf_smu_slots_fans = kmalloc(sizeof(struct wf_smu_slots_fans_state),
385                                         GFP_KERNEL);
386         if (wf_smu_slots_fans == NULL) {
387                 printk(KERN_WARNING "windfarm: Memory allocation error"
388                        " max fan speed\n");
389                 goto fail;
390         }
391         wf_smu_slots_fans->ticks = 1;
392
393         /* Fill PID params */
394         param.additive = (fan_slots->type == WF_CONTROL_RPM_FAN);
395         param.min = wf_control_get_min(fan_slots);
396         param.max = wf_control_get_max(fan_slots);
397         wf_pid_init(&wf_smu_slots_fans->pid, &param);
398
399         DBG("wf: Slots Fan control initialized.\n");
400         DBG("    itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
401             FIX32TOPRINT(param.itarget), param.min, param.max);
402         return;
403
404  fail:
405         if (fan_slots)
406                 wf_control_set_max(fan_slots);
407 }
408
409 static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st)
410 {
411         s32 new_setpoint, power;
412         int rc;
413
414         if (--st->ticks != 0) {
415                 if (wf_smu_readjust)
416                         goto readjust;
417                 return;
418         }
419         st->ticks = st->pid.param.interval;
420
421         rc = wf_sensor_get(sensor_slots_power, &power);
422         if (rc) {
423                 printk(KERN_WARNING "windfarm: Slots power sensor error %d\n",
424                        rc);
425                 wf_smu_failure_state |= FAILURE_SENSOR;
426                 return;
427         }
428
429         DBG("wf_smu: Slots Fans tick ! Slots power: %d.%03d\n",
430             FIX32TOPRINT(power));
431
432 #if 0 /* Check what makes a good overtemp condition */
433         if (power > (st->pid.param.itarget + 0x50000))
434                 wf_smu_failure_state |= FAILURE_OVERTEMP;
435 #endif
436
437         new_setpoint = wf_pid_run(&st->pid, power);
438
439         DBG("wf_smu: new_setpoint: %d\n", (int)new_setpoint);
440
441         if (st->setpoint == new_setpoint)
442                 return;
443         st->setpoint = new_setpoint;
444  readjust:
445         if (fan_slots && wf_smu_failure_state == 0) {
446                 rc = wf_control_set(fan_slots, st->setpoint);
447                 if (rc) {
448                         printk(KERN_WARNING "windfarm: Slots fan error %d\n",
449                                rc);
450                         wf_smu_failure_state |= FAILURE_FAN;
451                 }
452         }
453 }
454
455
456 /*
457  * ****** Setup / Init / Misc ... ******
458  *
459  */
460
461 static void wf_smu_tick(void)
462 {
463         unsigned int last_failure = wf_smu_failure_state;
464         unsigned int new_failure;
465
466         if (!wf_smu_started) {
467                 DBG("wf: creating control loops !\n");
468                 wf_smu_create_drive_fans();
469                 wf_smu_create_slots_fans();
470                 wf_smu_create_cpu_fans();
471                 wf_smu_started = true;
472         }
473
474         /* Skipping ticks */
475         if (wf_smu_skipping && --wf_smu_skipping)
476                 return;
477
478         wf_smu_failure_state = 0;
479         if (wf_smu_drive_fans)
480                 wf_smu_drive_fans_tick(wf_smu_drive_fans);
481         if (wf_smu_slots_fans)
482                 wf_smu_slots_fans_tick(wf_smu_slots_fans);
483         if (wf_smu_cpu_fans)
484                 wf_smu_cpu_fans_tick(wf_smu_cpu_fans);
485
486         wf_smu_readjust = 0;
487         new_failure = wf_smu_failure_state & ~last_failure;
488
489         /* If entering failure mode, clamp cpufreq and ramp all
490          * fans to full speed.
491          */
492         if (wf_smu_failure_state && !last_failure) {
493                 if (cpufreq_clamp)
494                         wf_control_set_max(cpufreq_clamp);
495                 if (fan_cpu_main)
496                         wf_control_set_max(fan_cpu_main);
497                 if (fan_cpu_second)
498                         wf_control_set_max(fan_cpu_second);
499                 if (fan_cpu_third)
500                         wf_control_set_max(fan_cpu_third);
501                 if (fan_hd)
502                         wf_control_set_max(fan_hd);
503                 if (fan_slots)
504                         wf_control_set_max(fan_slots);
505         }
506
507         /* If leaving failure mode, unclamp cpufreq and readjust
508          * all fans on next iteration
509          */
510         if (!wf_smu_failure_state && last_failure) {
511                 if (cpufreq_clamp)
512                         wf_control_set_min(cpufreq_clamp);
513                 wf_smu_readjust = 1;
514         }
515
516         /* Overtemp condition detected, notify and start skipping a couple
517          * ticks to let the temperature go down
518          */
519         if (new_failure & FAILURE_OVERTEMP) {
520                 wf_set_overtemp();
521                 wf_smu_skipping = 2;
522                 wf_smu_overtemp = true;
523         }
524
525         /* We only clear the overtemp condition if overtemp is cleared
526          * _and_ no other failure is present. Since a sensor error will
527          * clear the overtemp condition (can't measure temperature) at
528          * the control loop levels, but we don't want to keep it clear
529          * here in this case
530          */
531         if (!wf_smu_failure_state && wf_smu_overtemp) {
532                 wf_clear_overtemp();
533                 wf_smu_overtemp = false;
534         }
535 }
536
537
538 static void wf_smu_new_control(struct wf_control *ct)
539 {
540         if (wf_smu_all_controls_ok)
541                 return;
542
543         if (fan_cpu_main == NULL && !strcmp(ct->name, "cpu-rear-fan-0")) {
544                 if (wf_get_control(ct) == 0)
545                         fan_cpu_main = ct;
546         }
547
548         if (fan_cpu_second == NULL && !strcmp(ct->name, "cpu-rear-fan-1")) {
549                 if (wf_get_control(ct) == 0)
550                         fan_cpu_second = ct;
551         }
552
553         if (fan_cpu_third == NULL && !strcmp(ct->name, "cpu-front-fan-0")) {
554                 if (wf_get_control(ct) == 0)
555                         fan_cpu_third = ct;
556         }
557
558         if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
559                 if (wf_get_control(ct) == 0)
560                         cpufreq_clamp = ct;
561         }
562
563         if (fan_hd == NULL && !strcmp(ct->name, "drive-bay-fan")) {
564                 if (wf_get_control(ct) == 0)
565                         fan_hd = ct;
566         }
567
568         if (fan_slots == NULL && !strcmp(ct->name, "slots-fan")) {
569                 if (wf_get_control(ct) == 0)
570                         fan_slots = ct;
571         }
572
573         if (fan_cpu_main && (fan_cpu_second || fan_cpu_third) && fan_hd &&
574             fan_slots && cpufreq_clamp)
575                 wf_smu_all_controls_ok = 1;
576 }
577
578 static void wf_smu_new_sensor(struct wf_sensor *sr)
579 {
580         if (wf_smu_all_sensors_ok)
581                 return;
582
583         if (sensor_cpu_power == NULL && !strcmp(sr->name, "cpu-power")) {
584                 if (wf_get_sensor(sr) == 0)
585                         sensor_cpu_power = sr;
586         }
587
588         if (sensor_cpu_temp == NULL && !strcmp(sr->name, "cpu-temp")) {
589                 if (wf_get_sensor(sr) == 0)
590                         sensor_cpu_temp = sr;
591         }
592
593         if (sensor_hd_temp == NULL && !strcmp(sr->name, "hd-temp")) {
594                 if (wf_get_sensor(sr) == 0)
595                         sensor_hd_temp = sr;
596         }
597
598         if (sensor_slots_power == NULL && !strcmp(sr->name, "slots-power")) {
599                 if (wf_get_sensor(sr) == 0)
600                         sensor_slots_power = sr;
601         }
602
603         if (sensor_cpu_power && sensor_cpu_temp &&
604             sensor_hd_temp && sensor_slots_power)
605                 wf_smu_all_sensors_ok = 1;
606 }
607
608
609 static int wf_smu_notify(struct notifier_block *self,
610                                unsigned long event, void *data)
611 {
612         switch(event) {
613         case WF_EVENT_NEW_CONTROL:
614                 DBG("wf: new control %s detected\n",
615                     ((struct wf_control *)data)->name);
616                 wf_smu_new_control(data);
617                 wf_smu_readjust = 1;
618                 break;
619         case WF_EVENT_NEW_SENSOR:
620                 DBG("wf: new sensor %s detected\n",
621                     ((struct wf_sensor *)data)->name);
622                 wf_smu_new_sensor(data);
623                 break;
624         case WF_EVENT_TICK:
625                 if (wf_smu_all_controls_ok && wf_smu_all_sensors_ok)
626                         wf_smu_tick();
627         }
628
629         return 0;
630 }
631
632 static struct notifier_block wf_smu_events = {
633         .notifier_call  = wf_smu_notify,
634 };
635
636 static int wf_init_pm(void)
637 {
638         printk(KERN_INFO "windfarm: Initializing for Desktop G5 model\n");
639
640         return 0;
641 }
642
643 static int wf_smu_probe(struct platform_device *ddev)
644 {
645         wf_register_client(&wf_smu_events);
646
647         return 0;
648 }
649
650 static int wf_smu_remove(struct platform_device *ddev)
651 {
652         wf_unregister_client(&wf_smu_events);
653
654         /* XXX We don't have yet a guarantee that our callback isn't
655          * in progress when returning from wf_unregister_client, so
656          * we add an arbitrary delay. I'll have to fix that in the core
657          */
658         msleep(1000);
659
660         /* Release all sensors */
661         /* One more crappy race: I don't think we have any guarantee here
662          * that the attribute callback won't race with the sensor beeing
663          * disposed of, and I'm not 100% certain what best way to deal
664          * with that except by adding locks all over... I'll do that
665          * eventually but heh, who ever rmmod this module anyway ?
666          */
667         if (sensor_cpu_power)
668                 wf_put_sensor(sensor_cpu_power);
669         if (sensor_cpu_temp)
670                 wf_put_sensor(sensor_cpu_temp);
671         if (sensor_hd_temp)
672                 wf_put_sensor(sensor_hd_temp);
673         if (sensor_slots_power)
674                 wf_put_sensor(sensor_slots_power);
675
676         /* Release all controls */
677         if (fan_cpu_main)
678                 wf_put_control(fan_cpu_main);
679         if (fan_cpu_second)
680                 wf_put_control(fan_cpu_second);
681         if (fan_cpu_third)
682                 wf_put_control(fan_cpu_third);
683         if (fan_hd)
684                 wf_put_control(fan_hd);
685         if (fan_slots)
686                 wf_put_control(fan_slots);
687         if (cpufreq_clamp)
688                 wf_put_control(cpufreq_clamp);
689
690         /* Destroy control loops state structures */
691         kfree(wf_smu_slots_fans);
692         kfree(wf_smu_drive_fans);
693         kfree(wf_smu_cpu_fans);
694
695         return 0;
696 }
697
698 static struct platform_driver wf_smu_driver = {
699         .probe = wf_smu_probe,
700         .remove = wf_smu_remove,
701         .driver = {
702                 .name = "windfarm",
703         },
704 };
705
706
707 static int __init wf_smu_init(void)
708 {
709         int rc = -ENODEV;
710
711         if (of_machine_is_compatible("PowerMac9,1"))
712                 rc = wf_init_pm();
713
714         if (rc == 0) {
715 #ifdef MODULE
716                 request_module("windfarm_smu_controls");
717                 request_module("windfarm_smu_sensors");
718                 request_module("windfarm_lm75_sensor");
719                 request_module("windfarm_cpufreq_clamp");
720
721 #endif /* MODULE */
722                 platform_driver_register(&wf_smu_driver);
723         }
724
725         return rc;
726 }
727
728 static void __exit wf_smu_exit(void)
729 {
730
731         platform_driver_unregister(&wf_smu_driver);
732 }
733
734
735 module_init(wf_smu_init);
736 module_exit(wf_smu_exit);
737
738 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
739 MODULE_DESCRIPTION("Thermal control logic for PowerMac9,1");
740 MODULE_LICENSE("GPL");
741
742 MODULE_ALIAS("platform:windfarm");