Merge drm/drm-next into drm-misc-next-fixes
[linux-2.6-microblaze.git] / drivers / macintosh / windfarm_pm121.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Windfarm PowerMac thermal control. iMac G5 iSight
4  *
5  * (c) Copyright 2007 Étienne Bersac <bersace@gmail.com>
6  *
7  * Bits & pieces from windfarm_pm81.c by (c) Copyright 2005 Benjamin
8  * Herrenschmidt, IBM Corp. <benh@kernel.crashing.org>
9  *
10  * PowerMac12,1
11  * ============
12  *
13  * The algorithm used is the PID control algorithm, used the same way
14  * the published Darwin code does, using the same values that are
15  * present in the Darwin 8.10 snapshot property lists (note however
16  * that none of the code has been re-used, it's a complete
17  * re-implementation
18  *
19  * There is two models using PowerMac12,1. Model 2 is iMac G5 iSight
20  * 17" while Model 3 is iMac G5 20". They do have both the same
21  * controls with a tiny difference. The control-ids of hard-drive-fan
22  * and cpu-fan is swapped.
23  *
24  * Target Correction :
25  *
26  * controls have a target correction calculated as :
27  *
28  * new_min = ((((average_power * slope) >> 16) + offset) >> 16) + min_value
29  * new_value = max(new_value, max(new_min, 0))
30  *
31  * OD Fan control correction.
32  *
33  * # model_id: 2
34  *   offset             : -19563152
35  *   slope              :  1956315
36  *
37  * # model_id: 3
38  *   offset             : -15650652
39  *   slope              :  1565065
40  *
41  * HD Fan control correction.
42  *
43  * # model_id: 2
44  *   offset             : -15650652
45  *   slope              :  1565065
46  *
47  * # model_id: 3
48  *   offset             : -19563152
49  *   slope              :  1956315
50  *
51  * CPU Fan control correction.
52  *
53  * # model_id: 2
54  *   offset             : -25431900
55  *   slope              :  2543190
56  *
57  * # model_id: 3
58  *   offset             : -15650652
59  *   slope              :  1565065
60  *
61  * Target rubber-banding :
62  *
63  * Some controls have a target correction which depends on another
64  * control value. The correction is computed in the following way :
65  *
66  * new_min = ref_value * slope + offset
67  *
68  * ref_value is the value of the reference control. If new_min is
69  * greater than 0, then we correct the target value using :
70  *
71  * new_target = max (new_target, new_min >> 16)
72  *
73  * # model_id : 2
74  *   control    : cpu-fan
75  *   ref        : optical-drive-fan
76  *   offset     : -15650652
77  *   slope      : 1565065
78  *
79  * # model_id : 3
80  *   control    : optical-drive-fan
81  *   ref        : hard-drive-fan
82  *   offset     : -32768000
83  *   slope      : 65536
84  *
85  * In order to have the moste efficient correction with those
86  * dependencies, we must trigger HD loop before OD loop before CPU
87  * loop.
88  *
89  * The various control loops found in Darwin config file are:
90  *
91  * HD Fan control loop.
92  *
93  * # model_id: 2
94  *   control        : hard-drive-fan
95  *   sensor         : hard-drive-temp
96  *   PID params     : G_d = 0x00000000
97  *                    G_p = 0x002D70A3
98  *                    G_r = 0x00019999
99  *                    History = 2 entries
100  *                    Input target = 0x370000
101  *                    Interval = 5s
102  *
103  * # model_id: 3
104  *   control        : hard-drive-fan
105  *   sensor         : hard-drive-temp
106  *   PID params     : G_d = 0x00000000
107  *                    G_p = 0x002170A3
108  *                    G_r = 0x00019999
109  *                    History = 2 entries
110  *                    Input target = 0x370000
111  *                    Interval = 5s
112  *
113  * OD Fan control loop.
114  *
115  * # model_id: 2
116  *   control        : optical-drive-fan
117  *   sensor         : optical-drive-temp
118  *   PID params     : G_d = 0x00000000
119  *                    G_p = 0x001FAE14
120  *                    G_r = 0x00019999
121  *                    History = 2 entries
122  *                    Input target = 0x320000
123  *                    Interval = 5s
124  *
125  * # model_id: 3
126  *   control        : optical-drive-fan
127  *   sensor         : optical-drive-temp
128  *   PID params     : G_d = 0x00000000
129  *                    G_p = 0x001FAE14
130  *                    G_r = 0x00019999
131  *                    History = 2 entries
132  *                    Input target = 0x320000
133  *                    Interval = 5s
134  *
135  * GPU Fan control loop.
136  *
137  * # model_id: 2
138  *   control        : hard-drive-fan
139  *   sensor         : gpu-temp
140  *   PID params     : G_d = 0x00000000
141  *                    G_p = 0x002A6666
142  *                    G_r = 0x00019999
143  *                    History = 2 entries
144  *                    Input target = 0x5A0000
145  *                    Interval = 5s
146  *
147  * # model_id: 3
148  *   control        : cpu-fan
149  *   sensor         : gpu-temp
150  *   PID params     : G_d = 0x00000000
151  *                    G_p = 0x0010CCCC
152  *                    G_r = 0x00019999
153  *                    History = 2 entries
154  *                    Input target = 0x500000
155  *                    Interval = 5s
156  *
157  * KODIAK (aka northbridge) Fan control loop.
158  *
159  * # model_id: 2
160  *   control        : optical-drive-fan
161  *   sensor         : north-bridge-temp
162  *   PID params     : G_d = 0x00000000
163  *                    G_p = 0x003BD70A
164  *                    G_r = 0x00019999
165  *                    History = 2 entries
166  *                    Input target = 0x550000
167  *                    Interval = 5s
168  *
169  * # model_id: 3
170  *   control        : hard-drive-fan
171  *   sensor         : north-bridge-temp
172  *   PID params     : G_d = 0x00000000
173  *                    G_p = 0x0030F5C2
174  *                    G_r = 0x00019999
175  *                    History = 2 entries
176  *                    Input target = 0x550000
177  *                    Interval = 5s
178  *
179  * CPU Fan control loop.
180  *
181  *   control        : cpu-fan
182  *   sensors        : cpu-temp, cpu-power
183  *   PID params     : from SDB partition
184  *
185  * CPU Slew control loop.
186  *
187  *   control        : cpufreq-clamp
188  *   sensor         : cpu-temp
189  */
190
191 #undef  DEBUG
192
193 #include <linux/types.h>
194 #include <linux/errno.h>
195 #include <linux/kernel.h>
196 #include <linux/delay.h>
197 #include <linux/slab.h>
198 #include <linux/init.h>
199 #include <linux/spinlock.h>
200 #include <linux/wait.h>
201 #include <linux/kmod.h>
202 #include <linux/device.h>
203 #include <linux/platform_device.h>
204 #include <linux/of.h>
205
206 #include <asm/machdep.h>
207 #include <asm/io.h>
208 #include <asm/sections.h>
209 #include <asm/smu.h>
210
211 #include "windfarm.h"
212 #include "windfarm_pid.h"
213
214 #define VERSION "0.3"
215
216 static int pm121_mach_model;    /* machine model id */
217
218 /* Controls & sensors */
219 static struct wf_sensor *sensor_cpu_power;
220 static struct wf_sensor *sensor_cpu_temp;
221 static struct wf_sensor *sensor_cpu_voltage;
222 static struct wf_sensor *sensor_cpu_current;
223 static struct wf_sensor *sensor_gpu_temp;
224 static struct wf_sensor *sensor_north_bridge_temp;
225 static struct wf_sensor *sensor_hard_drive_temp;
226 static struct wf_sensor *sensor_optical_drive_temp;
227 static struct wf_sensor *sensor_incoming_air_temp; /* unused ! */
228
229 enum {
230         FAN_CPU,
231         FAN_HD,
232         FAN_OD,
233         CPUFREQ,
234         N_CONTROLS
235 };
236 static struct wf_control *controls[N_CONTROLS] = {};
237
238 /* Set to kick the control loop into life */
239 static int pm121_all_controls_ok, pm121_all_sensors_ok;
240 static bool pm121_started;
241
242 enum {
243         FAILURE_FAN             = 1 << 0,
244         FAILURE_SENSOR          = 1 << 1,
245         FAILURE_OVERTEMP        = 1 << 2
246 };
247
248 /* All sys loops. Note the HD before the OD loop in order to have it
249    run before. */
250 enum {
251         LOOP_GPU,               /* control = hd or cpu, but luckily,
252                                    it doesn't matter */
253         LOOP_HD,                /* control = hd */
254         LOOP_KODIAK,            /* control = hd or od */
255         LOOP_OD,                /* control = od */
256         N_LOOPS
257 };
258
259 static const char *loop_names[N_LOOPS] = {
260         "GPU",
261         "HD",
262         "KODIAK",
263         "OD",
264 };
265
266 #define PM121_NUM_CONFIGS       2
267
268 static unsigned int pm121_failure_state;
269 static int pm121_readjust, pm121_skipping;
270 static bool pm121_overtemp;
271 static s32 average_power;
272
273 struct pm121_correction {
274         int     offset;
275         int     slope;
276 };
277
278 static struct pm121_correction corrections[N_CONTROLS][PM121_NUM_CONFIGS] = {
279         /* FAN_OD */
280         {
281                 /* MODEL 2 */
282                 { .offset       = -19563152,
283                   .slope        =  1956315
284                 },
285                 /* MODEL 3 */
286                 { .offset       = -15650652,
287                   .slope        =  1565065
288                 },
289         },
290         /* FAN_HD */
291         {
292                 /* MODEL 2 */
293                 { .offset       = -15650652,
294                   .slope        =  1565065
295                 },
296                 /* MODEL 3 */
297                 { .offset       = -19563152,
298                   .slope        =  1956315
299                 },
300         },
301         /* FAN_CPU */
302         {
303                 /* MODEL 2 */
304                 { .offset       = -25431900,
305                   .slope        =  2543190
306                 },
307                 /* MODEL 3 */
308                 { .offset       = -15650652,
309                   .slope        =  1565065
310                 },
311         },
312         /* CPUFREQ has no correction (and is not implemented at all) */
313 };
314
315 struct pm121_connection {
316         unsigned int    control_id;
317         unsigned int    ref_id;
318         struct pm121_correction correction;
319 };
320
321 static struct pm121_connection pm121_connections[] = {
322         /* MODEL 2 */
323         { .control_id   = FAN_CPU,
324           .ref_id       = FAN_OD,
325           { .offset     = -32768000,
326             .slope      =  65536
327           }
328         },
329         /* MODEL 3 */
330         { .control_id   = FAN_OD,
331           .ref_id       = FAN_HD,
332           { .offset     = -32768000,
333             .slope      =  65536
334           }
335         },
336 };
337
338 /* pointer to the current model connection */
339 static struct pm121_connection *pm121_connection;
340
341 /*
342  * ****** System Fans Control Loop ******
343  *
344  */
345
346 /* Since each loop handles only one control and we want to avoid
347  * writing virtual control, we store the control correction with the
348  * loop params. Some data are not set, there are common to all loop
349  * and thus, hardcoded.
350  */
351 struct pm121_sys_param {
352         /* purely informative since we use mach_model-2 as index */
353         int                     model_id;
354         struct wf_sensor        **sensor; /* use sensor_id instead ? */
355         s32                     gp, itarget;
356         unsigned int            control_id;
357 };
358
359 static struct pm121_sys_param
360 pm121_sys_all_params[N_LOOPS][PM121_NUM_CONFIGS] = {
361         /* GPU Fan control loop */
362         {
363                 { .model_id     = 2,
364                   .sensor       = &sensor_gpu_temp,
365                   .gp           = 0x002A6666,
366                   .itarget      = 0x5A0000,
367                   .control_id   = FAN_HD,
368                 },
369                 { .model_id     = 3,
370                   .sensor       = &sensor_gpu_temp,
371                   .gp           = 0x0010CCCC,
372                   .itarget      = 0x500000,
373                   .control_id   = FAN_CPU,
374                 },
375         },
376         /* HD Fan control loop */
377         {
378                 { .model_id     = 2,
379                   .sensor       = &sensor_hard_drive_temp,
380                   .gp           = 0x002D70A3,
381                   .itarget      = 0x370000,
382                   .control_id   = FAN_HD,
383                 },
384                 { .model_id     = 3,
385                   .sensor       = &sensor_hard_drive_temp,
386                   .gp           = 0x002170A3,
387                   .itarget      = 0x370000,
388                   .control_id   = FAN_HD,
389                 },
390         },
391         /* KODIAK Fan control loop */
392         {
393                 { .model_id     = 2,
394                   .sensor       = &sensor_north_bridge_temp,
395                   .gp           = 0x003BD70A,
396                   .itarget      = 0x550000,
397                   .control_id   = FAN_OD,
398                 },
399                 { .model_id     = 3,
400                   .sensor       = &sensor_north_bridge_temp,
401                   .gp           = 0x0030F5C2,
402                   .itarget      = 0x550000,
403                   .control_id   = FAN_HD,
404                 },
405         },
406         /* OD Fan control loop */
407         {
408                 { .model_id     = 2,
409                   .sensor       = &sensor_optical_drive_temp,
410                   .gp           = 0x001FAE14,
411                   .itarget      = 0x320000,
412                   .control_id   = FAN_OD,
413                 },
414                 { .model_id     = 3,
415                   .sensor       = &sensor_optical_drive_temp,
416                   .gp           = 0x001FAE14,
417                   .itarget      = 0x320000,
418                   .control_id   = FAN_OD,
419                 },
420         },
421 };
422
423 /* the hardcoded values */
424 #define PM121_SYS_GD            0x00000000
425 #define PM121_SYS_GR            0x00019999
426 #define PM121_SYS_HISTORY_SIZE  2
427 #define PM121_SYS_INTERVAL      5
428
429 /* State data used by the system fans control loop
430  */
431 struct pm121_sys_state {
432         int                     ticks;
433         s32                     setpoint;
434         struct wf_pid_state     pid;
435 };
436
437 static struct pm121_sys_state *pm121_sys_state[N_LOOPS] = {};
438
439 /*
440  * ****** CPU Fans Control Loop ******
441  *
442  */
443
444 #define PM121_CPU_INTERVAL      1
445
446 /* State data used by the cpu fans control loop
447  */
448 struct pm121_cpu_state {
449         int                     ticks;
450         s32                     setpoint;
451         struct wf_cpu_pid_state pid;
452 };
453
454 static struct pm121_cpu_state *pm121_cpu_state;
455
456
457
458 /*
459  * ***** Implementation *****
460  *
461  */
462
463 /* correction the value using the output-low-bound correction algo */
464 static s32 pm121_correct(s32 new_setpoint,
465                          unsigned int control_id,
466                          s32 min)
467 {
468         s32 new_min;
469         struct pm121_correction *correction;
470         correction = &corrections[control_id][pm121_mach_model - 2];
471
472         new_min = (average_power * correction->slope) >> 16;
473         new_min += correction->offset;
474         new_min = (new_min >> 16) + min;
475
476         return max3(new_setpoint, new_min, 0);
477 }
478
479 static s32 pm121_connect(unsigned int control_id, s32 setpoint)
480 {
481         s32 new_min, value, new_setpoint;
482
483         if (pm121_connection->control_id == control_id) {
484                 controls[control_id]->ops->get_value(controls[control_id],
485                                                      &value);
486                 new_min = value * pm121_connection->correction.slope;
487                 new_min += pm121_connection->correction.offset;
488                 if (new_min > 0) {
489                         new_setpoint = max(setpoint, (new_min >> 16));
490                         if (new_setpoint != setpoint) {
491                                 pr_debug("pm121: %s depending on %s, "
492                                          "corrected from %d to %d RPM\n",
493                                          controls[control_id]->name,
494                                          controls[pm121_connection->ref_id]->name,
495                                          (int) setpoint, (int) new_setpoint);
496                         }
497                 } else
498                         new_setpoint = setpoint;
499         }
500         /* no connection */
501         else
502                 new_setpoint = setpoint;
503
504         return new_setpoint;
505 }
506
507 /* FAN LOOPS */
508 static void pm121_create_sys_fans(int loop_id)
509 {
510         struct pm121_sys_param *param = NULL;
511         struct wf_pid_param pid_param;
512         struct wf_control *control = NULL;
513         int i;
514
515         /* First, locate the params for this model */
516         for (i = 0; i < PM121_NUM_CONFIGS; i++) {
517                 if (pm121_sys_all_params[loop_id][i].model_id == pm121_mach_model) {
518                         param = &(pm121_sys_all_params[loop_id][i]);
519                         break;
520                 }
521         }
522
523         /* No params found, put fans to max */
524         if (param == NULL) {
525                 printk(KERN_WARNING "pm121: %s fan config not found "
526                        " for this machine model\n",
527                        loop_names[loop_id]);
528                 goto fail;
529         }
530
531         control = controls[param->control_id];
532
533         /* Alloc & initialize state */
534         pm121_sys_state[loop_id] = kmalloc(sizeof(struct pm121_sys_state),
535                                            GFP_KERNEL);
536         if (pm121_sys_state[loop_id] == NULL) {
537                 printk(KERN_WARNING "pm121: Memory allocation error\n");
538                 goto fail;
539         }
540         pm121_sys_state[loop_id]->ticks = 1;
541
542         /* Fill PID params */
543         pid_param.gd            = PM121_SYS_GD;
544         pid_param.gp            = param->gp;
545         pid_param.gr            = PM121_SYS_GR;
546         pid_param.interval      = PM121_SYS_INTERVAL;
547         pid_param.history_len   = PM121_SYS_HISTORY_SIZE;
548         pid_param.itarget       = param->itarget;
549         if(control)
550         {
551                 pid_param.min           = control->ops->get_min(control);
552                 pid_param.max           = control->ops->get_max(control);
553         } else {
554                 /*
555                  * This is probably not the right!?
556                  * Perhaps goto fail  if control == NULL  above?
557                  */
558                 pid_param.min           = 0;
559                 pid_param.max           = 0;
560         }
561
562         wf_pid_init(&pm121_sys_state[loop_id]->pid, &pid_param);
563
564         pr_debug("pm121: %s Fan control loop initialized.\n"
565                  "       itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
566                  loop_names[loop_id], FIX32TOPRINT(pid_param.itarget),
567                  pid_param.min, pid_param.max);
568         return;
569
570  fail:
571         /* note that this is not optimal since another loop may still
572            control the same control */
573         printk(KERN_WARNING "pm121: failed to set up %s loop "
574                "setting \"%s\" to max speed.\n",
575                loop_names[loop_id], control ? control->name : "uninitialized value");
576
577         if (control)
578                 wf_control_set_max(control);
579 }
580
581 static void pm121_sys_fans_tick(int loop_id)
582 {
583         struct pm121_sys_param *param;
584         struct pm121_sys_state *st;
585         struct wf_sensor *sensor;
586         struct wf_control *control;
587         s32 temp, new_setpoint;
588         int rc;
589
590         param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
591         st = pm121_sys_state[loop_id];
592         sensor = *(param->sensor);
593         control = controls[param->control_id];
594
595         if (--st->ticks != 0) {
596                 if (pm121_readjust)
597                         goto readjust;
598                 return;
599         }
600         st->ticks = PM121_SYS_INTERVAL;
601
602         rc = sensor->ops->get_value(sensor, &temp);
603         if (rc) {
604                 printk(KERN_WARNING "windfarm: %s sensor error %d\n",
605                        sensor->name, rc);
606                 pm121_failure_state |= FAILURE_SENSOR;
607                 return;
608         }
609
610         pr_debug("pm121: %s Fan tick ! %s: %d.%03d\n",
611                  loop_names[loop_id], sensor->name,
612                  FIX32TOPRINT(temp));
613
614         new_setpoint = wf_pid_run(&st->pid, temp);
615
616         /* correction */
617         new_setpoint = pm121_correct(new_setpoint,
618                                      param->control_id,
619                                      st->pid.param.min);
620         /* linked corretion */
621         new_setpoint = pm121_connect(param->control_id, new_setpoint);
622
623         if (new_setpoint == st->setpoint)
624                 return;
625         st->setpoint = new_setpoint;
626         pr_debug("pm121: %s corrected setpoint: %d RPM\n",
627                  control->name, (int)new_setpoint);
628  readjust:
629         if (control && pm121_failure_state == 0) {
630                 rc = control->ops->set_value(control, st->setpoint);
631                 if (rc) {
632                         printk(KERN_WARNING "windfarm: %s fan error %d\n",
633                                control->name, rc);
634                         pm121_failure_state |= FAILURE_FAN;
635                 }
636         }
637 }
638
639
640 /* CPU LOOP */
641 static void pm121_create_cpu_fans(void)
642 {
643         struct wf_cpu_pid_param pid_param;
644         const struct smu_sdbp_header *hdr;
645         struct smu_sdbp_cpupiddata *piddata;
646         struct smu_sdbp_fvt *fvt;
647         struct wf_control *fan_cpu;
648         s32 tmax, tdelta, maxpow, powadj;
649
650         fan_cpu = controls[FAN_CPU];
651
652         /* First, locate the PID params in SMU SBD */
653         hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
654         if (hdr == 0) {
655                 printk(KERN_WARNING "pm121: CPU PID fan config not found.\n");
656                 goto fail;
657         }
658         piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
659
660         /* Get the FVT params for operating point 0 (the only supported one
661          * for now) in order to get tmax
662          */
663         hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
664         if (hdr) {
665                 fvt = (struct smu_sdbp_fvt *)&hdr[1];
666                 tmax = ((s32)fvt->maxtemp) << 16;
667         } else
668                 tmax = 0x5e0000; /* 94 degree default */
669
670         /* Alloc & initialize state */
671         pm121_cpu_state = kmalloc(sizeof(struct pm121_cpu_state),
672                                   GFP_KERNEL);
673         if (pm121_cpu_state == NULL)
674                 goto fail;
675         pm121_cpu_state->ticks = 1;
676
677         /* Fill PID params */
678         pid_param.interval = PM121_CPU_INTERVAL;
679         pid_param.history_len = piddata->history_len;
680         if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
681                 printk(KERN_WARNING "pm121: History size overflow on "
682                        "CPU control loop (%d)\n", piddata->history_len);
683                 pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
684         }
685         pid_param.gd = piddata->gd;
686         pid_param.gp = piddata->gp;
687         pid_param.gr = piddata->gr / pid_param.history_len;
688
689         tdelta = ((s32)piddata->target_temp_delta) << 16;
690         maxpow = ((s32)piddata->max_power) << 16;
691         powadj = ((s32)piddata->power_adj) << 16;
692
693         pid_param.tmax = tmax;
694         pid_param.ttarget = tmax - tdelta;
695         pid_param.pmaxadj = maxpow - powadj;
696
697         pid_param.min = fan_cpu->ops->get_min(fan_cpu);
698         pid_param.max = fan_cpu->ops->get_max(fan_cpu);
699
700         wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param);
701
702         pr_debug("pm121: CPU Fan control initialized.\n");
703         pr_debug("       ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
704                  FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
705                  pid_param.min, pid_param.max);
706
707         return;
708
709  fail:
710         printk(KERN_WARNING "pm121: CPU fan config not found, max fan speed\n");
711
712         if (controls[CPUFREQ])
713                 wf_control_set_max(controls[CPUFREQ]);
714         if (fan_cpu)
715                 wf_control_set_max(fan_cpu);
716 }
717
718
719 static void pm121_cpu_fans_tick(struct pm121_cpu_state *st)
720 {
721         s32 new_setpoint, temp, power;
722         struct wf_control *fan_cpu = NULL;
723         int rc;
724
725         if (--st->ticks != 0) {
726                 if (pm121_readjust)
727                         goto readjust;
728                 return;
729         }
730         st->ticks = PM121_CPU_INTERVAL;
731
732         fan_cpu = controls[FAN_CPU];
733
734         rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
735         if (rc) {
736                 printk(KERN_WARNING "pm121: CPU temp sensor error %d\n",
737                        rc);
738                 pm121_failure_state |= FAILURE_SENSOR;
739                 return;
740         }
741
742         rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
743         if (rc) {
744                 printk(KERN_WARNING "pm121: CPU power sensor error %d\n",
745                        rc);
746                 pm121_failure_state |= FAILURE_SENSOR;
747                 return;
748         }
749
750         pr_debug("pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
751                  FIX32TOPRINT(temp), FIX32TOPRINT(power));
752
753         if (temp > st->pid.param.tmax)
754                 pm121_failure_state |= FAILURE_OVERTEMP;
755
756         new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
757
758         /* correction */
759         new_setpoint = pm121_correct(new_setpoint,
760                                      FAN_CPU,
761                                      st->pid.param.min);
762
763         /* connected correction */
764         new_setpoint = pm121_connect(FAN_CPU, new_setpoint);
765
766         if (st->setpoint == new_setpoint)
767                 return;
768         st->setpoint = new_setpoint;
769         pr_debug("pm121: CPU corrected setpoint: %d RPM\n", (int)new_setpoint);
770
771  readjust:
772         if (fan_cpu && pm121_failure_state == 0) {
773                 rc = fan_cpu->ops->set_value(fan_cpu, st->setpoint);
774                 if (rc) {
775                         printk(KERN_WARNING "pm121: %s fan error %d\n",
776                                fan_cpu->name, rc);
777                         pm121_failure_state |= FAILURE_FAN;
778                 }
779         }
780 }
781
782 /*
783  * ****** Common ******
784  *
785  */
786
787 static void pm121_tick(void)
788 {
789         unsigned int last_failure = pm121_failure_state;
790         unsigned int new_failure;
791         s32 total_power;
792         int i;
793
794         if (!pm121_started) {
795                 pr_debug("pm121: creating control loops !\n");
796                 for (i = 0; i < N_LOOPS; i++)
797                         pm121_create_sys_fans(i);
798
799                 pm121_create_cpu_fans();
800                 pm121_started = true;
801         }
802
803         /* skipping ticks */
804         if (pm121_skipping && --pm121_skipping)
805                 return;
806
807         /* compute average power */
808         total_power = 0;
809         for (i = 0; i < pm121_cpu_state->pid.param.history_len; i++)
810                 total_power += pm121_cpu_state->pid.powers[i];
811
812         average_power = total_power / pm121_cpu_state->pid.param.history_len;
813
814
815         pm121_failure_state = 0;
816         for (i = 0 ; i < N_LOOPS; i++) {
817                 if (pm121_sys_state[i])
818                         pm121_sys_fans_tick(i);
819         }
820
821         if (pm121_cpu_state)
822                 pm121_cpu_fans_tick(pm121_cpu_state);
823
824         pm121_readjust = 0;
825         new_failure = pm121_failure_state & ~last_failure;
826
827         /* If entering failure mode, clamp cpufreq and ramp all
828          * fans to full speed.
829          */
830         if (pm121_failure_state && !last_failure) {
831                 for (i = 0; i < N_CONTROLS; i++) {
832                         if (controls[i])
833                                 wf_control_set_max(controls[i]);
834                 }
835         }
836
837         /* If leaving failure mode, unclamp cpufreq and readjust
838          * all fans on next iteration
839          */
840         if (!pm121_failure_state && last_failure) {
841                 if (controls[CPUFREQ])
842                         wf_control_set_min(controls[CPUFREQ]);
843                 pm121_readjust = 1;
844         }
845
846         /* Overtemp condition detected, notify and start skipping a couple
847          * ticks to let the temperature go down
848          */
849         if (new_failure & FAILURE_OVERTEMP) {
850                 wf_set_overtemp();
851                 pm121_skipping = 2;
852                 pm121_overtemp = true;
853         }
854
855         /* We only clear the overtemp condition if overtemp is cleared
856          * _and_ no other failure is present. Since a sensor error will
857          * clear the overtemp condition (can't measure temperature) at
858          * the control loop levels, but we don't want to keep it clear
859          * here in this case
860          */
861         if (!pm121_failure_state && pm121_overtemp) {
862                 wf_clear_overtemp();
863                 pm121_overtemp = false;
864         }
865 }
866
867
868 static struct wf_control* pm121_register_control(struct wf_control *ct,
869                                                  const char *match,
870                                                  unsigned int id)
871 {
872         if (controls[id] == NULL && !strcmp(ct->name, match)) {
873                 if (wf_get_control(ct) == 0)
874                         controls[id] = ct;
875         }
876         return controls[id];
877 }
878
879 static void pm121_new_control(struct wf_control *ct)
880 {
881         int all = 1;
882
883         if (pm121_all_controls_ok)
884                 return;
885
886         all = pm121_register_control(ct, "optical-drive-fan", FAN_OD) && all;
887         all = pm121_register_control(ct, "hard-drive-fan", FAN_HD) && all;
888         all = pm121_register_control(ct, "cpu-fan", FAN_CPU) && all;
889         all = pm121_register_control(ct, "cpufreq-clamp", CPUFREQ) && all;
890
891         if (all)
892                 pm121_all_controls_ok = 1;
893 }
894
895
896
897
898 static struct wf_sensor* pm121_register_sensor(struct wf_sensor *sensor,
899                                                const char *match,
900                                                struct wf_sensor **var)
901 {
902         if (*var == NULL && !strcmp(sensor->name, match)) {
903                 if (wf_get_sensor(sensor) == 0)
904                         *var = sensor;
905         }
906         return *var;
907 }
908
909 static void pm121_new_sensor(struct wf_sensor *sr)
910 {
911         int all = 1;
912
913         if (pm121_all_sensors_ok)
914                 return;
915
916         all = pm121_register_sensor(sr, "cpu-temp",
917                                     &sensor_cpu_temp) && all;
918         all = pm121_register_sensor(sr, "cpu-current",
919                                     &sensor_cpu_current) && all;
920         all = pm121_register_sensor(sr, "cpu-voltage",
921                                     &sensor_cpu_voltage) && all;
922         all = pm121_register_sensor(sr, "cpu-power",
923                                     &sensor_cpu_power) && all;
924         all = pm121_register_sensor(sr, "hard-drive-temp",
925                                     &sensor_hard_drive_temp) && all;
926         all = pm121_register_sensor(sr, "optical-drive-temp",
927                                     &sensor_optical_drive_temp) && all;
928         all = pm121_register_sensor(sr, "incoming-air-temp",
929                                     &sensor_incoming_air_temp) && all;
930         all = pm121_register_sensor(sr, "north-bridge-temp",
931                                     &sensor_north_bridge_temp) && all;
932         all = pm121_register_sensor(sr, "gpu-temp",
933                                     &sensor_gpu_temp) && all;
934
935         if (all)
936                 pm121_all_sensors_ok = 1;
937 }
938
939
940
941 static int pm121_notify(struct notifier_block *self,
942                         unsigned long event, void *data)
943 {
944         switch (event) {
945         case WF_EVENT_NEW_CONTROL:
946                 pr_debug("pm121: new control %s detected\n",
947                          ((struct wf_control *)data)->name);
948                 pm121_new_control(data);
949                 break;
950         case WF_EVENT_NEW_SENSOR:
951                 pr_debug("pm121: new sensor %s detected\n",
952                          ((struct wf_sensor *)data)->name);
953                 pm121_new_sensor(data);
954                 break;
955         case WF_EVENT_TICK:
956                 if (pm121_all_controls_ok && pm121_all_sensors_ok)
957                         pm121_tick();
958                 break;
959         }
960
961         return 0;
962 }
963
964 static struct notifier_block pm121_events = {
965         .notifier_call  = pm121_notify,
966 };
967
968 static int pm121_init_pm(void)
969 {
970         const struct smu_sdbp_header *hdr;
971
972         hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
973         if (hdr != 0) {
974                 struct smu_sdbp_sensortree *st =
975                         (struct smu_sdbp_sensortree *)&hdr[1];
976                 pm121_mach_model = st->model_id;
977         }
978
979         pm121_connection = &pm121_connections[pm121_mach_model - 2];
980
981         printk(KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
982                pm121_mach_model);
983
984         return 0;
985 }
986
987
988 static int pm121_probe(struct platform_device *ddev)
989 {
990         wf_register_client(&pm121_events);
991
992         return 0;
993 }
994
995 static int pm121_remove(struct platform_device *ddev)
996 {
997         wf_unregister_client(&pm121_events);
998         return 0;
999 }
1000
1001 static struct platform_driver pm121_driver = {
1002         .probe = pm121_probe,
1003         .remove = pm121_remove,
1004         .driver = {
1005                 .name = "windfarm",
1006                 .bus = &platform_bus_type,
1007         },
1008 };
1009
1010
1011 static int __init pm121_init(void)
1012 {
1013         int rc = -ENODEV;
1014
1015         if (of_machine_is_compatible("PowerMac12,1"))
1016                 rc = pm121_init_pm();
1017
1018         if (rc == 0) {
1019                 request_module("windfarm_smu_controls");
1020                 request_module("windfarm_smu_sensors");
1021                 request_module("windfarm_smu_sat");
1022                 request_module("windfarm_lm75_sensor");
1023                 request_module("windfarm_max6690_sensor");
1024                 request_module("windfarm_cpufreq_clamp");
1025                 platform_driver_register(&pm121_driver);
1026         }
1027
1028         return rc;
1029 }
1030
1031 static void __exit pm121_exit(void)
1032 {
1033
1034         platform_driver_unregister(&pm121_driver);
1035 }
1036
1037
1038 module_init(pm121_init);
1039 module_exit(pm121_exit);
1040
1041 MODULE_AUTHOR("Étienne Bersac <bersace@gmail.com>");
1042 MODULE_DESCRIPTION("Thermal control logic for iMac G5 (iSight)");
1043 MODULE_LICENSE("GPL");
1044