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