Update copyrights
[linux-2.6.git] / drivers / misc / nct1008.c
1 /*
2  * drivers/misc/nct1008.c
3  *
4  * Driver for NCT1008, temperature monitoring device from ON Semiconductors
5  *
6  * Copyright (c) 2010-2011, NVIDIA Corporation.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22
23
24 #include <linux/interrupt.h>
25 #include <linux/mutex.h>
26 #include <linux/module.h>
27 #include <linux/i2c.h>
28 #include <linux/slab.h>
29 #include <linux/err.h>
30 #include <linux/gpio.h>
31 #include <linux/device.h>
32
33 #include <linux/nct1008.h>
34
35 #define DRIVER_NAME "nct1008"
36
37 /* Register Addresses */
38 #define LOCAL_TEMP_RD                   0x00
39 #define EXT_TEMP_RD_HI                  0x01
40 #define EXT_TEMP_RD_LO                  0x10
41 #define STATUS_RD                       0x02
42 #define CONFIG_RD                       0x03
43
44 #define LOCAL_TEMP_HI_LIMIT_RD          0x05
45
46 #define EXT_TEMP_HI_LIMIT_HI_BYTE_RD    0x07
47
48 #define CONFIG_WR                       0x09
49 #define CONV_RATE_WR                    0x0A
50 #define LOCAL_TEMP_HI_LIMIT_WR          0x0B
51 #define EXT_TEMP_HI_LIMIT_HI_BYTE_WR    0x0D
52 #define EXT_TEMP_RD_LOW                 0x10
53 #define OFFSET_WR                       0x11
54 #define EXT_THERM_LIMIT_WR              0x19
55 #define LOCAL_THERM_LIMIT_WR            0x20
56 #define THERM_HYSTERESIS_WR             0x21
57
58 /* Configuration Register Bits */
59 #define EXTENDED_RANGE_BIT              (0x1 << 2)
60 #define THERM2_BIT                      (0x1 << 5)
61 #define STANDBY_BIT                     (0x1 << 6)
62
63 /* Max Temperature Measurements */
64 #define EXTENDED_RANGE_OFFSET           64U
65 #define STANDARD_RANGE_MAX              127U
66 #define EXTENDED_RANGE_MAX              (150U + EXTENDED_RANGE_OFFSET)
67
68 #define NCT1008_MIN_TEMP -64
69 #define NCT1008_MAX_TEMP 191
70
71 #define MAX_STR_PRINT 50
72
73 struct nct1008_data {
74         struct work_struct work;
75         struct i2c_client *client;
76         struct nct1008_platform_data plat_data;
77         struct mutex mutex;
78         u8 config;
79         void (*alarm_fn)(bool raised);
80 };
81
82 static inline u8 value_to_temperature(bool extended, u8 value)
83 {
84         return extended ? (u8)(value - EXTENDED_RANGE_OFFSET) : value;
85 }
86
87 static inline u8 temperature_to_value(bool extended, u8 temp)
88 {
89         return extended ? (u8)(temp + EXTENDED_RANGE_OFFSET) : temp;
90 }
91
92 static int nct1008_get_temp(struct device *dev, u8 *pTemp)
93 {
94         struct i2c_client *client = to_i2c_client(dev);
95         struct nct1008_platform_data *pdata = client->dev.platform_data;
96         u8 temp1, temp2, temp;
97         u8 value;
98         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD);
99         if (value < 0)
100                 goto error;
101         temp1 = value_to_temperature(pdata->ext_range, value);
102
103         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LOW);
104         if (value < 0)
105                 goto error;
106         temp2 = (value >> 6);
107         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
108         if (value < 0)
109                 goto error;
110         temp = value_to_temperature(pdata->ext_range, value);
111         if (temp2 > 0) {
112                 if (temp1 > (temp + 1))
113                         *pTemp = temp1;
114                 else
115                         *pTemp = (temp + 1);
116         } else {
117                 if (temp1 > temp)
118                         *pTemp = temp1;
119                 else
120                         *pTemp = temp;
121         }
122         return 0;
123 error:
124         dev_err(&client->dev, "\n error in file=: %s %s() line=%d: "
125                 "error=%d ", __FILE__, __func__, __LINE__, value);
126         return value;
127 }
128
129 static ssize_t nct1008_show_temp(struct device *dev,
130         struct device_attribute *attr, char *buf)
131 {
132         struct i2c_client *client = to_i2c_client(dev);
133         struct nct1008_platform_data *pdata = client->dev.platform_data;
134         u8 temp1 = 0;
135         u8 temp = 0;
136         u8 temp2 = 0;
137         u8 value;
138
139         if (!dev || !buf || !attr)
140                 return -EINVAL;
141
142         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD);
143         if (value < 0)
144                 goto error;
145         temp1 = value_to_temperature(pdata->ext_range, value);
146
147         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LOW);
148         if (value < 0)
149                 goto error;
150         temp2 = (value >> 6);
151         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
152         if (value < 0)
153                 goto error;
154         temp = value_to_temperature(pdata->ext_range, value);
155         if (temp2 > 0) {
156                 if (temp2 == 1)
157                         return snprintf(buf, MAX_STR_PRINT, "%d %d.25\n",
158                                 temp1, temp);
159                 else if (temp2 == 2)
160                         return snprintf(buf, MAX_STR_PRINT, "%d %d.5\n",
161                                 temp1, temp);
162                 else if (temp2 == 3)
163                         return snprintf(buf, MAX_STR_PRINT, "%d %d.75\n",
164                                 temp1, temp);
165         } else {
166                 return snprintf(buf, MAX_STR_PRINT, "%d %d.0\n",
167                         temp1, temp);
168         }
169 error:
170         snprintf(buf, MAX_STR_PRINT, " Rd Error\n");
171         return value;
172 }
173
174 static ssize_t nct1008_show_temp_overheat(struct device *dev,
175                                 struct device_attribute *attr,
176                                 char *buf)
177 {
178         struct i2c_client *client = to_i2c_client(dev);
179         struct nct1008_platform_data *pdata = client->dev.platform_data;
180         u8 value;
181         u8 temp, temp2;
182
183         /* Local temperature h/w shutdown limit */
184         value = i2c_smbus_read_byte_data(client, LOCAL_THERM_LIMIT_WR);
185         if (value < 0)
186                 goto error;
187         temp = value_to_temperature(pdata->ext_range, value);
188
189         /* External temperature h/w shutdown limit */
190         value = i2c_smbus_read_byte_data(client, EXT_THERM_LIMIT_WR);
191         if (value < 0)
192                 goto error;
193         temp2 = value_to_temperature(pdata->ext_range, value);
194
195         return snprintf(buf, MAX_STR_PRINT, "%d %d\n", temp, temp2);
196 error:
197         snprintf(buf, MAX_STR_PRINT, " Rd overheat Error\n");
198         dev_err(dev, "%s: failed to read temperature-overheat "
199                 "\n", __func__);
200         return value;
201 }
202
203 static ssize_t nct1008_set_temp_overheat(struct device *dev,
204                         struct device_attribute *attr,
205                         const char *buf, size_t count)
206 {
207         long int num;
208         int err;
209         u8 temp;
210         u8 currTemp;
211         struct i2c_client *client = to_i2c_client(dev);
212         struct nct1008_platform_data *pdata = client->dev.platform_data;
213         char bufTemp[MAX_STR_PRINT];
214         char bufOverheat[MAX_STR_PRINT];
215         unsigned int ret;
216
217         if (strict_strtoul(buf, 0, &num)) {
218                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
219                         __LINE__, __func__);
220                 return -EINVAL;
221         }
222         if (((int)num < NCT1008_MIN_TEMP) || ((int)num >= NCT1008_MAX_TEMP)) {
223                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
224                         __LINE__, __func__);
225                 return -EINVAL;
226         }
227         /* check for system power down */
228         err = nct1008_get_temp(dev, &currTemp);
229         if (err < 0)
230                 goto error;
231
232         if (currTemp >= (int)num) {
233                 ret = nct1008_show_temp(dev, attr, bufTemp);
234                 ret = nct1008_show_temp_overheat(dev, attr, bufOverheat);
235                 dev_err(dev, "\nCurrent temp: %s ", bufTemp);
236                 dev_err(dev, "\nOld overheat limit: %s ", bufOverheat);
237                 dev_err(dev, "\nReset from overheat: curr temp=%d, "
238                         "new overheat temp=%d\n\n", currTemp, (int)num);
239         }
240
241         /* External temperature h/w shutdown limit */
242         temp = temperature_to_value(pdata->ext_range, (u8)num);
243         err = i2c_smbus_write_byte_data(client, EXT_THERM_LIMIT_WR, temp);
244         if (err < 0)
245                 goto error;
246
247         /* Local temperature h/w shutdown limit */
248         temp = temperature_to_value(pdata->ext_range, (u8)num);
249         err = i2c_smbus_write_byte_data(client, LOCAL_THERM_LIMIT_WR, temp);
250         if (err < 0)
251                 goto error;
252         return count;
253 error:
254         dev_err(dev, " %s: failed to set temperature-overheat\n", __func__);
255         return err;
256 }
257
258 static ssize_t nct1008_show_temp_alert(struct device *dev,
259                                 struct device_attribute *attr,
260                                 char *buf)
261 {
262         struct i2c_client *client = to_i2c_client(dev);
263         struct nct1008_platform_data *pdata = client->dev.platform_data;
264         u8 value;
265         u8 temp, temp2;
266         /* External Temperature Throttling limit */
267         value = i2c_smbus_read_byte_data(client, EXT_TEMP_HI_LIMIT_HI_BYTE_RD);
268         if (value < 0)
269                 goto error;
270         temp2 = value_to_temperature(pdata->ext_range, value);
271
272         /* Local Temperature Throttling limit */
273         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_HI_LIMIT_RD);
274         if (value < 0)
275                 goto error;
276         temp = value_to_temperature(pdata->ext_range, value);
277
278         return snprintf(buf, MAX_STR_PRINT, "%d %d\n", temp, temp2);
279 error:
280         snprintf(buf, MAX_STR_PRINT, " Rd overheat Error\n");
281         dev_err(dev, "%s: failed to read temperature-overheat "
282                 "\n", __func__);
283         return value;
284 }
285
286 static ssize_t nct1008_set_temp_alert(struct device *dev,
287                         struct device_attribute *attr,
288                         const char *buf, size_t count)
289 {
290         long int num;
291         int value;
292         int err;
293         struct i2c_client *client = to_i2c_client(dev);
294         struct nct1008_platform_data *pdata = client->dev.platform_data;
295
296         if (strict_strtoul(buf, 0, &num)) {
297                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
298                         __LINE__, __func__);
299                 return -EINVAL;
300         }
301         if (((int)num < NCT1008_MIN_TEMP) || ((int)num >= NCT1008_MAX_TEMP)) {
302                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
303                         __LINE__, __func__);
304                 return -EINVAL;
305         }
306
307         /* External Temperature Throttling limit */
308         value = temperature_to_value(pdata->ext_range, num);
309         err = i2c_smbus_write_byte_data(client, EXT_TEMP_HI_LIMIT_HI_BYTE_WR,
310                 value);
311         if (err < 0)
312                 goto error;
313
314         /* Local Temperature Throttling limit */
315         err = i2c_smbus_write_byte_data(client, LOCAL_TEMP_HI_LIMIT_WR,
316                 value);
317         if (err < 0)
318                 goto error;
319
320         return count;
321 error:
322         dev_err(dev, "%s: failed to set temperature-alert "
323                 "\n", __func__);
324         return err;
325 }
326
327 static ssize_t nct1008_show_ext_temp(struct device *dev,
328         struct device_attribute *attr, char *buf)
329 {
330         struct i2c_client *client = to_i2c_client(dev);
331         signed int temp_value = 0;
332         u8 data = 0;
333
334         if (!dev || !buf || !attr)
335                 return -EINVAL;
336
337         data = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
338         if (data < 0) {
339                 dev_err(&client->dev, "%s: failed to read "
340                         "ext_temperature\n", __func__);
341                 return -EINVAL;
342         }
343
344         temp_value = (signed int)data;
345
346         data = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LO);
347
348         return sprintf(buf, "%d.%d\n", temp_value, (25 * (data >> 6)));
349 }
350
351 static DEVICE_ATTR(temperature, S_IRUGO, nct1008_show_temp, NULL);
352 static DEVICE_ATTR(temperature_overheat, (S_IRUGO | (S_IWUSR | S_IWGRP)),
353                 nct1008_show_temp_overheat, nct1008_set_temp_overheat);
354 static DEVICE_ATTR(temperature_alert, (S_IRUGO | (S_IWUSR | S_IWGRP)),
355                 nct1008_show_temp_alert, nct1008_set_temp_alert);
356 static DEVICE_ATTR(ext_temperature, S_IRUGO, nct1008_show_ext_temp, NULL);
357
358 static struct attribute *nct1008_attributes[] = {
359         &dev_attr_temperature.attr,
360         &dev_attr_temperature_overheat.attr,
361         &dev_attr_temperature_alert.attr,
362         &dev_attr_ext_temperature.attr,
363         NULL
364 };
365
366 static const struct attribute_group nct1008_attr_group = {
367         .attrs = nct1008_attributes,
368 };
369
370 static void nct1008_enable(struct i2c_client *client)
371 {
372         struct nct1008_data *data = i2c_get_clientdata(client);
373
374         i2c_smbus_write_byte_data(client, CONFIG_WR,
375                                   data->config & ~STANDBY_BIT);
376 }
377
378 static void nct1008_disable(struct i2c_client *client)
379 {
380         struct nct1008_data *data = i2c_get_clientdata(client);
381
382         i2c_smbus_write_byte_data(client, CONFIG_WR,
383                                   data->config | STANDBY_BIT);
384 }
385
386 static void nct1008_work_func(struct work_struct *work)
387 {
388         struct nct1008_data *data = container_of(work, struct nct1008_data,
389                                                 work);
390         int irq = data->client->irq;
391
392         mutex_lock(&data->mutex);
393
394         if (data->alarm_fn) {
395                 /* Therm2 line is active low */
396                 data->alarm_fn(!gpio_get_value(irq_to_gpio(irq)));
397         }
398
399         mutex_unlock(&data->mutex);
400 }
401
402 static irqreturn_t nct1008_irq(int irq, void *dev_id)
403 {
404         struct nct1008_data *data = dev_id;
405         schedule_work(&data->work);
406
407         return IRQ_HANDLED;
408 }
409
410 static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
411 {
412         struct i2c_client *client           = data->client;
413         struct nct1008_platform_data *pdata = client->dev.platform_data;
414         u8 value;
415         int err;
416         u8 temp;
417         u8 temp2;
418
419         if (!pdata || !pdata->supported_hwrev)
420                 return -ENODEV;
421
422         /*
423          * Initial Configuration - device is placed in standby and
424          * ALERT/THERM2 pin is configured as THERM2
425          */
426         data->config = value = pdata->ext_range ?
427                 (STANDBY_BIT | THERM2_BIT | EXTENDED_RANGE_BIT) :
428                 (STANDBY_BIT | THERM2_BIT);
429
430         err = i2c_smbus_write_byte_data(client, CONFIG_WR, value);
431         if (err < 0)
432                 goto error;
433
434         /* Temperature conversion rate */
435         err = i2c_smbus_write_byte_data(client, CONV_RATE_WR, pdata->conv_rate);
436         if (err < 0)
437                 goto error;
438
439         /* External temperature h/w shutdown limit */
440         value = temperature_to_value(pdata->ext_range,
441                         pdata->shutdown_ext_limit);
442         err = i2c_smbus_write_byte_data(client, EXT_THERM_LIMIT_WR, value);
443         if (err < 0)
444                 goto error;
445
446         /* Local temperature h/w shutdown limit */
447         value = temperature_to_value(pdata->ext_range,
448                         pdata->shutdown_local_limit);
449         err = i2c_smbus_write_byte_data(client, LOCAL_THERM_LIMIT_WR, value);
450         if (err < 0)
451                 goto error;
452
453         /* External Temperature Throttling limit */
454         value = temperature_to_value(pdata->ext_range,
455                         pdata->throttling_ext_limit);
456         err = i2c_smbus_write_byte_data(client, EXT_TEMP_HI_LIMIT_HI_BYTE_WR,
457                         value);
458         if (err < 0)
459                 goto error;
460
461         /* Local Temperature Throttling limit */
462         /* Local and remote Temperature Throttling limit kept same */
463         /*
464         value = pdata->ext_range ? EXTENDED_RANGE_MAX : STANDARD_RANGE_MAX;
465         */
466         err = i2c_smbus_write_byte_data(client, LOCAL_TEMP_HI_LIMIT_WR,
467                         value);
468         if (err < 0)
469                 goto error;
470
471         /* read initial temperature */
472         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD);
473         if (value < 0) {
474                 err = value;
475                 goto error;
476         }
477         temp = value_to_temperature(pdata->ext_range, value);
478         dev_dbg(&client->dev, "\n initial local temp read=%d ", temp);
479
480         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LOW);
481         if (value < 0) {
482                 err = value;
483                 goto error;
484         }
485         temp2 = (value >> 6);
486         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
487         if (value < 0) {
488                 err = value;
489                 goto error;
490         }
491         temp = value_to_temperature(pdata->ext_range, value);
492
493         if (temp2 > 0) {
494                 if (temp2 == 1)
495                         dev_dbg(&client->dev, "\n initial external temp "
496                                 "read=%d.25 deg ", temp);
497                 else if (temp2 == 2)
498                         dev_dbg(&client->dev, "\n initial external temp "
499                                 "read=%d.5 deg ", temp);
500                 else if (temp2 == 3)
501                         dev_dbg(&client->dev, "\n initial external temp "
502                                 "read=%d.75 deg ", temp);
503         } else {
504                 dev_dbg(&client->dev, "\n initial external temp read=%d.0 deg ",
505                         temp);
506         }
507
508         /* Remote channel offset */
509         err = i2c_smbus_write_byte_data(client, OFFSET_WR, pdata->offset);
510         if (err < 0)
511                 goto error;
512
513         /* THERM hysteresis */
514         err = i2c_smbus_write_byte_data(client, THERM_HYSTERESIS_WR,
515                         pdata->hysteresis);
516         if (err < 0)
517                 goto error;
518
519         /* register sysfs hooks */
520         err = sysfs_create_group(&client->dev.kobj, &nct1008_attr_group);
521         if (err < 0) {
522                 dev_err(&client->dev, "\n sysfs create err=%d ", err);
523                 goto error;
524         }
525
526         data->alarm_fn = pdata->alarm_fn;
527         return 0;
528 error:
529         dev_err(&client->dev, "\n exit %s, err=%d ", __func__, err);
530         return err;
531 }
532
533 static int __devinit nct1008_configure_irq(struct nct1008_data *data)
534 {
535         INIT_WORK(&data->work, nct1008_work_func);
536
537         if (data->client->irq < 0)
538                 return 0;
539         else
540                 return request_irq(data->client->irq, nct1008_irq,
541                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
542                         DRIVER_NAME, data);
543 }
544
545 static int __devinit nct1008_probe(struct i2c_client *client,
546                                 const struct i2c_device_id *id)
547 {
548         struct nct1008_data *data;
549         int err;
550
551         data = kzalloc(sizeof(struct nct1008_data), GFP_KERNEL);
552
553         if (!data)
554                 return -ENOMEM;
555
556         data->client = client;
557         i2c_set_clientdata(client, data);
558         mutex_init(&data->mutex);
559
560         err = nct1008_configure_sensor(data);   /* sensor is in standby */
561         if (err < 0) {
562                 dev_err(&client->dev, "\n error file: %s : %s(), line=%d ",
563                         __FILE__, __func__, __LINE__);
564                 goto error;
565         }
566
567         err = nct1008_configure_irq(data);
568         if (err < 0) {
569                 dev_err(&client->dev, "\n error file: %s : %s(), line=%d ",
570                         __FILE__, __func__, __LINE__);
571                 goto error;
572         }
573         dev_info(&client->dev, "%s: initialized\n", __func__);
574
575         nct1008_enable(client);         /* sensor is running */
576
577         schedule_work(&data->work);             /* check initial state */
578
579         return 0;
580
581 error:
582         dev_err(&client->dev, "\n exit %s, err=%d ", __func__, err);
583         kfree(data);
584         return err;
585 }
586
587 static int __devexit nct1008_remove(struct i2c_client *client)
588 {
589         struct nct1008_data *data = i2c_get_clientdata(client);
590
591         free_irq(data->client->irq, data);
592         cancel_work_sync(&data->work);
593         sysfs_remove_group(&client->dev.kobj, &nct1008_attr_group);
594         kfree(data);
595
596         return 0;
597 }
598
599 #ifdef CONFIG_PM
600 static int nct1008_suspend(struct i2c_client *client, pm_message_t state)
601 {
602         disable_irq(client->irq);
603         nct1008_disable(client);
604
605         return 0;
606 }
607
608 static int nct1008_resume(struct i2c_client *client)
609 {
610         struct nct1008_data *data = i2c_get_clientdata(client);
611
612         nct1008_enable(client);
613         enable_irq(client->irq);
614         schedule_work(&data->work);
615
616         return 0;
617 }
618 #endif
619
620 static const struct i2c_device_id nct1008_id[] = {
621         { DRIVER_NAME, 0 },
622         { }
623 };
624 MODULE_DEVICE_TABLE(i2c, nct1008_id);
625
626 static struct i2c_driver nct1008_driver = {
627         .driver = {
628                 .name   = DRIVER_NAME,
629         },
630         .probe          = nct1008_probe,
631         .remove         = __devexit_p(nct1008_remove),
632         .id_table       = nct1008_id,
633 #ifdef CONFIG_PM
634         .suspend        = nct1008_suspend,
635         .resume         = nct1008_resume,
636 #endif
637 };
638
639 static int __init nct1008_init(void)
640 {
641         return i2c_add_driver(&nct1008_driver);
642 }
643
644 static void __exit nct1008_exit(void)
645 {
646         i2c_del_driver(&nct1008_driver);
647 }
648
649 MODULE_DESCRIPTION("Temperature sensor driver for OnSemi NCT1008");
650 MODULE_LICENSE("GPL");
651
652 module_init (nct1008_init);
653 module_exit (nct1008_exit);