sched: Prevent balance_push() on remote runqueues
[linux-2.6-microblaze.git] / drivers / macintosh / windfarm_fcu_controls.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Windfarm PowerMac thermal control. FCU fan control
4  *
5  * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
6  */
7 #undef DEBUG
8
9 #include <linux/types.h>
10 #include <linux/errno.h>
11 #include <linux/kernel.h>
12 #include <linux/delay.h>
13 #include <linux/slab.h>
14 #include <linux/init.h>
15 #include <linux/wait.h>
16 #include <linux/i2c.h>
17 #include <asm/prom.h>
18 #include <asm/machdep.h>
19 #include <asm/io.h>
20 #include <asm/sections.h>
21
22 #include "windfarm.h"
23 #include "windfarm_mpu.h"
24
25 #define VERSION "1.0"
26
27 #ifdef DEBUG
28 #define DBG(args...)    printk(args)
29 #else
30 #define DBG(args...)    do { } while(0)
31 #endif
32
33 /*
34  * This option is "weird" :) Basically, if you define this to 1
35  * the control loop for the RPMs fans (not PWMs) will apply the
36  * correction factor obtained from the PID to the actual RPM
37  * speed read from the FCU.
38  *
39  * If you define the below constant to 0, then it will be
40  * applied to the setpoint RPM speed, that is basically the
41  * speed we proviously "asked" for.
42  *
43  * I'm using 0 for now which is what therm_pm72 used to do and
44  * what Darwin -apparently- does based on observed behaviour.
45  */
46 #define RPM_PID_USE_ACTUAL_SPEED        0
47
48 /* Default min/max for pumps */
49 #define CPU_PUMP_OUTPUT_MAX             3200
50 #define CPU_PUMP_OUTPUT_MIN             1250
51
52 #define FCU_FAN_RPM             0
53 #define FCU_FAN_PWM             1
54
55 struct wf_fcu_priv {
56         struct kref             ref;
57         struct i2c_client       *i2c;
58         struct mutex            lock;
59         struct list_head        fan_list;
60         int                     rpm_shift;
61 };
62
63 struct wf_fcu_fan {
64         struct list_head        link;
65         int                     id;
66         s32                     min, max, target;
67         struct wf_fcu_priv      *fcu_priv;
68         struct wf_control       ctrl;
69 };
70
71 static void wf_fcu_release(struct kref *ref)
72 {
73         struct wf_fcu_priv *pv = container_of(ref, struct wf_fcu_priv, ref);
74
75         kfree(pv);
76 }
77
78 static void wf_fcu_fan_release(struct wf_control *ct)
79 {
80         struct wf_fcu_fan *fan = ct->priv;
81
82         kref_put(&fan->fcu_priv->ref, wf_fcu_release);
83         kfree(fan);
84 }
85
86 static int wf_fcu_read_reg(struct wf_fcu_priv *pv, int reg,
87                            unsigned char *buf, int nb)
88 {
89         int tries, nr, nw;
90
91         mutex_lock(&pv->lock);
92
93         buf[0] = reg;
94         tries = 0;
95         for (;;) {
96                 nw = i2c_master_send(pv->i2c, buf, 1);
97                 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
98                         break;
99                 msleep(10);
100                 ++tries;
101         }
102         if (nw <= 0) {
103                 pr_err("Failure writing address to FCU: %d", nw);
104                 nr = nw;
105                 goto bail;
106         }
107         tries = 0;
108         for (;;) {
109                 nr = i2c_master_recv(pv->i2c, buf, nb);
110                 if (nr > 0 || (nr < 0 && nr != -ENODEV) || tries >= 100)
111                         break;
112                 msleep(10);
113                 ++tries;
114         }
115         if (nr <= 0)
116                 pr_err("wf_fcu: Failure reading data from FCU: %d", nw);
117  bail:
118         mutex_unlock(&pv->lock);
119         return nr;
120 }
121
122 static int wf_fcu_write_reg(struct wf_fcu_priv *pv, int reg,
123                             const unsigned char *ptr, int nb)
124 {
125         int tries, nw;
126         unsigned char buf[16];
127
128         buf[0] = reg;
129         memcpy(buf+1, ptr, nb);
130         ++nb;
131         tries = 0;
132         for (;;) {
133                 nw = i2c_master_send(pv->i2c, buf, nb);
134                 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
135                         break;
136                 msleep(10);
137                 ++tries;
138         }
139         if (nw < 0)
140                 pr_err("wf_fcu: Failure writing to FCU: %d", nw);
141         return nw;
142 }
143
144 static int wf_fcu_fan_set_rpm(struct wf_control *ct, s32 value)
145 {
146         struct wf_fcu_fan *fan = ct->priv;
147         struct wf_fcu_priv *pv = fan->fcu_priv;
148         int rc, shift = pv->rpm_shift;
149         unsigned char buf[2];
150
151         if (value < fan->min)
152                 value = fan->min;
153         if (value > fan->max)
154                 value = fan->max;
155
156         fan->target = value;
157
158         buf[0] = value >> (8 - shift);
159         buf[1] = value << shift;
160         rc = wf_fcu_write_reg(pv, 0x10 + (fan->id * 2), buf, 2);
161         if (rc < 0)
162                 return -EIO;
163         return 0;
164 }
165
166 static int wf_fcu_fan_get_rpm(struct wf_control *ct, s32 *value)
167 {
168         struct wf_fcu_fan *fan = ct->priv;
169         struct wf_fcu_priv *pv = fan->fcu_priv;
170         int rc, reg_base, shift = pv->rpm_shift;
171         unsigned char failure;
172         unsigned char active;
173         unsigned char buf[2];
174
175         rc = wf_fcu_read_reg(pv, 0xb, &failure, 1);
176         if (rc != 1)
177                 return -EIO;
178         if ((failure & (1 << fan->id)) != 0)
179                 return -EFAULT;
180         rc = wf_fcu_read_reg(pv, 0xd, &active, 1);
181         if (rc != 1)
182                 return -EIO;
183         if ((active & (1 << fan->id)) == 0)
184                 return -ENXIO;
185
186         /* Programmed value or real current speed */
187 #if RPM_PID_USE_ACTUAL_SPEED
188         reg_base = 0x11;
189 #else
190         reg_base = 0x10;
191 #endif
192         rc = wf_fcu_read_reg(pv, reg_base + (fan->id * 2), buf, 2);
193         if (rc != 2)
194                 return -EIO;
195
196         *value = (buf[0] << (8 - shift)) | buf[1] >> shift;
197
198         return 0;
199 }
200
201 static int wf_fcu_fan_set_pwm(struct wf_control *ct, s32 value)
202 {
203         struct wf_fcu_fan *fan = ct->priv;
204         struct wf_fcu_priv *pv = fan->fcu_priv;
205         unsigned char buf[2];
206         int rc;
207
208         if (value < fan->min)
209                 value = fan->min;
210         if (value > fan->max)
211                 value = fan->max;
212
213         fan->target = value;
214
215         value = (value * 2559) / 1000;
216         buf[0] = value;
217         rc = wf_fcu_write_reg(pv, 0x30 + (fan->id * 2), buf, 1);
218         if (rc < 0)
219                 return -EIO;
220         return 0;
221 }
222
223 static int wf_fcu_fan_get_pwm(struct wf_control *ct, s32 *value)
224 {
225         struct wf_fcu_fan *fan = ct->priv;
226         struct wf_fcu_priv *pv = fan->fcu_priv;
227         unsigned char failure;
228         unsigned char active;
229         unsigned char buf[2];
230         int rc;
231
232         rc = wf_fcu_read_reg(pv, 0x2b, &failure, 1);
233         if (rc != 1)
234                 return -EIO;
235         if ((failure & (1 << fan->id)) != 0)
236                 return -EFAULT;
237         rc = wf_fcu_read_reg(pv, 0x2d, &active, 1);
238         if (rc != 1)
239                 return -EIO;
240         if ((active & (1 << fan->id)) == 0)
241                 return -ENXIO;
242
243         rc = wf_fcu_read_reg(pv, 0x30 + (fan->id * 2), buf, 1);
244         if (rc != 1)
245                 return -EIO;
246
247         *value = (((s32)buf[0]) * 1000) / 2559;
248
249         return 0;
250 }
251
252 static s32 wf_fcu_fan_min(struct wf_control *ct)
253 {
254         struct wf_fcu_fan *fan = ct->priv;
255
256         return fan->min;
257 }
258
259 static s32 wf_fcu_fan_max(struct wf_control *ct)
260 {
261         struct wf_fcu_fan *fan = ct->priv;
262
263         return fan->max;
264 }
265
266 static const struct wf_control_ops wf_fcu_fan_rpm_ops = {
267         .set_value      = wf_fcu_fan_set_rpm,
268         .get_value      = wf_fcu_fan_get_rpm,
269         .get_min        = wf_fcu_fan_min,
270         .get_max        = wf_fcu_fan_max,
271         .release        = wf_fcu_fan_release,
272         .owner          = THIS_MODULE,
273 };
274
275 static const struct wf_control_ops wf_fcu_fan_pwm_ops = {
276         .set_value      = wf_fcu_fan_set_pwm,
277         .get_value      = wf_fcu_fan_get_pwm,
278         .get_min        = wf_fcu_fan_min,
279         .get_max        = wf_fcu_fan_max,
280         .release        = wf_fcu_fan_release,
281         .owner          = THIS_MODULE,
282 };
283
284 static void wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan)
285 {
286         const struct mpu_data *mpu = wf_get_mpu(0);
287         u16 pump_min = 0, pump_max = 0xffff;
288         u16 tmp[4];
289
290         /* Try to fetch pumps min/max infos from eeprom */
291         if (mpu) {
292                 memcpy(&tmp, mpu->processor_part_num, 8);
293                 if (tmp[0] != 0xffff && tmp[1] != 0xffff) {
294                         pump_min = max(pump_min, tmp[0]);
295                         pump_max = min(pump_max, tmp[1]);
296                 }
297                 if (tmp[2] != 0xffff && tmp[3] != 0xffff) {
298                         pump_min = max(pump_min, tmp[2]);
299                         pump_max = min(pump_max, tmp[3]);
300                 }
301         }
302
303         /* Double check the values, this _IS_ needed as the EEPROM on
304          * some dual 2.5Ghz G5s seem, at least, to have both min & max
305          * same to the same value ... (grrrr)
306          */
307         if (pump_min == pump_max || pump_min == 0 || pump_max == 0xffff) {
308                 pump_min = CPU_PUMP_OUTPUT_MIN;
309                 pump_max = CPU_PUMP_OUTPUT_MAX;
310         }
311
312         fan->min = pump_min;
313         fan->max = pump_max;
314
315         DBG("wf_fcu: pump min/max for %s set to: [%d..%d] RPM\n",
316             fan->ctrl.name, pump_min, pump_max);
317 }
318
319 static void wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan)
320 {
321         struct wf_fcu_priv *pv = fan->fcu_priv;
322         const struct mpu_data *mpu0 = wf_get_mpu(0);
323         const struct mpu_data *mpu1 = wf_get_mpu(1);
324
325         /* Default */
326         fan->min = 2400 >> pv->rpm_shift;
327         fan->max = 56000 >> pv->rpm_shift;
328
329         /* CPU fans have min/max in MPU */
330         if (mpu0 && !strcmp(fan->ctrl.name, "cpu-front-fan-0")) {
331                 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
332                 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
333                 goto bail;
334         }
335         if (mpu1 && !strcmp(fan->ctrl.name, "cpu-front-fan-1")) {
336                 fan->min = max(fan->min, (s32)mpu1->rminn_intake_fan);
337                 fan->max = min(fan->max, (s32)mpu1->rmaxn_intake_fan);
338                 goto bail;
339         }
340         if (mpu0 && !strcmp(fan->ctrl.name, "cpu-rear-fan-0")) {
341                 fan->min = max(fan->min, (s32)mpu0->rminn_exhaust_fan);
342                 fan->max = min(fan->max, (s32)mpu0->rmaxn_exhaust_fan);
343                 goto bail;
344         }
345         if (mpu1 && !strcmp(fan->ctrl.name, "cpu-rear-fan-1")) {
346                 fan->min = max(fan->min, (s32)mpu1->rminn_exhaust_fan);
347                 fan->max = min(fan->max, (s32)mpu1->rmaxn_exhaust_fan);
348                 goto bail;
349         }
350         /* Rackmac variants, we just use mpu0 intake */
351         if (!strncmp(fan->ctrl.name, "cpu-fan", 7)) {
352                 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
353                 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
354                 goto bail;
355         }
356  bail:
357         DBG("wf_fcu: fan min/max for %s set to: [%d..%d] RPM\n",
358             fan->ctrl.name, fan->min, fan->max);
359 }
360
361 static void wf_fcu_add_fan(struct wf_fcu_priv *pv, const char *name,
362                            int type, int id)
363 {
364         struct wf_fcu_fan *fan;
365
366         fan = kzalloc(sizeof(*fan), GFP_KERNEL);
367         if (!fan)
368                 return;
369         fan->fcu_priv = pv;
370         fan->id = id;
371         fan->ctrl.name = name;
372         fan->ctrl.priv = fan;
373
374         /* min/max is oddball but the code comes from
375          * therm_pm72 which seems to work so ...
376          */
377         if (type == FCU_FAN_RPM) {
378                 if (!strncmp(name, "cpu-pump", strlen("cpu-pump")))
379                         wf_fcu_get_pump_minmax(fan);
380                 else
381                         wf_fcu_get_rpmfan_minmax(fan);
382                 fan->ctrl.type = WF_CONTROL_RPM_FAN;
383                 fan->ctrl.ops = &wf_fcu_fan_rpm_ops;
384         } else {
385                 fan->min = 10;
386                 fan->max = 100;
387                 fan->ctrl.type = WF_CONTROL_PWM_FAN;
388                 fan->ctrl.ops = &wf_fcu_fan_pwm_ops;
389         }
390
391         if (wf_register_control(&fan->ctrl)) {
392                 pr_err("wf_fcu: Failed to register fan %s\n", name);
393                 kfree(fan);
394                 return;
395         }
396         list_add(&fan->link, &pv->fan_list);
397         kref_get(&pv->ref);
398 }
399
400 static void wf_fcu_lookup_fans(struct wf_fcu_priv *pv)
401 {
402         /* Translation of device-tree location properties to
403          * windfarm fan names
404          */
405         static const struct {
406                 const char *dt_name;    /* Device-tree name */
407                 const char *ct_name;    /* Control name */
408         } loc_trans[] = {
409                 { "BACKSIDE",           "backside-fan",         },
410                 { "SYS CTRLR FAN",      "backside-fan",         },
411                 { "DRIVE BAY",          "drive-bay-fan",        },
412                 { "SLOT",               "slots-fan",            },
413                 { "PCI FAN",            "slots-fan",            },
414                 { "CPU A INTAKE",       "cpu-front-fan-0",      },
415                 { "CPU A EXHAUST",      "cpu-rear-fan-0",       },
416                 { "CPU B INTAKE",       "cpu-front-fan-1",      },
417                 { "CPU B EXHAUST",      "cpu-rear-fan-1",       },
418                 { "CPU A PUMP",         "cpu-pump-0",           },
419                 { "CPU B PUMP",         "cpu-pump-1",           },
420                 { "CPU A 1",            "cpu-fan-a-0",          },
421                 { "CPU A 2",            "cpu-fan-b-0",          },
422                 { "CPU A 3",            "cpu-fan-c-0",          },
423                 { "CPU B 1",            "cpu-fan-a-1",          },
424                 { "CPU B 2",            "cpu-fan-b-1",          },
425                 { "CPU B 3",            "cpu-fan-c-1",          },
426         };
427         struct device_node *np, *fcu = pv->i2c->dev.of_node;
428         int i;
429
430         DBG("Looking up FCU controls in device-tree...\n");
431
432         for_each_child_of_node(fcu, np) {
433                 int id, type = -1;
434                 const char *loc;
435                 const char *name;
436                 const u32 *reg;
437
438                 DBG(" control: %pOFn, type: %s\n", np, of_node_get_device_type(np));
439
440                 /* Detect control type */
441                 if (of_node_is_type(np, "fan-rpm-control") ||
442                     of_node_is_type(np, "fan-rpm"))
443                         type = FCU_FAN_RPM;
444                 if (of_node_is_type(np, "fan-pwm-control") ||
445                     of_node_is_type(np, "fan-pwm"))
446                         type = FCU_FAN_PWM;
447                 /* Only care about fans for now */
448                 if (type == -1)
449                         continue;
450
451                 /* Lookup for a matching location */
452                 loc = of_get_property(np, "location", NULL);
453                 reg = of_get_property(np, "reg", NULL);
454                 if (loc == NULL || reg == NULL)
455                         continue;
456                 DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg);
457
458                 for (i = 0; i < ARRAY_SIZE(loc_trans); i++) {
459                         if (strncmp(loc, loc_trans[i].dt_name,
460                                     strlen(loc_trans[i].dt_name)))
461                                 continue;
462                         name = loc_trans[i].ct_name;
463
464                         DBG(" location match, name: %s\n", name);
465
466                         if (type == FCU_FAN_RPM)
467                                 id = ((*reg) - 0x10) / 2;
468                         else
469                                 id = ((*reg) - 0x30) / 2;
470                         if (id > 7) {
471                                 pr_warn("wf_fcu: Can't parse fan ID in device-tree for %pOF\n", np);
472                                 break;
473                         }
474                         wf_fcu_add_fan(pv, name, type, id);
475                         break;
476                 }
477         }
478 }
479
480 static void wf_fcu_default_fans(struct wf_fcu_priv *pv)
481 {
482         /* We only support the default fans for PowerMac7,2 */
483         if (!of_machine_is_compatible("PowerMac7,2"))
484                 return;
485
486         wf_fcu_add_fan(pv, "backside-fan",      FCU_FAN_PWM, 1);
487         wf_fcu_add_fan(pv, "drive-bay-fan",     FCU_FAN_RPM, 2);
488         wf_fcu_add_fan(pv, "slots-fan",         FCU_FAN_PWM, 2);
489         wf_fcu_add_fan(pv, "cpu-front-fan-0",   FCU_FAN_RPM, 3);
490         wf_fcu_add_fan(pv, "cpu-rear-fan-0",    FCU_FAN_RPM, 4);
491         wf_fcu_add_fan(pv, "cpu-front-fan-1",   FCU_FAN_RPM, 5);
492         wf_fcu_add_fan(pv, "cpu-rear-fan-1",    FCU_FAN_RPM, 6);
493 }
494
495 static int wf_fcu_init_chip(struct wf_fcu_priv *pv)
496 {
497         unsigned char buf = 0xff;
498         int rc;
499
500         rc = wf_fcu_write_reg(pv, 0xe, &buf, 1);
501         if (rc < 0)
502                 return -EIO;
503         rc = wf_fcu_write_reg(pv, 0x2e, &buf, 1);
504         if (rc < 0)
505                 return -EIO;
506         rc = wf_fcu_read_reg(pv, 0, &buf, 1);
507         if (rc < 0)
508                 return -EIO;
509         pv->rpm_shift = (buf == 1) ? 2 : 3;
510
511         pr_debug("wf_fcu: FCU Initialized, RPM fan shift is %d\n",
512                  pv->rpm_shift);
513
514         return 0;
515 }
516
517 static int wf_fcu_probe(struct i2c_client *client,
518                         const struct i2c_device_id *id)
519 {
520         struct wf_fcu_priv *pv;
521
522         pv = kzalloc(sizeof(*pv), GFP_KERNEL);
523         if (!pv)
524                 return -ENOMEM;
525
526         kref_init(&pv->ref);
527         mutex_init(&pv->lock);
528         INIT_LIST_HEAD(&pv->fan_list);
529         pv->i2c = client;
530
531         /*
532          * First we must start the FCU which will query the
533          * shift value to apply to RPMs
534          */
535         if (wf_fcu_init_chip(pv)) {
536                 pr_err("wf_fcu: Initialization failed !\n");
537                 kfree(pv);
538                 return -ENXIO;
539         }
540
541         /* First lookup fans in the device-tree */
542         wf_fcu_lookup_fans(pv);
543
544         /*
545          * Older machines don't have the device-tree entries
546          * we are looking for, just hard code the list
547          */
548         if (list_empty(&pv->fan_list))
549                 wf_fcu_default_fans(pv);
550
551         /* Still no fans ? FAIL */
552         if (list_empty(&pv->fan_list)) {
553                 pr_err("wf_fcu: Failed to find fans for your machine\n");
554                 kfree(pv);
555                 return -ENODEV;
556         }
557
558         dev_set_drvdata(&client->dev, pv);
559
560         return 0;
561 }
562
563 static int wf_fcu_remove(struct i2c_client *client)
564 {
565         struct wf_fcu_priv *pv = dev_get_drvdata(&client->dev);
566         struct wf_fcu_fan *fan;
567
568         while (!list_empty(&pv->fan_list)) {
569                 fan = list_first_entry(&pv->fan_list, struct wf_fcu_fan, link);
570                 list_del(&fan->link);
571                 wf_unregister_control(&fan->ctrl);
572         }
573         kref_put(&pv->ref, wf_fcu_release);
574         return 0;
575 }
576
577 static const struct i2c_device_id wf_fcu_id[] = {
578         { "MAC,fcu", 0 },
579         { }
580 };
581 MODULE_DEVICE_TABLE(i2c, wf_fcu_id);
582
583 static const struct of_device_id wf_fcu_of_id[] = {
584         { .compatible = "fcu", },
585         { }
586 };
587 MODULE_DEVICE_TABLE(of, wf_fcu_of_id);
588
589 static struct i2c_driver wf_fcu_driver = {
590         .driver = {
591                 .name   = "wf_fcu",
592                 .of_match_table = wf_fcu_of_id,
593         },
594         .probe          = wf_fcu_probe,
595         .remove         = wf_fcu_remove,
596         .id_table       = wf_fcu_id,
597 };
598
599 module_i2c_driver(wf_fcu_driver);
600
601 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
602 MODULE_DESCRIPTION("FCU control objects for PowerMacs thermal control");
603 MODULE_LICENSE("GPL");
604