arm: tegra: power: Improved thermal accuracy
[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 #include <linux/nct1008.h>
33 #include <linux/delay.h>
34 #include <linux/regulator/consumer.h>
35
36 #define DRIVER_NAME "nct1008"
37
38 /* Register Addresses */
39 #define LOCAL_TEMP_RD                   0x00
40 #define EXT_TEMP_RD_HI                  0x01
41 #define EXT_TEMP_RD_LO                  0x10
42 #define STATUS_RD                       0x02
43 #define CONFIG_RD                       0x03
44
45 #define LOCAL_TEMP_HI_LIMIT_RD          0x05
46 #define LOCAL_TEMP_LO_LIMIT_RD          0x06
47
48 #define EXT_TEMP_HI_LIMIT_HI_BYTE_RD    0x07
49
50 #define CONFIG_WR                       0x09
51 #define CONV_RATE_WR                    0x0A
52 #define LOCAL_TEMP_HI_LIMIT_WR          0x0B
53 #define LOCAL_TEMP_LO_LIMIT_WR          0x0C
54 #define EXT_TEMP_HI_LIMIT_HI_BYTE_WR    0x0D
55 #define EXT_TEMP_LO_LIMIT_HI_BYTE_WR    0x0E
56 #define OFFSET_WR                       0x11
57 #define OFFSET_QUARTER_WR               0x12
58 #define EXT_THERM_LIMIT_WR              0x19
59 #define LOCAL_THERM_LIMIT_WR            0x20
60 #define THERM_HYSTERESIS_WR             0x21
61
62 /* Configuration Register Bits */
63 #define EXTENDED_RANGE_BIT              BIT(2)
64 #define THERM2_BIT                      BIT(5)
65 #define STANDBY_BIT                     BIT(6)
66 #define ALERT_BIT                       BIT(7)
67
68 /* Status register bits */
69 #define STATUS_BUSY                     BIT(7)
70
71 /* Worst-case wait when nct1008 is busy */
72 #define BUSY_TIMEOUT_MSEC               1000
73
74 /* Max Temperature Measurements */
75 #define EXTENDED_RANGE_OFFSET           64U
76 #define STANDARD_RANGE_MAX              127U
77 #define EXTENDED_RANGE_MAX              (150U + EXTENDED_RANGE_OFFSET)
78
79 #define NCT1008_MIN_TEMP -64
80 #define NCT1008_MAX_TEMP 191
81
82 #define MAX_STR_PRINT 50
83
84 #define MIN_SLEEP_MSEC                  20
85 #define CELSIUS_TO_MILLICELSIUS(x) ((x)*1000)
86 #define MILLICELSIUS_TO_CELSIUS(x) ((x)/1000)
87
88 struct nct1008_data {
89         struct work_struct work;
90         struct i2c_client *client;
91         struct nct1008_platform_data plat_data;
92         struct mutex mutex;
93         struct dentry *dent;
94         u8 config;
95         s8 *limits;
96         u8 limits_sz;
97         void (*alarm_fn)(bool raised);
98         struct regulator *nct_reg;
99 };
100
101 static inline s8 value_to_temperature(bool extended, u8 value)
102 {
103         return extended ? (s8)(value - EXTENDED_RANGE_OFFSET) : (s8)value;
104 }
105
106 static inline u8 temperature_to_value(bool extended, s8 temp)
107 {
108         return extended ? (u8)(temp + EXTENDED_RANGE_OFFSET) : (u8)temp;
109 }
110
111 /* Wait with timeout if busy */
112 static int nct1008_wait_till_busy(struct i2c_client *client)
113 {
114         int intr_status;
115         int msec_left = BUSY_TIMEOUT_MSEC;
116         bool is_busy;
117
118         do {
119                 intr_status = i2c_smbus_read_byte_data(client, STATUS_RD);
120
121                 if (intr_status < 0) {
122                         dev_err(&client->dev, "%s, line=%d, i2c read error=%d\n"
123                                 , __func__, __LINE__, intr_status);
124                         return intr_status;
125                 }
126
127                 /* check for busy bit */
128                 is_busy = (intr_status & STATUS_BUSY) ? true : false;
129                 if (is_busy) {
130                         /* fastest nct1008 conversion rate ~15msec */
131                         /* using 20msec since msleep below 20 is not
132                          * guaranteed to complete in specified duration */
133                         msleep(MIN_SLEEP_MSEC);
134                         msec_left -= MIN_SLEEP_MSEC;
135                 }
136         } while ((is_busy) && (msec_left > 0));
137
138         if (msec_left <= 0) {
139                 dev_err(&client->dev, "error: nct1008 busy timed out\n");
140                 return -ETIMEDOUT;
141         }
142
143         return 0;
144 }
145
146 static int nct1008_get_temp(struct device *dev, long *pTemp)
147 {
148         struct i2c_client *client = to_i2c_client(dev);
149         struct nct1008_platform_data *pdata = client->dev.platform_data;
150         s8 temp_local;
151         u8 temp_ext_lo;
152         s8 temp_ext_hi;
153         long temp_ext_milli;
154         long temp_local_milli;
155         u8 value;
156
157         value = nct1008_wait_till_busy(client);
158         if (value < 0)
159                 goto error;
160
161         /* Read Local Temp */
162         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD);
163         if (value < 0)
164                 goto error;
165         temp_local = value_to_temperature(pdata->ext_range, value);
166         temp_local_milli = CELSIUS_TO_MILLICELSIUS(temp_local);
167
168         /* Read External Temp */
169         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LO);
170         if (value < 0)
171                 goto error;
172         temp_ext_lo = (value >> 6);
173
174         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
175         if (value < 0)
176                 goto error;
177         temp_ext_hi = value_to_temperature(pdata->ext_range, value);
178
179         temp_ext_milli = CELSIUS_TO_MILLICELSIUS(temp_ext_hi) +
180                                 temp_ext_lo * 250;
181
182         /* Return max between Local and External Temp */
183         *pTemp = max(temp_local_milli, temp_ext_milli);
184
185         dev_dbg(dev, "\n %s: ret temp=%ldC ", __func__, *pTemp);
186         return 0;
187 error:
188         dev_err(&client->dev, "\n error in file=: %s %s() line=%d: "
189                 "error=%d ", __FILE__, __func__, __LINE__, value);
190         return value;
191 }
192
193 static ssize_t nct1008_show_temp(struct device *dev,
194         struct device_attribute *attr, char *buf)
195 {
196         struct i2c_client *client = to_i2c_client(dev);
197         struct nct1008_platform_data *pdata = client->dev.platform_data;
198         s8 temp1 = 0;
199         s8 temp = 0;
200         u8 temp2 = 0;
201         int value = 0;
202
203         if (!dev || !buf || !attr)
204                 return -EINVAL;
205
206         value = nct1008_wait_till_busy(client);
207         if (value < 0)
208                 goto error;
209
210         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD);
211         if (value < 0)
212                 goto error;
213         temp1 = value_to_temperature(pdata->ext_range, value);
214
215         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LO);
216         if (value < 0)
217                 goto error;
218         temp2 = (value >> 6);
219         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
220         if (value < 0)
221                 goto error;
222         temp = value_to_temperature(pdata->ext_range, value);
223
224         return snprintf(buf, MAX_STR_PRINT, "%d %d.%d\n",
225                 temp1, temp, temp2 * 25);
226
227 error:
228         return snprintf(buf, MAX_STR_PRINT,
229                 "Error read local/ext temperature\n");
230 }
231
232 static ssize_t nct1008_show_temp_overheat(struct device *dev,
233                                 struct device_attribute *attr,
234                                 char *buf)
235 {
236         struct i2c_client *client = to_i2c_client(dev);
237         struct nct1008_platform_data *pdata = client->dev.platform_data;
238         int value;
239         s8 temp, temp2;
240
241         /* Local temperature h/w shutdown limit */
242         value = i2c_smbus_read_byte_data(client, LOCAL_THERM_LIMIT_WR);
243         if (value < 0)
244                 goto error;
245         temp = value_to_temperature(pdata->ext_range, value);
246
247         /* External temperature h/w shutdown limit */
248         value = i2c_smbus_read_byte_data(client, EXT_THERM_LIMIT_WR);
249         if (value < 0)
250                 goto error;
251         temp2 = value_to_temperature(pdata->ext_range, value);
252
253         return snprintf(buf, MAX_STR_PRINT, "%d %d\n", temp, temp2);
254 error:
255         dev_err(dev, "%s: failed to read temperature-overheat "
256                 "\n", __func__);
257         return snprintf(buf, MAX_STR_PRINT, " Rd overheat Error\n");
258 }
259
260 static ssize_t nct1008_set_temp_overheat(struct device *dev,
261                         struct device_attribute *attr,
262                         const char *buf, size_t count)
263 {
264         long int num;
265         int err;
266         u8 temp;
267         long currTemp;
268         struct i2c_client *client = to_i2c_client(dev);
269         struct nct1008_platform_data *pdata = client->dev.platform_data;
270         char bufTemp[MAX_STR_PRINT];
271         char bufOverheat[MAX_STR_PRINT];
272         unsigned int ret;
273
274         if (strict_strtol(buf, 0, &num)) {
275                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
276                         __LINE__, __func__);
277                 return -EINVAL;
278         }
279         if (((int)num < NCT1008_MIN_TEMP) || ((int)num >= NCT1008_MAX_TEMP)) {
280                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
281                         __LINE__, __func__);
282                 return -EINVAL;
283         }
284         /* check for system power down */
285         err = nct1008_get_temp(dev, &currTemp);
286         if (err)
287                 goto error;
288
289         currTemp = MILLICELSIUS_TO_CELSIUS(currTemp);
290
291         if (currTemp >= (int)num) {
292                 ret = nct1008_show_temp(dev, attr, bufTemp);
293                 ret = nct1008_show_temp_overheat(dev, attr, bufOverheat);
294                 dev_err(dev, "\nCurrent temp: %s ", bufTemp);
295                 dev_err(dev, "\nOld overheat limit: %s ", bufOverheat);
296                 dev_err(dev, "\nReset from overheat: curr temp=%ld, "
297                         "new overheat temp=%d\n\n", currTemp, (int)num);
298         }
299
300         /* External temperature h/w shutdown limit */
301         temp = temperature_to_value(pdata->ext_range, (s8)num);
302         err = i2c_smbus_write_byte_data(client, EXT_THERM_LIMIT_WR, temp);
303         if (err < 0)
304                 goto error;
305
306         /* Local temperature h/w shutdown limit */
307         temp = temperature_to_value(pdata->ext_range, (s8)num);
308         err = i2c_smbus_write_byte_data(client, LOCAL_THERM_LIMIT_WR, temp);
309         if (err < 0)
310                 goto error;
311         return count;
312 error:
313         dev_err(dev, " %s: failed to set temperature-overheat\n", __func__);
314         return err;
315 }
316
317 static ssize_t nct1008_show_temp_alert(struct device *dev,
318                                 struct device_attribute *attr,
319                                 char *buf)
320 {
321         struct i2c_client *client = to_i2c_client(dev);
322         struct nct1008_platform_data *pdata = client->dev.platform_data;
323         int value;
324         s8 temp, temp2;
325         /* External Temperature Throttling limit */
326         value = i2c_smbus_read_byte_data(client, EXT_TEMP_HI_LIMIT_HI_BYTE_RD);
327         if (value < 0)
328                 goto error;
329         temp2 = value_to_temperature(pdata->ext_range, value);
330
331         /* Local Temperature Throttling limit */
332         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_HI_LIMIT_RD);
333         if (value < 0)
334                 goto error;
335         temp = value_to_temperature(pdata->ext_range, value);
336
337         return snprintf(buf, MAX_STR_PRINT, "%d %d\n", temp, temp2);
338 error:
339         dev_err(dev, "%s: failed to read temperature-overheat "
340                 "\n", __func__);
341         return snprintf(buf, MAX_STR_PRINT, " Rd overheat Error\n");
342 }
343
344 static ssize_t nct1008_set_temp_alert(struct device *dev,
345                         struct device_attribute *attr,
346                         const char *buf, size_t count)
347 {
348         long int num;
349         int value;
350         int err;
351         struct i2c_client *client = to_i2c_client(dev);
352         struct nct1008_platform_data *pdata = client->dev.platform_data;
353
354         if (strict_strtol(buf, 0, &num)) {
355                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
356                         __LINE__, __func__);
357                 return -EINVAL;
358         }
359         if (((int)num < NCT1008_MIN_TEMP) || ((int)num >= NCT1008_MAX_TEMP)) {
360                 dev_err(dev, "\n file: %s, line=%d return %s() ", __FILE__,
361                         __LINE__, __func__);
362                 return -EINVAL;
363         }
364
365         /* External Temperature Throttling limit */
366         value = temperature_to_value(pdata->ext_range, (s8)num);
367         err = i2c_smbus_write_byte_data(client, EXT_TEMP_HI_LIMIT_HI_BYTE_WR,
368                 value);
369         if (err < 0)
370                 goto error;
371
372         /* Local Temperature Throttling limit */
373         err = i2c_smbus_write_byte_data(client, LOCAL_TEMP_HI_LIMIT_WR,
374                 value);
375         if (err < 0)
376                 goto error;
377
378         return count;
379 error:
380         dev_err(dev, "%s: failed to set temperature-alert "
381                 "\n", __func__);
382         return err;
383 }
384
385 static ssize_t nct1008_show_ext_temp(struct device *dev,
386         struct device_attribute *attr, char *buf)
387 {
388         struct i2c_client *client = to_i2c_client(dev);
389         struct nct1008_platform_data *pdata = client->dev.platform_data;
390         s8 temp_value;
391         int data = 0;
392         int data_lo;
393
394         if (!dev || !buf || !attr)
395                 return -EINVAL;
396
397         data = nct1008_wait_till_busy(client);
398         if (data < 0)
399                 goto error;
400
401         /* When reading the full external temperature value, read the
402          * LSB first. This causes the MSB to be locked (that is, the
403          * ADC does not write to it) until it is read */
404         data_lo = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LO);
405         if (data_lo < 0) {
406                 dev_err(&client->dev, "%s: failed to read "
407                         "ext_temperature, i2c error=%d\n", __func__, data_lo);
408                 goto error;
409         }
410
411         data = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
412         if (data < 0) {
413                 dev_err(&client->dev, "%s: failed to read "
414                         "ext_temperature, i2c error=%d\n", __func__, data);
415                 goto error;
416         }
417
418         temp_value = value_to_temperature(pdata->ext_range, data);
419
420         return snprintf(buf, MAX_STR_PRINT, "%d.%d\n", temp_value,
421                 (25 * (data_lo >> 6)));
422 error:
423         return snprintf(buf, MAX_STR_PRINT, "Error read ext temperature\n");
424 }
425
426 static DEVICE_ATTR(temperature, S_IRUGO, nct1008_show_temp, NULL);
427 static DEVICE_ATTR(temperature_overheat, (S_IRUGO | (S_IWUSR | S_IWGRP)),
428                 nct1008_show_temp_overheat, nct1008_set_temp_overheat);
429 static DEVICE_ATTR(temperature_alert, (S_IRUGO | (S_IWUSR | S_IWGRP)),
430                 nct1008_show_temp_alert, nct1008_set_temp_alert);
431 static DEVICE_ATTR(ext_temperature, S_IRUGO, nct1008_show_ext_temp, NULL);
432
433 static struct attribute *nct1008_attributes[] = {
434         &dev_attr_temperature.attr,
435         &dev_attr_temperature_overheat.attr,
436         &dev_attr_temperature_alert.attr,
437         &dev_attr_ext_temperature.attr,
438         NULL
439 };
440
441 static const struct attribute_group nct1008_attr_group = {
442         .attrs = nct1008_attributes,
443 };
444
445 #ifdef CONFIG_DEBUG_FS
446 #include <linux/debugfs.h>
447 #include <linux/seq_file.h>
448 static void print_reg(const char *reg_name, struct seq_file *s,
449                 int offset)
450 {
451         struct nct1008_data *nct_data = s->private;
452         int ret;
453
454         ret = i2c_smbus_read_byte_data(nct_data->client,
455                 offset);
456         if (ret >= 0)
457                 seq_printf(s, "Reg %s Addr = 0x%02x Reg 0x%02x "
458                 "Value 0x%02x\n", reg_name,
459                 nct_data->client->addr,
460                         offset, ret);
461         else
462                 seq_printf(s, "%s: line=%d, i2c read error=%d\n",
463                 __func__, __LINE__, ret);
464 }
465
466 static int dbg_nct1008_show(struct seq_file *s, void *unused)
467 {
468         seq_printf(s, "nct1008 Registers\n");
469         seq_printf(s, "------------------\n");
470         print_reg("Local Temp Value    ",     s, 0x00);
471         print_reg("Ext Temp Value Hi   ",     s, 0x01);
472         print_reg("Status              ",     s, 0x02);
473         print_reg("Configuration       ",     s, 0x03);
474         print_reg("Conversion Rate     ",     s, 0x04);
475         print_reg("Local Temp Hi Limit ",     s, 0x05);
476         print_reg("Local Temp Lo Limit ",     s, 0x06);
477         print_reg("Ext Temp Hi Limit Hi",     s, 0x07);
478         print_reg("Ext Temp Hi Limit Lo",     s, 0x13);
479         print_reg("Ext Temp Lo Limit Hi",     s, 0x08);
480         print_reg("Ext Temp Lo Limit Lo",     s, 0x14);
481         print_reg("Ext Temp Value Lo   ",     s, 0x10);
482         print_reg("Ext Temp Offset Hi  ",     s, 0x11);
483         print_reg("Ext Temp Offset Lo  ",     s, 0x12);
484         print_reg("Ext THERM Limit     ",     s, 0x19);
485         print_reg("Local THERM Limit   ",     s, 0x20);
486         print_reg("THERM Hysteresis    ",     s, 0x21);
487         print_reg("Consecutive ALERT   ",     s, 0x22);
488         return 0;
489 }
490
491 static int dbg_nct1008_open(struct inode *inode, struct file *file)
492 {
493         return single_open(file, dbg_nct1008_show, inode->i_private);
494 }
495
496 static const struct file_operations debug_fops = {
497         .open           = dbg_nct1008_open,
498         .read           = seq_read,
499         .llseek         = seq_lseek,
500         .release        = single_release,
501 };
502
503 static int __init nct1008_debuginit(struct nct1008_data *nct)
504 {
505         int err = 0;
506         struct dentry *d;
507         d = debugfs_create_file("nct1008", S_IRUGO, NULL,
508                         (void *)nct, &debug_fops);
509         if ((!d) || IS_ERR(d)) {
510                 dev_err(&nct->client->dev, "Error: %s debugfs_create_file"
511                         " returned an error\n", __func__);
512                 err = -ENOENT;
513                 goto end;
514         }
515         if (d == ERR_PTR(-ENODEV)) {
516                 dev_err(&nct->client->dev, "Error: %s debugfs not supported "
517                         "error=-ENODEV\n", __func__);
518                 err = -ENODEV;
519         } else {
520                 nct->dent = d;
521         }
522 end:
523         return err;
524 }
525 #else
526 static int __init nct1008_debuginit(struct nct1008_data *nct)
527 {
528         return 0;
529 }
530 #endif
531
532 static int nct1008_enable(struct i2c_client *client)
533 {
534         struct nct1008_data *data = i2c_get_clientdata(client);
535         int err;
536
537         err = i2c_smbus_write_byte_data(client, CONFIG_WR,
538                                   data->config & ~STANDBY_BIT);
539         if (err < 0)
540                 dev_err(&client->dev, "%s, line=%d, i2c write error=%d\n",
541                 __func__, __LINE__, err);
542         return err;
543 }
544
545 static int nct1008_disable(struct i2c_client *client)
546 {
547         struct nct1008_data *data = i2c_get_clientdata(client);
548         int err;
549
550         err = i2c_smbus_write_byte_data(client, CONFIG_WR,
551                                   data->config | STANDBY_BIT);
552         if (err < 0)
553                 dev_err(&client->dev, "%s, line=%d, i2c write error=%d\n",
554                 __func__, __LINE__, err);
555         return err;
556 }
557
558 static int nct1008_disable_alert(struct nct1008_data *data)
559 {
560         struct i2c_client *client = data->client;
561         int ret = 0;
562         int val;
563
564         /*
565          * Disable ALERT# output, because these chips don't implement
566          * SMBus alert correctly; they should only hold the alert line
567          * low briefly.
568          */
569         val = i2c_smbus_read_byte_data(data->client, CONFIG_RD);
570         if (val < 0) {
571                 dev_err(&client->dev, "%s, line=%d, disable alert failed ... "
572                         "i2c read error=%d\n", __func__, __LINE__, val);
573                 return val;
574         }
575         data->config = val | ALERT_BIT;
576         ret = i2c_smbus_write_byte_data(client, CONFIG_WR, val | ALERT_BIT);
577         if (ret)
578                 dev_err(&client->dev, "%s: fail to disable alert, i2c "
579                         "write error=%d#\n", __func__, ret);
580
581         return ret;
582 }
583
584 static int nct1008_enable_alert(struct nct1008_data *data)
585 {
586         int val;
587         int ret;
588
589         val = i2c_smbus_read_byte_data(data->client, CONFIG_RD);
590         if (val < 0) {
591                 dev_err(&data->client->dev, "%s, line=%d, enable alert "
592                         "failed ... i2c read error=%d\n", __func__,
593                         __LINE__, val);
594                 return val;
595         }
596         val &= ~(ALERT_BIT | THERM2_BIT);
597         ret = i2c_smbus_write_byte_data(data->client, CONFIG_WR, val);
598         if (ret) {
599                 dev_err(&data->client->dev, "%s: fail to enable alert, i2c "
600                         "write error=%d\n", __func__, ret);
601                 return ret;
602         }
603
604         return ret;
605 }
606
607 static bool throttle_enb;
608 static void therm_throttle(struct nct1008_data *data, bool enable)
609 {
610         if (!data->alarm_fn) {
611                 dev_err(&data->client->dev, "system too hot. no way to "
612                         "cool down!\n");
613                 return;
614         }
615
616         if (throttle_enb != enable) {
617                 mutex_lock(&data->mutex);
618                 data->alarm_fn(enable);
619                 throttle_enb = enable;
620                 mutex_unlock(&data->mutex);
621         }
622 }
623
624 #define ALERT_HYSTERESIS_THROTTLE       1
625 #define ALERT_HYSTERESIS_EDP    3
626 static int edp_thermal_zone_val = -1;
627 static int current_hi_limit = -1;
628 static int current_lo_limit = -1;
629
630 static void nct1008_work_func(struct work_struct *work)
631 {
632         struct nct1008_data *data = container_of(work, struct nct1008_data,
633                                                 work);
634         bool extended_range = data->plat_data.ext_range;
635         long temp_milli;
636         u8 value;
637         int err = 0, i;
638         int hysteresis;
639         int nentries = data->limits_sz;
640         int lo_limit = 0, hi_limit = 0;
641         long throttling_ext_limit_milli;
642         int intr_status = i2c_smbus_read_byte_data(data->client, STATUS_RD);
643
644         if (intr_status < 0) {
645                 dev_err(&data->client->dev, "%s, line=%d, i2c read error=%d\n",
646                         __func__, __LINE__, intr_status);
647                 return;
648         }
649
650         intr_status &= (BIT(3) | BIT(4));
651         if (!intr_status)
652                 return;
653
654         err = nct1008_get_temp(&data->client->dev, &temp_milli);
655         if (err) {
656                 dev_err(&data->client->dev, "%s: get temp fail(%d)", __func__,
657                         err);
658                 return;
659         }
660
661         err = nct1008_disable_alert(data);
662         if (err) {
663                 dev_err(&data->client->dev, "%s: disable alert fail(error=%d)\n"
664                         , __func__, err);
665                 return;
666         }
667
668         hysteresis = ALERT_HYSTERESIS_EDP;
669         throttling_ext_limit_milli =
670                 CELSIUS_TO_MILLICELSIUS(data->plat_data.throttling_ext_limit);
671
672         if (temp_milli >= throttling_ext_limit_milli) {
673                 /* start throttling */
674                 therm_throttle(data, true);
675                 hysteresis = ALERT_HYSTERESIS_THROTTLE;
676         } else if (temp_milli <=
677                         (throttling_ext_limit_milli -
678                         ALERT_HYSTERESIS_THROTTLE)) {
679                 /* switch off throttling */
680                 therm_throttle(data, false);
681         }
682
683         if (temp_milli < CELSIUS_TO_MILLICELSIUS(data->limits[0])) {
684                 lo_limit = 0;
685                 hi_limit = data->limits[0];
686         } else if (temp_milli >= CELSIUS_TO_MILLICELSIUS(data->limits[nentries-1])) {
687                 lo_limit = data->limits[nentries-1] - hysteresis;
688                 hi_limit = data->plat_data.shutdown_ext_limit;
689         } else {
690                 for (i = 0; (i + 1) < nentries; i++) {
691                         if (temp_milli >=
692                                 CELSIUS_TO_MILLICELSIUS(data->limits[i]) &&
693                             temp_milli <
694                                 CELSIUS_TO_MILLICELSIUS(data->limits[i + 1])) {
695                                 lo_limit = data->limits[i] - hysteresis;
696                                 hi_limit = data->limits[i + 1];
697                                 break;
698                         }
699                 }
700         }
701
702         if (lo_limit == hi_limit) {
703                 err = -ENODATA;
704                 goto out;
705         }
706
707         if (current_lo_limit == lo_limit && current_hi_limit == hi_limit)
708                 goto out;
709
710         if (current_lo_limit != lo_limit) {
711                 value = temperature_to_value(extended_range, lo_limit);
712                 pr_debug("%s: %d\n", __func__, value);
713                 err = i2c_smbus_write_byte_data(data->client,
714                         EXT_TEMP_LO_LIMIT_HI_BYTE_WR, value);
715                 if (err)
716                         goto out;
717
718                 current_lo_limit = lo_limit;
719         }
720
721         if (current_hi_limit != hi_limit) {
722                 value = temperature_to_value(extended_range, hi_limit);
723                 pr_debug("%s: %d\n", __func__, value);
724                 err = i2c_smbus_write_byte_data(data->client,
725                         EXT_TEMP_HI_LIMIT_HI_BYTE_WR, value);
726                 if (err)
727                         goto out;
728
729                 current_hi_limit = hi_limit;
730         }
731
732         /* inform edp governor */
733         if (edp_thermal_zone_val != temp_milli)
734                 /*
735                  * FIXME: Move this direct tegra_ function call to be called
736                  * via a pointer in 'struct nct1008_data' (like 'alarm_fn')
737                  */
738                 tegra_edp_update_thermal_zone(
739                         MILLICELSIUS_TO_CELSIUS(temp_milli));
740
741         edp_thermal_zone_val = temp_milli;
742
743 out:
744         nct1008_enable_alert(data);
745
746         if (err)
747                 dev_err(&data->client->dev, "%s: fail(error=%d)\n", __func__,
748                         err);
749         else
750                 pr_debug("%s: done\n", __func__);
751 }
752
753 static irqreturn_t nct1008_irq(int irq, void *dev_id)
754 {
755         struct nct1008_data *data = dev_id;
756
757         schedule_work(&data->work);
758         return IRQ_HANDLED;
759 }
760
761 static void nct1008_power_control(struct nct1008_data *data, bool is_enable)
762 {
763         int ret;
764         if (!data->nct_reg) {
765                 data->nct_reg = regulator_get(&data->client->dev, "vdd");
766                 if (IS_ERR_OR_NULL(data->nct_reg)) {
767                         dev_warn(&data->client->dev, "Error [%d] in"
768                                 "getting the regulator handle for vdd "
769                                 "of %s\n", (int)data->nct_reg,
770                                 dev_name(&data->client->dev));
771                         data->nct_reg = NULL;
772                         return;
773                 }
774         }
775         if (is_enable)
776                 ret = regulator_enable(data->nct_reg);
777         else
778                 ret = regulator_disable(data->nct_reg);
779
780         if (ret < 0)
781                 dev_err(&data->client->dev, "Error in %s rail vdd_nct1008, "
782                         "error %d\n", (is_enable) ? "enabling" : "disabling",
783                         ret);
784         else
785                 dev_info(&data->client->dev, "success in %s rail vdd_nct1008\n",
786                         (is_enable) ? "enabling" : "disabling");
787 }
788
789 static int __devinit nct1008_configure_sensor(struct nct1008_data* data)
790 {
791         struct i2c_client *client = data->client;
792         struct nct1008_platform_data *pdata = client->dev.platform_data;
793         u8 value;
794         s8 temp;
795         u8 temp2;
796         int err;
797         int hi_limit;
798
799         if (!pdata || !pdata->supported_hwrev)
800                 return -ENODEV;
801
802         /* Place in Standby */
803         data->config = STANDBY_BIT;
804         err = i2c_smbus_write_byte_data(client, CONFIG_WR, data->config);
805         if (err)
806                 goto error;
807
808         /* External temperature h/w shutdown limit */
809         value = temperature_to_value(pdata->ext_range,
810                         pdata->shutdown_ext_limit);
811         err = i2c_smbus_write_byte_data(client, EXT_THERM_LIMIT_WR, value);
812         if (err)
813                 goto error;
814
815         /* Local temperature h/w shutdown limit */
816         value = temperature_to_value(pdata->ext_range,
817                         pdata->shutdown_local_limit);
818         err = i2c_smbus_write_byte_data(client, LOCAL_THERM_LIMIT_WR, value);
819         if (err)
820                 goto error;
821
822         /* set extended range mode if needed */
823         if (pdata->ext_range)
824                 data->config |= EXTENDED_RANGE_BIT;
825         if (pdata->thermal_zones_sz)
826                 data->config &= ~(THERM2_BIT | ALERT_BIT);
827         else
828                 data->config |= (ALERT_BIT | THERM2_BIT);
829
830         err = i2c_smbus_write_byte_data(client, CONFIG_WR, data->config);
831         if (err)
832                 goto error;
833
834         /* Temperature conversion rate */
835         err = i2c_smbus_write_byte_data(client, CONV_RATE_WR, pdata->conv_rate);
836         if (err)
837                 goto error;
838
839         if (pdata->thermal_zones_sz) {
840                 data->limits = pdata->thermal_zones;
841                 data->limits_sz = pdata->thermal_zones_sz;
842
843                 /* setup alarm */
844                 hi_limit = pdata->thermal_zones[0];
845
846                 err = i2c_smbus_write_byte_data(client,
847                         EXT_TEMP_LO_LIMIT_HI_BYTE_WR, 0);
848                 if (err)
849                         goto error;
850
851                 err = i2c_smbus_write_byte_data(client,
852                         LOCAL_TEMP_HI_LIMIT_WR, NCT1008_MAX_TEMP);
853                 if (err)
854                         goto error;
855
856                 err = i2c_smbus_write_byte_data(client,
857                         LOCAL_TEMP_LO_LIMIT_WR, 0);
858                 if (err)
859                         goto error;
860         } else {
861                 /*
862                  * External Temperature Throttling limit:
863                  *   Applies when 'Thermal Zones' are not specified.
864                  */
865                 hi_limit = pdata->throttling_ext_limit;
866         }
867
868         value = temperature_to_value(pdata->ext_range, hi_limit);
869         err = i2c_smbus_write_byte_data(client, EXT_TEMP_HI_LIMIT_HI_BYTE_WR,
870                         value);
871         if (err)
872                 goto error;
873
874         /* read initial temperature */
875         value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD);
876         if (value < 0) {
877                 err = value;
878                 goto error;
879         }
880         temp = value_to_temperature(pdata->ext_range, value);
881         dev_dbg(&client->dev, "\n initial local temp = %d ", temp);
882
883         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LO);
884         if (value < 0) {
885                 err = value;
886                 goto error;
887         }
888         temp2 = (value >> 6);
889         value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
890         if (value < 0) {
891                 err = value;
892                 goto error;
893         }
894         temp = value_to_temperature(pdata->ext_range, value);
895
896         if (temp2 > 0)
897                 dev_dbg(&client->dev, "\n initial ext temp = %d.%d deg",
898                                 temp, temp2 * 25);
899         else
900                 dev_dbg(&client->dev, "\n initial ext temp = %d.0 deg", temp);
901
902         /* Remote channel offset */
903         err = i2c_smbus_write_byte_data(client, OFFSET_WR, pdata->offset / 4);
904         if (err < 0)
905                 goto error;
906
907         /* Remote channel offset fraction (quarters) */
908         err = i2c_smbus_write_byte_data(client, OFFSET_QUARTER_WR,
909                                         (pdata->offset % 4) << 6);
910         if (err < 0)
911                 goto error;
912
913         /* THERM hysteresis */
914         err = i2c_smbus_write_byte_data(client, THERM_HYSTERESIS_WR,
915                         pdata->hysteresis);
916         if (err < 0)
917                 goto error;
918
919         /* register sysfs hooks */
920         err = sysfs_create_group(&client->dev.kobj, &nct1008_attr_group);
921         if (err < 0) {
922                 dev_err(&client->dev, "\n sysfs create err=%d ", err);
923                 goto error;
924         }
925
926         data->alarm_fn = pdata->alarm_fn;
927         return 0;
928 error:
929         dev_err(&client->dev, "\n exit %s, err=%d ", __func__, err);
930         return err;
931 }
932
933 static int __devinit nct1008_configure_irq(struct nct1008_data *data)
934 {
935         INIT_WORK(&data->work, nct1008_work_func);
936
937         if (data->client->irq < 0)
938                 return 0;
939         else
940                 return request_irq(data->client->irq, nct1008_irq,
941                         IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
942                         DRIVER_NAME, data);
943 }
944
945 static unsigned int get_ext_mode_delay_ms(unsigned int conv_rate)
946 {
947         switch (conv_rate) {
948         case 0:
949                 return 16000;
950         case 1:
951                 return 8000;
952         case 2:
953                 return 4000;
954         case 3:
955                 return 2000;
956         case 4:
957                 return 1000;
958         case 5:
959                 return 500;
960         case 6:
961                 return 250;
962         case 7:
963                 return 125;
964         case 9:
965                 return 32;
966         case 10:
967                 return 16;
968         case 8:
969         default:
970                 return 63;
971         }
972 }
973
974 /*
975  * Manufacturer(OnSemi) recommended sequence for
976  * Extended Range mode is as follows
977  * 1. Place in Standby
978  * 2. Scale the THERM and ALERT limits
979  *      appropriately(for Extended Range mode).
980  * 3. Enable Extended Range mode.
981  *      ALERT mask/THERM2 mode may be done here
982  *      as these are not critical
983  * 4. Set Conversion Rate as required
984  * 5. Take device out of Standby
985  */
986
987 /*
988  * function nct1008_probe takes care of initial configuration
989  */
990 static int __devinit nct1008_probe(struct i2c_client *client,
991                                 const struct i2c_device_id *id)
992 {
993         struct nct1008_data *data;
994         int err;
995         long temp_milli;
996         unsigned int delay;
997
998         data = kzalloc(sizeof(struct nct1008_data), GFP_KERNEL);
999
1000         if (!data)
1001                 return -ENOMEM;
1002
1003         data->client = client;
1004         memcpy(&data->plat_data, client->dev.platform_data,
1005                 sizeof(struct nct1008_platform_data));
1006         i2c_set_clientdata(client, data);
1007         mutex_init(&data->mutex);
1008
1009         nct1008_power_control(data, true);
1010         /* extended range recommended steps 1 through 4 taken care
1011          * in nct1008_configure_sensor function */
1012         err = nct1008_configure_sensor(data);   /* sensor is in standby */
1013         if (err < 0) {
1014                 dev_err(&client->dev, "\n error file: %s : %s(), line=%d ",
1015                         __FILE__, __func__, __LINE__);
1016                 goto error;
1017         }
1018
1019         err = nct1008_configure_irq(data);
1020         if (err < 0) {
1021                 dev_err(&client->dev, "\n error file: %s : %s(), line=%d ",
1022                         __FILE__, __func__, __LINE__);
1023                 goto error;
1024         }
1025         dev_info(&client->dev, "%s: initialized\n", __func__);
1026
1027         /* extended range recommended step 5 is in nct1008_enable function */
1028         err = nct1008_enable(client);           /* sensor is running */
1029         if (err < 0) {
1030                 dev_err(&client->dev, "Error: %s, line=%d, error=%d\n",
1031                         __func__, __LINE__, err);
1032                 goto error;
1033         }
1034
1035         err = nct1008_debuginit(data);
1036         if (err < 0)
1037                 err = 0; /* without debugfs we may continue */
1038
1039         /* switch to extended mode reports correct temperature
1040          * from next measurement cycle */
1041         if (data->plat_data.ext_range) {
1042                 delay = get_ext_mode_delay_ms(
1043                         data->plat_data.conv_rate);
1044                 msleep(delay); /* 63msec for default conv rate 0x8 */
1045         }
1046         err = nct1008_get_temp(&data->client->dev, &temp_milli);
1047         if (err) {
1048                 dev_err(&data->client->dev, "%s: get temp fail(%d)",
1049                         __func__, err);
1050                 return 0;       /*do not fail init on the 1st read */
1051         }
1052
1053         tegra_edp_update_thermal_zone(MILLICELSIUS_TO_CELSIUS(temp_milli));
1054         return 0;
1055
1056 error:
1057         dev_err(&client->dev, "\n exit %s, err=%d ", __func__, err);
1058         nct1008_power_control(data, false);
1059         if (data->nct_reg)
1060                 regulator_put(data->nct_reg);
1061         kfree(data);
1062         return err;
1063 }
1064
1065 static int __devexit nct1008_remove(struct i2c_client *client)
1066 {
1067         struct nct1008_data *data = i2c_get_clientdata(client);
1068
1069         if (data->dent)
1070                 debugfs_remove(data->dent);
1071         free_irq(data->client->irq, data);
1072         cancel_work_sync(&data->work);
1073         sysfs_remove_group(&client->dev.kobj, &nct1008_attr_group);
1074         nct1008_power_control(data, false);
1075         if (data->nct_reg)
1076                 regulator_put(data->nct_reg);
1077         kfree(data);
1078
1079         return 0;
1080 }
1081
1082 #ifdef CONFIG_PM
1083 static int nct1008_suspend(struct i2c_client *client, pm_message_t state)
1084 {
1085         int err;
1086
1087         disable_irq(client->irq);
1088         err = nct1008_disable(client);
1089         return err;
1090 }
1091
1092 static int nct1008_resume(struct i2c_client *client)
1093 {
1094         struct nct1008_data *data = i2c_get_clientdata(client);
1095         int err;
1096
1097         err = nct1008_enable(client);
1098         if (err < 0) {
1099                 dev_err(&client->dev, "Error: %s, error=%d\n",
1100                         __func__, err);
1101                 return err;
1102         }
1103         enable_irq(client->irq);
1104         schedule_work(&data->work);
1105
1106         return 0;
1107 }
1108 #endif
1109
1110 static const struct i2c_device_id nct1008_id[] = {
1111         { DRIVER_NAME, 0 },
1112         { }
1113 };
1114 MODULE_DEVICE_TABLE(i2c, nct1008_id);
1115
1116 static struct i2c_driver nct1008_driver = {
1117         .driver = {
1118                 .name   = DRIVER_NAME,
1119         },
1120         .probe          = nct1008_probe,
1121         .remove         = __devexit_p(nct1008_remove),
1122         .id_table       = nct1008_id,
1123 #ifdef CONFIG_PM
1124         .suspend        = nct1008_suspend,
1125         .resume         = nct1008_resume,
1126 #endif
1127 };
1128
1129 static int __init nct1008_init(void)
1130 {
1131         return i2c_add_driver(&nct1008_driver);
1132 }
1133
1134 static void __exit nct1008_exit(void)
1135 {
1136         i2c_del_driver(&nct1008_driver);
1137 }
1138
1139 MODULE_DESCRIPTION("Temperature sensor driver for OnSemi NCT1008");
1140 MODULE_LICENSE("GPL");
1141
1142 module_init(nct1008_init);
1143 module_exit(nct1008_exit);