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