GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / macintosh / therm_adt746x.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Device driver for the i2c thermostat found on the iBook G4, Albook G4
4  *
5  * Copyright (C) 2003, 2004 Colin Leroy, Rasmus Rohde, Benjamin Herrenschmidt
6  *
7  * Documentation from 115254175ADT7467_pra.pdf and 3686221171167ADT7460_b.pdf
8  * https://www.onsemi.com/PowerSolutions/product.do?id=ADT7467
9  * https://www.onsemi.com/PowerSolutions/product.do?id=ADT7460
10  *
11  */
12
13 #include <linux/types.h>
14 #include <linux/module.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/delay.h>
18 #include <linux/sched.h>
19 #include <linux/i2c.h>
20 #include <linux/slab.h>
21 #include <linux/init.h>
22 #include <linux/spinlock.h>
23 #include <linux/wait.h>
24 #include <linux/suspend.h>
25 #include <linux/kthread.h>
26 #include <linux/moduleparam.h>
27 #include <linux/freezer.h>
28 #include <linux/of.h>
29 #include <linux/of_platform.h>
30 #include <linux/platform_device.h>
31
32 #include <asm/machdep.h>
33 #include <asm/io.h>
34 #include <asm/sections.h>
35
36 #undef DEBUG
37
38 #define CONFIG_REG   0x40
39 #define MANUAL_MASK  0xe0
40 #define AUTO_MASK    0x20
41 #define INVERT_MASK  0x10
42
43 static u8 TEMP_REG[3]    = {0x26, 0x25, 0x27}; /* local, sensor1, sensor2 */
44 static u8 LIMIT_REG[3]   = {0x6b, 0x6a, 0x6c}; /* local, sensor1, sensor2 */
45 static u8 MANUAL_MODE[2] = {0x5c, 0x5d};       
46 static u8 REM_CONTROL[2] = {0x00, 0x40};
47 static u8 FAN_SPEED[2]   = {0x28, 0x2a};
48 static u8 FAN_SPD_SET[2] = {0x30, 0x31};
49
50 static u8 default_limits_local[3] = {70, 50, 70};    /* local, sensor1, sensor2 */
51 static u8 default_limits_chip[3] = {80, 65, 80};    /* local, sensor1, sensor2 */
52 static const char *sensor_location[3] = { "?", "?", "?" };
53
54 static int limit_adjust;
55 static int fan_speed = -1;
56 static bool verbose;
57
58 MODULE_AUTHOR("Colin Leroy <colin@colino.net>");
59 MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
60                    "Powerbook G4 Alu");
61 MODULE_LICENSE("GPL");
62
63 module_param(limit_adjust, int, 0644);
64 MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 sensor1, 70 sensor2) "
65                  "by N degrees.");
66
67 module_param(fan_speed, int, 0644);
68 MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) "
69                  "(default 64)");
70
71 module_param(verbose, bool, 0);
72 MODULE_PARM_DESC(verbose,"Verbose log operations "
73                  "(default 0)");
74
75 struct thermostat {
76         struct i2c_client       *clt;
77         u8                      temps[3];
78         u8                      cached_temp[3];
79         u8                      initial_limits[3];
80         u8                      limits[3];
81         int                     last_speed[2];
82         int                     last_var[2];
83         int                     pwm_inv[2];
84         struct task_struct      *thread;
85         struct platform_device  *pdev;
86         enum {
87                 ADT7460,
88                 ADT7467
89         }                       type;
90 };
91
92 static void write_both_fan_speed(struct thermostat *th, int speed);
93 static void write_fan_speed(struct thermostat *th, int speed, int fan);
94
95 static int
96 write_reg(struct thermostat* th, int reg, u8 data)
97 {
98         u8 tmp[2];
99         int rc;
100         
101         tmp[0] = reg;
102         tmp[1] = data;
103         rc = i2c_master_send(th->clt, (const char *)tmp, 2);
104         if (rc < 0)
105                 return rc;
106         if (rc != 2)
107                 return -ENODEV;
108         return 0;
109 }
110
111 static int
112 read_reg(struct thermostat* th, int reg)
113 {
114         u8 reg_addr, data;
115         int rc;
116
117         reg_addr = (u8)reg;
118         rc = i2c_master_send(th->clt, &reg_addr, 1);
119         if (rc < 0)
120                 return rc;
121         if (rc != 1)
122                 return -ENODEV;
123         rc = i2c_master_recv(th->clt, (char *)&data, 1);
124         if (rc < 0)
125                 return rc;
126         return data;
127 }
128
129 static int read_fan_speed(struct thermostat *th, u8 addr)
130 {
131         u8 tmp[2];
132         u16 res;
133         
134         /* should start with low byte */
135         tmp[1] = read_reg(th, addr);
136         tmp[0] = read_reg(th, addr + 1);
137         
138         res = tmp[1] + (tmp[0] << 8);
139         /* "a value of 0xffff means that the fan has stopped" */
140         return (res == 0xffff ? 0 : (90000*60)/res);
141 }
142
143 static void write_both_fan_speed(struct thermostat *th, int speed)
144 {
145         write_fan_speed(th, speed, 0);
146         if (th->type == ADT7460)
147                 write_fan_speed(th, speed, 1);
148 }
149
150 static void write_fan_speed(struct thermostat *th, int speed, int fan)
151 {
152         u8 manual;
153         
154         if (speed > 0xff) 
155                 speed = 0xff;
156         else if (speed < -1) 
157                 speed = 0;
158         
159         if (th->type == ADT7467 && fan == 1)
160                 return;
161         
162         if (th->last_speed[fan] != speed) {
163                 if (verbose) {
164                         if (speed == -1)
165                                 printk(KERN_DEBUG "adt746x: Setting speed to automatic "
166                                         "for %s fan.\n", sensor_location[fan+1]);
167                         else
168                                 printk(KERN_DEBUG "adt746x: Setting speed to %d "
169                                         "for %s fan.\n", speed, sensor_location[fan+1]);
170                 }
171         } else
172                 return;
173         
174         if (speed >= 0) {
175                 manual = read_reg(th, MANUAL_MODE[fan]);
176                 manual &= ~INVERT_MASK;
177                 write_reg(th, MANUAL_MODE[fan],
178                         manual | MANUAL_MASK | th->pwm_inv[fan]);
179                 write_reg(th, FAN_SPD_SET[fan], speed);
180         } else {
181                 /* back to automatic */
182                 if(th->type == ADT7460) {
183                         manual = read_reg(th,
184                                 MANUAL_MODE[fan]) & (~MANUAL_MASK);
185                         manual &= ~INVERT_MASK;
186                         manual |= th->pwm_inv[fan];
187                         write_reg(th,
188                                 MANUAL_MODE[fan], manual|REM_CONTROL[fan]);
189                 } else {
190                         manual = read_reg(th, MANUAL_MODE[fan]);
191                         manual &= ~INVERT_MASK;
192                         manual |= th->pwm_inv[fan];
193                         write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK));
194                 }
195         }
196         
197         th->last_speed[fan] = speed;                    
198 }
199
200 static void read_sensors(struct thermostat *th)
201 {
202         int i = 0;
203
204         for (i = 0; i < 3; i++)
205                 th->temps[i]  = read_reg(th, TEMP_REG[i]);
206 }
207
208 #ifdef DEBUG
209 static void display_stats(struct thermostat *th)
210 {
211         if (th->temps[0] != th->cached_temp[0]
212         ||  th->temps[1] != th->cached_temp[1]
213         ||  th->temps[2] != th->cached_temp[2]) {
214                 printk(KERN_INFO "adt746x: Temperature infos:"
215                                  " thermostats: %d,%d,%d;"
216                                  " limits: %d,%d,%d;"
217                                  " fan speed: %d RPM\n",
218                                  th->temps[0], th->temps[1], th->temps[2],
219                                  th->limits[0],  th->limits[1],  th->limits[2],
220                                  read_fan_speed(th, FAN_SPEED[0]));
221         }
222         th->cached_temp[0] = th->temps[0];
223         th->cached_temp[1] = th->temps[1];
224         th->cached_temp[2] = th->temps[2];
225 }
226 #endif
227
228 static void update_fans_speed (struct thermostat *th)
229 {
230         int lastvar = 0; /* last variation, for iBook */
231         int i = 0;
232
233         /* we don't care about local sensor, so we start at sensor 1 */
234         for (i = 1; i < 3; i++) {
235                 bool started = false;
236                 int fan_number = (th->type == ADT7460 && i == 2);
237                 int var = th->temps[i] - th->limits[i];
238
239                 if (var > -1) {
240                         int step = (255 - fan_speed) / 7;
241                         int new_speed = 0;
242
243                         /* hysteresis : change fan speed only if variation is
244                          * more than two degrees */
245                         if (abs(var - th->last_var[fan_number]) < 2)
246                                 continue;
247
248                         started = true;
249                         new_speed = fan_speed + ((var-1)*step);
250
251                         if (new_speed < fan_speed)
252                                 new_speed = fan_speed;
253                         if (new_speed > 255)
254                                 new_speed = 255;
255
256                         if (verbose)
257                                 printk(KERN_DEBUG "adt746x: Setting fans speed to %d "
258                                                  "(limit exceeded by %d on %s)\n",
259                                                 new_speed, var,
260                                                 sensor_location[fan_number+1]);
261                         write_both_fan_speed(th, new_speed);
262                         th->last_var[fan_number] = var;
263                 } else if (var < -2) {
264                         /* don't stop fan if sensor2 is cold and sensor1 is not
265                          * so cold (lastvar >= -1) */
266                         if (i == 2 && lastvar < -1) {
267                                 if (th->last_speed[fan_number] != 0)
268                                         if (verbose)
269                                                 printk(KERN_DEBUG "adt746x: Stopping "
270                                                         "fans.\n");
271                                 write_both_fan_speed(th, 0);
272                         }
273                 }
274
275                 lastvar = var;
276
277                 if (started)
278                         return; /* we don't want to re-stop the fan
279                                 * if sensor1 is heating and sensor2 is not */
280         }
281 }
282
283 static int monitor_task(void *arg)
284 {
285         struct thermostat* th = arg;
286
287         set_freezable();
288         while(!kthread_should_stop()) {
289                 try_to_freeze();
290                 msleep_interruptible(2000);
291
292 #ifndef DEBUG
293                 if (fan_speed != -1)
294                         read_sensors(th);
295 #else
296                 read_sensors(th);
297 #endif          
298
299                 if (fan_speed != -1)
300                         update_fans_speed(th);
301
302 #ifdef DEBUG
303                 display_stats(th);
304 #endif
305
306         }
307
308         return 0;
309 }
310
311 static void set_limit(struct thermostat *th, int i)
312 {
313         /* Set sensor1 limit higher to avoid powerdowns */
314         th->limits[i] = default_limits_chip[i] + limit_adjust;
315         write_reg(th, LIMIT_REG[i], th->limits[i]);
316                 
317         /* set our limits to normal */
318         th->limits[i] = default_limits_local[i] + limit_adjust;
319 }
320
321 #define BUILD_SHOW_FUNC_INT(name, data)                         \
322 static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)        \
323 {                                                               \
324         struct thermostat *th = dev_get_drvdata(dev);           \
325         return sprintf(buf, "%d\n", data);                      \
326 }
327
328 #define BUILD_SHOW_FUNC_INT_LITE(name, data)                            \
329 static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)        \
330 {                                                               \
331         return sprintf(buf, "%d\n", data);                      \
332 }
333
334 #define BUILD_SHOW_FUNC_STR(name, data)                         \
335 static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)       \
336 {                                                               \
337         return sprintf(buf, "%s\n", data);                      \
338 }
339
340 #define BUILD_SHOW_FUNC_FAN(name, data)                         \
341 static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)       \
342 {                                                               \
343         struct thermostat *th = dev_get_drvdata(dev);           \
344         return sprintf(buf, "%d (%d rpm)\n",                    \
345                 th->last_speed[data],                           \
346                 read_fan_speed(th, FAN_SPEED[data])             \
347                 );                                              \
348 }
349
350 #define BUILD_STORE_FUNC_DEG(name, data)                        \
351 static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
352 {                                                               \
353         struct thermostat *th = dev_get_drvdata(dev);           \
354         int val;                                                \
355         int i;                                                  \
356         val = simple_strtol(buf, NULL, 10);                     \
357         printk(KERN_INFO "Adjusting limits by %d degrees\n", val);      \
358         limit_adjust = val;                                     \
359         for (i=0; i < 3; i++)                                   \
360                 set_limit(th, i);                               \
361         return n;                                               \
362 }
363
364 #define BUILD_STORE_FUNC_INT(name, data)                        \
365 static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
366 {                                                               \
367         int val;                                                \
368         val = simple_strtol(buf, NULL, 10);                     \
369         if (val < 0 || val > 255)                               \
370                 return -EINVAL;                                 \
371         printk(KERN_INFO "Setting specified fan speed to %d\n", val);   \
372         data = val;                                             \
373         return n;                                               \
374 }
375
376 BUILD_SHOW_FUNC_INT(sensor1_temperature,         (read_reg(th, TEMP_REG[1])))
377 BUILD_SHOW_FUNC_INT(sensor2_temperature,         (read_reg(th, TEMP_REG[2])))
378 BUILD_SHOW_FUNC_INT(sensor1_limit,               th->limits[1])
379 BUILD_SHOW_FUNC_INT(sensor2_limit,               th->limits[2])
380 BUILD_SHOW_FUNC_STR(sensor1_location,            sensor_location[1])
381 BUILD_SHOW_FUNC_STR(sensor2_location,            sensor_location[2])
382
383 BUILD_SHOW_FUNC_INT_LITE(specified_fan_speed, fan_speed)
384 BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed)
385
386 BUILD_SHOW_FUNC_FAN(sensor1_fan_speed,   0)
387 BUILD_SHOW_FUNC_FAN(sensor2_fan_speed,   1)
388
389 BUILD_SHOW_FUNC_INT_LITE(limit_adjust,   limit_adjust)
390 BUILD_STORE_FUNC_DEG(limit_adjust,       th)
391                 
392 static DEVICE_ATTR(sensor1_temperature, S_IRUGO,
393                    show_sensor1_temperature,NULL);
394 static DEVICE_ATTR(sensor2_temperature, S_IRUGO,
395                    show_sensor2_temperature,NULL);
396 static DEVICE_ATTR(sensor1_limit, S_IRUGO,
397                    show_sensor1_limit,  NULL);
398 static DEVICE_ATTR(sensor2_limit, S_IRUGO,
399                    show_sensor2_limit,  NULL);
400 static DEVICE_ATTR(sensor1_location, S_IRUGO,
401                    show_sensor1_location, NULL);
402 static DEVICE_ATTR(sensor2_location, S_IRUGO,
403                    show_sensor2_location, NULL);
404
405 static DEVICE_ATTR(specified_fan_speed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
406                    show_specified_fan_speed,store_specified_fan_speed);
407
408 static DEVICE_ATTR(sensor1_fan_speed,   S_IRUGO,
409                    show_sensor1_fan_speed,      NULL);
410 static DEVICE_ATTR(sensor2_fan_speed,   S_IRUGO,
411                    show_sensor2_fan_speed,      NULL);
412
413 static DEVICE_ATTR(limit_adjust,        S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
414                    show_limit_adjust,   store_limit_adjust);
415
416 static void thermostat_create_files(struct thermostat *th)
417 {
418         struct device_node *np = th->clt->dev.of_node;
419         struct device *dev;
420         int err;
421
422         /* To maintain ABI compatibility with userspace, create
423          * the old style platform driver and attach the attributes
424          * to it here
425          */
426         th->pdev = of_platform_device_create(np, "temperatures", NULL);
427         if (!th->pdev)
428                 return;
429         dev = &th->pdev->dev;
430         dev_set_drvdata(dev, th);
431         err = device_create_file(dev, &dev_attr_sensor1_temperature);
432         err |= device_create_file(dev, &dev_attr_sensor2_temperature);
433         err |= device_create_file(dev, &dev_attr_sensor1_limit);
434         err |= device_create_file(dev, &dev_attr_sensor2_limit);
435         err |= device_create_file(dev, &dev_attr_sensor1_location);
436         err |= device_create_file(dev, &dev_attr_sensor2_location);
437         err |= device_create_file(dev, &dev_attr_limit_adjust);
438         err |= device_create_file(dev, &dev_attr_specified_fan_speed);
439         err |= device_create_file(dev, &dev_attr_sensor1_fan_speed);
440         if(th->type == ADT7460)
441                 err |= device_create_file(dev, &dev_attr_sensor2_fan_speed);
442         if (err)
443                 printk(KERN_WARNING
444                         "Failed to create temperature attribute file(s).\n");
445 }
446
447 static void thermostat_remove_files(struct thermostat *th)
448 {
449         struct device *dev;
450
451         if (!th->pdev)
452                 return;
453         dev = &th->pdev->dev;
454         device_remove_file(dev, &dev_attr_sensor1_temperature);
455         device_remove_file(dev, &dev_attr_sensor2_temperature);
456         device_remove_file(dev, &dev_attr_sensor1_limit);
457         device_remove_file(dev, &dev_attr_sensor2_limit);
458         device_remove_file(dev, &dev_attr_sensor1_location);
459         device_remove_file(dev, &dev_attr_sensor2_location);
460         device_remove_file(dev, &dev_attr_limit_adjust);
461         device_remove_file(dev, &dev_attr_specified_fan_speed);
462         device_remove_file(dev, &dev_attr_sensor1_fan_speed);   
463         if (th->type == ADT7460)
464                 device_remove_file(dev, &dev_attr_sensor2_fan_speed);
465         of_device_unregister(th->pdev);
466
467 }
468
469 static int probe_thermostat(struct i2c_client *client)
470 {
471         const struct i2c_device_id *id = i2c_client_get_device_id(client);
472         struct device_node *np = client->dev.of_node;
473         struct thermostat* th;
474         const __be32 *prop;
475         int i, rc, vers, offset = 0;
476
477         if (!np)
478                 return -ENXIO;
479         prop = of_get_property(np, "hwsensor-params-version", NULL);
480         if (!prop)
481                 return -ENXIO;
482         vers = be32_to_cpup(prop);
483         printk(KERN_INFO "adt746x: version %d (%ssupported)\n",
484                vers, vers == 1 ? "" : "un");
485         if (vers != 1)
486                 return -ENXIO;
487
488         if (of_property_present(np, "hwsensor-location")) {
489                 for (i = 0; i < 3; i++) {
490                         sensor_location[i] = of_get_property(np,
491                                         "hwsensor-location", NULL) + offset;
492
493                         if (sensor_location[i] == NULL)
494                                 sensor_location[i] = "";
495
496                         printk(KERN_INFO "sensor %d: %s\n", i, sensor_location[i]);
497                         offset += strlen(sensor_location[i]) + 1;
498                 }
499         }
500
501         th = kzalloc(sizeof(struct thermostat), GFP_KERNEL);
502         if (!th)
503                 return -ENOMEM;
504
505         i2c_set_clientdata(client, th);
506         th->clt = client;
507         th->type = id->driver_data;
508
509         rc = read_reg(th, CONFIG_REG);
510         if (rc < 0) {
511                 dev_err(&client->dev, "Thermostat failed to read config!\n");
512                 kfree(th);
513                 return -ENODEV;
514         }
515
516         /* force manual control to start the fan quieter */
517         if (fan_speed == -1)
518                 fan_speed = 64;
519         
520         if (th->type == ADT7460) {
521                 printk(KERN_INFO "adt746x: ADT7460 initializing\n");
522                 /* The 7460 needs to be started explicitly */
523                 write_reg(th, CONFIG_REG, 1);
524         } else
525                 printk(KERN_INFO "adt746x: ADT7467 initializing\n");
526
527         for (i = 0; i < 3; i++) {
528                 th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
529                 set_limit(th, i);
530         }
531
532         printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
533                          " to %d, %d, %d\n",
534                          th->initial_limits[0], th->initial_limits[1],
535                          th->initial_limits[2], th->limits[0], th->limits[1],
536                          th->limits[2]);
537
538         /* record invert bit status because fw can corrupt it after suspend */
539         th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK;
540         th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK;
541
542         /* be sure to really write fan speed the first time */
543         th->last_speed[0] = -2;
544         th->last_speed[1] = -2;
545         th->last_var[0] = -80;
546         th->last_var[1] = -80;
547
548         if (fan_speed != -1) {
549                 /* manual mode, stop fans */
550                 write_both_fan_speed(th, 0);
551         } else {
552                 /* automatic mode */
553                 write_both_fan_speed(th, -1);
554         }
555         
556         th->thread = kthread_run(monitor_task, th, "kfand");
557         if (th->thread == ERR_PTR(-ENOMEM)) {
558                 printk(KERN_INFO "adt746x: Kthread creation failed\n");
559                 th->thread = NULL;
560                 return -ENOMEM;
561         }
562
563         thermostat_create_files(th);
564
565         return 0;
566 }
567
568 static void remove_thermostat(struct i2c_client *client)
569 {
570         struct thermostat *th = i2c_get_clientdata(client);
571         int i;
572         
573         thermostat_remove_files(th);
574
575         if (th->thread != NULL)
576                 kthread_stop(th->thread);
577
578         printk(KERN_INFO "adt746x: Putting max temperatures back from "
579                          "%d, %d, %d to %d, %d, %d\n",
580                 th->limits[0], th->limits[1], th->limits[2],
581                 th->initial_limits[0], th->initial_limits[1],
582                 th->initial_limits[2]);
583
584         for (i = 0; i < 3; i++)
585                 write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
586
587         write_both_fan_speed(th, -1);
588
589         kfree(th);
590 }
591
592 static const struct i2c_device_id therm_adt746x_id[] = {
593         { "MAC,adt7460", ADT7460 },
594         { "MAC,adt7467", ADT7467 },
595         { }
596 };
597 MODULE_DEVICE_TABLE(i2c, therm_adt746x_id);
598
599 static struct i2c_driver thermostat_driver = {
600         .driver = {
601                 .name   = "therm_adt746x",
602         },
603         .probe = probe_thermostat,
604         .remove = remove_thermostat,
605         .id_table = therm_adt746x_id,
606 };
607
608 static int __init thermostat_init(void)
609 {
610 #ifndef CONFIG_I2C_POWERMAC
611         request_module("i2c-powermac");
612 #endif
613
614         return i2c_add_driver(&thermostat_driver);
615 }
616
617 static void __exit thermostat_exit(void)
618 {
619         i2c_del_driver(&thermostat_driver);
620 }
621
622 module_init(thermostat_init);
623 module_exit(thermostat_exit);