Merge branch 'parisc-4.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller...
[cascardo/linux.git] / drivers / hwmon / ntc_thermistor.c
1 /*
2  * ntc_thermistor.c - NTC Thermistors
3  *
4  *  Copyright (C) 2010 Samsung Electronics
5  *  MyungJoo Ham <myungjoo.ham@samsung.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include <linux/slab.h>
24 #include <linux/module.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/math64.h>
27 #include <linux/platform_device.h>
28 #include <linux/err.h>
29 #include <linux/of.h>
30 #include <linux/of_device.h>
31
32 #include <linux/platform_data/ntc_thermistor.h>
33
34 #include <linux/iio/iio.h>
35 #include <linux/iio/machine.h>
36 #include <linux/iio/driver.h>
37 #include <linux/iio/consumer.h>
38
39 #include <linux/hwmon.h>
40 #include <linux/hwmon-sysfs.h>
41 #include <linux/thermal.h>
42
43 struct ntc_compensation {
44         int             temp_c;
45         unsigned int    ohm;
46 };
47
48 /* Order matters, ntc_match references the entries by index */
49 static const struct platform_device_id ntc_thermistor_id[] = {
50         { "ncp15wb473", TYPE_NCPXXWB473 },
51         { "ncp18wb473", TYPE_NCPXXWB473 },
52         { "ncp21wb473", TYPE_NCPXXWB473 },
53         { "ncp03wb473", TYPE_NCPXXWB473 },
54         { "ncp15wl333", TYPE_NCPXXWL333 },
55         { "b57330v2103", TYPE_B57330V2103},
56         { "ncp03wf104", TYPE_NCPXXWF104 },
57         { "ncp15xh103", TYPE_NCPXXXH103 },
58         { },
59 };
60
61 /*
62  * A compensation table should be sorted by the values of .ohm
63  * in descending order.
64  * The following compensation tables are from the specification of Murata NTC
65  * Thermistors Datasheet
66  */
67 static const struct ntc_compensation ncpXXwb473[] = {
68         { .temp_c       = -40, .ohm     = 1747920 },
69         { .temp_c       = -35, .ohm     = 1245428 },
70         { .temp_c       = -30, .ohm     = 898485 },
71         { .temp_c       = -25, .ohm     = 655802 },
72         { .temp_c       = -20, .ohm     = 483954 },
73         { .temp_c       = -15, .ohm     = 360850 },
74         { .temp_c       = -10, .ohm     = 271697 },
75         { .temp_c       = -5, .ohm      = 206463 },
76         { .temp_c       = 0, .ohm       = 158214 },
77         { .temp_c       = 5, .ohm       = 122259 },
78         { .temp_c       = 10, .ohm      = 95227 },
79         { .temp_c       = 15, .ohm      = 74730 },
80         { .temp_c       = 20, .ohm      = 59065 },
81         { .temp_c       = 25, .ohm      = 47000 },
82         { .temp_c       = 30, .ohm      = 37643 },
83         { .temp_c       = 35, .ohm      = 30334 },
84         { .temp_c       = 40, .ohm      = 24591 },
85         { .temp_c       = 45, .ohm      = 20048 },
86         { .temp_c       = 50, .ohm      = 16433 },
87         { .temp_c       = 55, .ohm      = 13539 },
88         { .temp_c       = 60, .ohm      = 11209 },
89         { .temp_c       = 65, .ohm      = 9328 },
90         { .temp_c       = 70, .ohm      = 7798 },
91         { .temp_c       = 75, .ohm      = 6544 },
92         { .temp_c       = 80, .ohm      = 5518 },
93         { .temp_c       = 85, .ohm      = 4674 },
94         { .temp_c       = 90, .ohm      = 3972 },
95         { .temp_c       = 95, .ohm      = 3388 },
96         { .temp_c       = 100, .ohm     = 2902 },
97         { .temp_c       = 105, .ohm     = 2494 },
98         { .temp_c       = 110, .ohm     = 2150 },
99         { .temp_c       = 115, .ohm     = 1860 },
100         { .temp_c       = 120, .ohm     = 1615 },
101         { .temp_c       = 125, .ohm     = 1406 },
102 };
103 static const struct ntc_compensation ncpXXwl333[] = {
104         { .temp_c       = -40, .ohm     = 1610154 },
105         { .temp_c       = -35, .ohm     = 1130850 },
106         { .temp_c       = -30, .ohm     = 802609 },
107         { .temp_c       = -25, .ohm     = 575385 },
108         { .temp_c       = -20, .ohm     = 416464 },
109         { .temp_c       = -15, .ohm     = 304219 },
110         { .temp_c       = -10, .ohm     = 224193 },
111         { .temp_c       = -5, .ohm      = 166623 },
112         { .temp_c       = 0, .ohm       = 124850 },
113         { .temp_c       = 5, .ohm       = 94287 },
114         { .temp_c       = 10, .ohm      = 71747 },
115         { .temp_c       = 15, .ohm      = 54996 },
116         { .temp_c       = 20, .ohm      = 42455 },
117         { .temp_c       = 25, .ohm      = 33000 },
118         { .temp_c       = 30, .ohm      = 25822 },
119         { .temp_c       = 35, .ohm      = 20335 },
120         { .temp_c       = 40, .ohm      = 16115 },
121         { .temp_c       = 45, .ohm      = 12849 },
122         { .temp_c       = 50, .ohm      = 10306 },
123         { .temp_c       = 55, .ohm      = 8314 },
124         { .temp_c       = 60, .ohm      = 6746 },
125         { .temp_c       = 65, .ohm      = 5503 },
126         { .temp_c       = 70, .ohm      = 4513 },
127         { .temp_c       = 75, .ohm      = 3721 },
128         { .temp_c       = 80, .ohm      = 3084 },
129         { .temp_c       = 85, .ohm      = 2569 },
130         { .temp_c       = 90, .ohm      = 2151 },
131         { .temp_c       = 95, .ohm      = 1809 },
132         { .temp_c       = 100, .ohm     = 1529 },
133         { .temp_c       = 105, .ohm     = 1299 },
134         { .temp_c       = 110, .ohm     = 1108 },
135         { .temp_c       = 115, .ohm     = 949 },
136         { .temp_c       = 120, .ohm     = 817 },
137         { .temp_c       = 125, .ohm     = 707 },
138 };
139
140 static const struct ntc_compensation ncpXXwf104[] = {
141         { .temp_c       = -40, .ohm     = 4397119 },
142         { .temp_c       = -35, .ohm     = 3088599 },
143         { .temp_c       = -30, .ohm     = 2197225 },
144         { .temp_c       = -25, .ohm     = 1581881 },
145         { .temp_c       = -20, .ohm     = 1151037 },
146         { .temp_c       = -15, .ohm     = 846579 },
147         { .temp_c       = -10, .ohm     = 628988 },
148         { .temp_c       = -5, .ohm      = 471632 },
149         { .temp_c       = 0, .ohm       = 357012 },
150         { .temp_c       = 5, .ohm       = 272500 },
151         { .temp_c       = 10, .ohm      = 209710 },
152         { .temp_c       = 15, .ohm      = 162651 },
153         { .temp_c       = 20, .ohm      = 127080 },
154         { .temp_c       = 25, .ohm      = 100000 },
155         { .temp_c       = 30, .ohm      = 79222 },
156         { .temp_c       = 35, .ohm      = 63167 },
157         { .temp_c       = 40, .ohm      = 50677 },
158         { .temp_c       = 45, .ohm      = 40904 },
159         { .temp_c       = 50, .ohm      = 33195 },
160         { .temp_c       = 55, .ohm      = 27091 },
161         { .temp_c       = 60, .ohm      = 22224 },
162         { .temp_c       = 65, .ohm      = 18323 },
163         { .temp_c       = 70, .ohm      = 15184 },
164         { .temp_c       = 75, .ohm      = 12635 },
165         { .temp_c       = 80, .ohm      = 10566 },
166         { .temp_c       = 85, .ohm      = 8873 },
167         { .temp_c       = 90, .ohm      = 7481 },
168         { .temp_c       = 95, .ohm      = 6337 },
169         { .temp_c       = 100, .ohm     = 5384 },
170         { .temp_c       = 105, .ohm     = 4594 },
171         { .temp_c       = 110, .ohm     = 3934 },
172         { .temp_c       = 115, .ohm     = 3380 },
173         { .temp_c       = 120, .ohm     = 2916 },
174         { .temp_c       = 125, .ohm     = 2522 },
175 };
176
177 static const struct ntc_compensation ncpXXxh103[] = {
178         { .temp_c       = -40, .ohm     = 247565 },
179         { .temp_c       = -35, .ohm     = 181742 },
180         { .temp_c       = -30, .ohm     = 135128 },
181         { .temp_c       = -25, .ohm     = 101678 },
182         { .temp_c       = -20, .ohm     = 77373 },
183         { .temp_c       = -15, .ohm     = 59504 },
184         { .temp_c       = -10, .ohm     = 46222 },
185         { .temp_c       = -5, .ohm      = 36244 },
186         { .temp_c       = 0, .ohm       = 28674 },
187         { .temp_c       = 5, .ohm       = 22878 },
188         { .temp_c       = 10, .ohm      = 18399 },
189         { .temp_c       = 15, .ohm      = 14910 },
190         { .temp_c       = 20, .ohm      = 12169 },
191         { .temp_c       = 25, .ohm      = 10000 },
192         { .temp_c       = 30, .ohm      = 8271 },
193         { .temp_c       = 35, .ohm      = 6883 },
194         { .temp_c       = 40, .ohm      = 5762 },
195         { .temp_c       = 45, .ohm      = 4851 },
196         { .temp_c       = 50, .ohm      = 4105 },
197         { .temp_c       = 55, .ohm      = 3492 },
198         { .temp_c       = 60, .ohm      = 2985 },
199         { .temp_c       = 65, .ohm      = 2563 },
200         { .temp_c       = 70, .ohm      = 2211 },
201         { .temp_c       = 75, .ohm      = 1915 },
202         { .temp_c       = 80, .ohm      = 1666 },
203         { .temp_c       = 85, .ohm      = 1454 },
204         { .temp_c       = 90, .ohm      = 1275 },
205         { .temp_c       = 95, .ohm      = 1121 },
206         { .temp_c       = 100, .ohm     = 990 },
207         { .temp_c       = 105, .ohm     = 876 },
208         { .temp_c       = 110, .ohm     = 779 },
209         { .temp_c       = 115, .ohm     = 694 },
210         { .temp_c       = 120, .ohm     = 620 },
211         { .temp_c       = 125, .ohm     = 556 },
212 };
213
214 /*
215  * The following compensation table is from the specification of EPCOS NTC
216  * Thermistors Datasheet
217  */
218 static const struct ntc_compensation b57330v2103[] = {
219         { .temp_c       = -40, .ohm     = 190030 },
220         { .temp_c       = -35, .ohm     = 145360 },
221         { .temp_c       = -30, .ohm     = 112060 },
222         { .temp_c       = -25, .ohm     = 87041 },
223         { .temp_c       = -20, .ohm     = 68104 },
224         { .temp_c       = -15, .ohm     = 53665 },
225         { .temp_c       = -10, .ohm     = 42576 },
226         { .temp_c       = -5, .ohm      = 34001 },
227         { .temp_c       = 0, .ohm       = 27326 },
228         { .temp_c       = 5, .ohm       = 22096 },
229         { .temp_c       = 10, .ohm      = 17973 },
230         { .temp_c       = 15, .ohm      = 14703 },
231         { .temp_c       = 20, .ohm      = 12090 },
232         { .temp_c       = 25, .ohm      = 10000 },
233         { .temp_c       = 30, .ohm      = 8311 },
234         { .temp_c       = 35, .ohm      = 6941 },
235         { .temp_c       = 40, .ohm      = 5825 },
236         { .temp_c       = 45, .ohm      = 4911 },
237         { .temp_c       = 50, .ohm      = 4158 },
238         { .temp_c       = 55, .ohm      = 3536 },
239         { .temp_c       = 60, .ohm      = 3019 },
240         { .temp_c       = 65, .ohm      = 2588 },
241         { .temp_c       = 70, .ohm      = 2227 },
242         { .temp_c       = 75, .ohm      = 1924 },
243         { .temp_c       = 80, .ohm      = 1668 },
244         { .temp_c       = 85, .ohm      = 1451 },
245         { .temp_c       = 90, .ohm      = 1266 },
246         { .temp_c       = 95, .ohm      = 1108 },
247         { .temp_c       = 100, .ohm     = 973 },
248         { .temp_c       = 105, .ohm     = 857 },
249         { .temp_c       = 110, .ohm     = 757 },
250         { .temp_c       = 115, .ohm     = 671 },
251         { .temp_c       = 120, .ohm     = 596 },
252         { .temp_c       = 125, .ohm     = 531 },
253 };
254
255 struct ntc_data {
256         struct ntc_thermistor_platform_data *pdata;
257         const struct ntc_compensation *comp;
258         int n_comp;
259 };
260
261 #if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO)
262 static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
263 {
264         struct iio_channel *channel = pdata->chan;
265         int raw, uv, ret;
266
267         ret = iio_read_channel_raw(channel, &raw);
268         if (ret < 0) {
269                 pr_err("read channel() error: %d\n", ret);
270                 return ret;
271         }
272
273         ret = iio_convert_raw_to_processed(channel, raw, &uv, 1000);
274         if (ret < 0) {
275                 /* Assume 12 bit ADC with vref at pullup_uv */
276                 uv = (pdata->pullup_uv * (s64)raw) >> 12;
277         }
278
279         return uv;
280 }
281
282 static const struct of_device_id ntc_match[] = {
283         { .compatible = "murata,ncp15wb473",
284                 .data = &ntc_thermistor_id[0] },
285         { .compatible = "murata,ncp18wb473",
286                 .data = &ntc_thermistor_id[1] },
287         { .compatible = "murata,ncp21wb473",
288                 .data = &ntc_thermistor_id[2] },
289         { .compatible = "murata,ncp03wb473",
290                 .data = &ntc_thermistor_id[3] },
291         { .compatible = "murata,ncp15wl333",
292                 .data = &ntc_thermistor_id[4] },
293         { .compatible = "epcos,b57330v2103",
294                 .data = &ntc_thermistor_id[5]},
295         { .compatible = "murata,ncp03wf104",
296                 .data = &ntc_thermistor_id[6] },
297         { .compatible = "murata,ncp15xh103",
298                 .data = &ntc_thermistor_id[7] },
299
300         /* Usage of vendor name "ntc" is deprecated */
301         { .compatible = "ntc,ncp15wb473",
302                 .data = &ntc_thermistor_id[0] },
303         { .compatible = "ntc,ncp18wb473",
304                 .data = &ntc_thermistor_id[1] },
305         { .compatible = "ntc,ncp21wb473",
306                 .data = &ntc_thermistor_id[2] },
307         { .compatible = "ntc,ncp03wb473",
308                 .data = &ntc_thermistor_id[3] },
309         { .compatible = "ntc,ncp15wl333",
310                 .data = &ntc_thermistor_id[4] },
311         { },
312 };
313 MODULE_DEVICE_TABLE(of, ntc_match);
314
315 static struct ntc_thermistor_platform_data *
316 ntc_thermistor_parse_dt(struct device *dev)
317 {
318         struct iio_channel *chan;
319         enum iio_chan_type type;
320         struct device_node *np = dev->of_node;
321         struct ntc_thermistor_platform_data *pdata;
322         int ret;
323
324         if (!np)
325                 return NULL;
326
327         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
328         if (!pdata)
329                 return ERR_PTR(-ENOMEM);
330
331         chan = devm_iio_channel_get(dev, NULL);
332         if (IS_ERR(chan))
333                 return ERR_CAST(chan);
334
335         ret = iio_get_channel_type(chan, &type);
336         if (ret < 0)
337                 return ERR_PTR(ret);
338
339         if (type != IIO_VOLTAGE)
340                 return ERR_PTR(-EINVAL);
341
342         if (of_property_read_u32(np, "pullup-uv", &pdata->pullup_uv))
343                 return ERR_PTR(-ENODEV);
344         if (of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm))
345                 return ERR_PTR(-ENODEV);
346         if (of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm))
347                 return ERR_PTR(-ENODEV);
348
349         if (of_find_property(np, "connected-positive", NULL))
350                 pdata->connect = NTC_CONNECTED_POSITIVE;
351         else /* status change should be possible if not always on. */
352                 pdata->connect = NTC_CONNECTED_GROUND;
353
354         pdata->chan = chan;
355         pdata->read_uv = ntc_adc_iio_read;
356
357         return pdata;
358 }
359 #else
360 static struct ntc_thermistor_platform_data *
361 ntc_thermistor_parse_dt(struct device *dev)
362 {
363         return NULL;
364 }
365
366 #define ntc_match       NULL
367
368 #endif
369
370 static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
371 {
372         if (divisor == 0 && dividend == 0)
373                 return 0;
374         if (divisor == 0)
375                 return UINT_MAX;
376         return div64_u64(dividend, divisor);
377 }
378
379 static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uv)
380 {
381         struct ntc_thermistor_platform_data *pdata = data->pdata;
382         u32 puv = pdata->pullup_uv;
383         u64 n, puo, pdo;
384         puo = pdata->pullup_ohm;
385         pdo = pdata->pulldown_ohm;
386
387         if (uv == 0)
388                 return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
389                         INT_MAX : 0;
390         if (uv >= puv)
391                 return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
392                         0 : INT_MAX;
393
394         if (pdata->connect == NTC_CONNECTED_POSITIVE && puo == 0)
395                 n = div_u64(pdo * (puv - uv), uv);
396         else if (pdata->connect == NTC_CONNECTED_GROUND && pdo == 0)
397                 n = div_u64(puo * uv, puv - uv);
398         else if (pdata->connect == NTC_CONNECTED_POSITIVE)
399                 n = div64_u64_safe(pdo * puo * (puv - uv),
400                                 puo * uv - pdo * (puv - uv));
401         else
402                 n = div64_u64_safe(pdo * puo * uv, pdo * (puv - uv) - puo * uv);
403
404         if (n > INT_MAX)
405                 n = INT_MAX;
406         return n;
407 }
408
409 static void lookup_comp(struct ntc_data *data, unsigned int ohm,
410                         int *i_low, int *i_high)
411 {
412         int start, end, mid;
413
414         /*
415          * Handle special cases: Resistance is higher than or equal to
416          * resistance in first table entry, or resistance is lower or equal
417          * to resistance in last table entry.
418          * In these cases, return i_low == i_high, either pointing to the
419          * beginning or to the end of the table depending on the condition.
420          */
421         if (ohm >= data->comp[0].ohm) {
422                 *i_low = 0;
423                 *i_high = 0;
424                 return;
425         }
426         if (ohm <= data->comp[data->n_comp - 1].ohm) {
427                 *i_low = data->n_comp - 1;
428                 *i_high = data->n_comp - 1;
429                 return;
430         }
431
432         /* Do a binary search on compensation table */
433         start = 0;
434         end = data->n_comp;
435         while (start < end) {
436                 mid = start + (end - start) / 2;
437                 /*
438                  * start <= mid < end
439                  * data->comp[start].ohm > ohm >= data->comp[end].ohm
440                  *
441                  * We could check for "ohm == data->comp[mid].ohm" here, but
442                  * that is a quite unlikely condition, and we would have to
443                  * check again after updating start. Check it at the end instead
444                  * for simplicity.
445                  */
446                 if (ohm >= data->comp[mid].ohm) {
447                         end = mid;
448                 } else {
449                         start = mid + 1;
450                         /*
451                          * ohm >= data->comp[start].ohm might be true here,
452                          * since we set start to mid + 1. In that case, we are
453                          * done. We could keep going, but the condition is quite
454                          * likely to occur, so it is worth checking for it.
455                          */
456                         if (ohm >= data->comp[start].ohm)
457                                 end = start;
458                 }
459                 /*
460                  * start <= end
461                  * data->comp[start].ohm >= ohm >= data->comp[end].ohm
462                  */
463         }
464         /*
465          * start == end
466          * ohm >= data->comp[end].ohm
467          */
468         *i_low = end;
469         if (ohm == data->comp[end].ohm)
470                 *i_high = end;
471         else
472                 *i_high = end - 1;
473 }
474
475 static int get_temp_mc(struct ntc_data *data, unsigned int ohm)
476 {
477         int low, high;
478         int temp;
479
480         lookup_comp(data, ohm, &low, &high);
481         if (low == high) {
482                 /* Unable to use linear approximation */
483                 temp = data->comp[low].temp_c * 1000;
484         } else {
485                 temp = data->comp[low].temp_c * 1000 +
486                         ((data->comp[high].temp_c - data->comp[low].temp_c) *
487                          1000 * ((int)ohm - (int)data->comp[low].ohm)) /
488                         ((int)data->comp[high].ohm - (int)data->comp[low].ohm);
489         }
490         return temp;
491 }
492
493 static int ntc_thermistor_get_ohm(struct ntc_data *data)
494 {
495         int read_uv;
496
497         if (data->pdata->read_ohm)
498                 return data->pdata->read_ohm();
499
500         if (data->pdata->read_uv) {
501                 read_uv = data->pdata->read_uv(data->pdata);
502                 if (read_uv < 0)
503                         return read_uv;
504                 return get_ohm_of_thermistor(data, read_uv);
505         }
506         return -EINVAL;
507 }
508
509 static int ntc_read_temp(void *data, int *temp)
510 {
511         int ohm;
512
513         ohm = ntc_thermistor_get_ohm(data);
514         if (ohm < 0)
515                 return ohm;
516
517         *temp = get_temp_mc(data, ohm);
518
519         return 0;
520 }
521
522 static ssize_t ntc_show_type(struct device *dev,
523                 struct device_attribute *attr, char *buf)
524 {
525         return sprintf(buf, "4\n");
526 }
527
528 static ssize_t ntc_show_temp(struct device *dev,
529                 struct device_attribute *attr, char *buf)
530 {
531         struct ntc_data *data = dev_get_drvdata(dev);
532         int ohm;
533
534         ohm = ntc_thermistor_get_ohm(data);
535         if (ohm < 0)
536                 return ohm;
537
538         return sprintf(buf, "%d\n", get_temp_mc(data, ohm));
539 }
540
541 static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0);
542 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ntc_show_temp, NULL, 0);
543
544 static struct attribute *ntc_attrs[] = {
545         &sensor_dev_attr_temp1_type.dev_attr.attr,
546         &sensor_dev_attr_temp1_input.dev_attr.attr,
547         NULL,
548 };
549 ATTRIBUTE_GROUPS(ntc);
550
551 static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = {
552         .get_temp = ntc_read_temp,
553 };
554
555 static int ntc_thermistor_probe(struct platform_device *pdev)
556 {
557         struct thermal_zone_device *tz;
558         struct device *dev = &pdev->dev;
559         const struct of_device_id *of_id =
560                         of_match_device(of_match_ptr(ntc_match), dev);
561         const struct platform_device_id *pdev_id;
562         struct ntc_thermistor_platform_data *pdata;
563         struct device *hwmon_dev;
564         struct ntc_data *data;
565
566         pdata = ntc_thermistor_parse_dt(dev);
567         if (IS_ERR(pdata))
568                 return PTR_ERR(pdata);
569         else if (pdata == NULL)
570                 pdata = dev_get_platdata(dev);
571
572         if (!pdata) {
573                 dev_err(dev, "No platform init data supplied.\n");
574                 return -ENODEV;
575         }
576
577         /* Either one of the two is required. */
578         if (!pdata->read_uv && !pdata->read_ohm) {
579                 dev_err(dev,
580                         "Both read_uv and read_ohm missing. Need either one of the two.\n");
581                 return -EINVAL;
582         }
583
584         if (pdata->read_uv && pdata->read_ohm) {
585                 dev_warn(dev,
586                          "Only one of read_uv and read_ohm is needed; ignoring read_uv.\n");
587                 pdata->read_uv = NULL;
588         }
589
590         if (pdata->read_uv && (pdata->pullup_uv == 0 ||
591                                 (pdata->pullup_ohm == 0 && pdata->connect ==
592                                  NTC_CONNECTED_GROUND) ||
593                                 (pdata->pulldown_ohm == 0 && pdata->connect ==
594                                  NTC_CONNECTED_POSITIVE) ||
595                                 (pdata->connect != NTC_CONNECTED_POSITIVE &&
596                                  pdata->connect != NTC_CONNECTED_GROUND))) {
597                 dev_err(dev, "Required data to use read_uv not supplied.\n");
598                 return -EINVAL;
599         }
600
601         data = devm_kzalloc(dev, sizeof(struct ntc_data), GFP_KERNEL);
602         if (!data)
603                 return -ENOMEM;
604
605         pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
606
607         data->pdata = pdata;
608
609         switch (pdev_id->driver_data) {
610         case TYPE_NCPXXWB473:
611                 data->comp = ncpXXwb473;
612                 data->n_comp = ARRAY_SIZE(ncpXXwb473);
613                 break;
614         case TYPE_NCPXXWL333:
615                 data->comp = ncpXXwl333;
616                 data->n_comp = ARRAY_SIZE(ncpXXwl333);
617                 break;
618         case TYPE_B57330V2103:
619                 data->comp = b57330v2103;
620                 data->n_comp = ARRAY_SIZE(b57330v2103);
621                 break;
622         case TYPE_NCPXXWF104:
623                 data->comp = ncpXXwf104;
624                 data->n_comp = ARRAY_SIZE(ncpXXwf104);
625                 break;
626         case TYPE_NCPXXXH103:
627                 data->comp = ncpXXxh103;
628                 data->n_comp = ARRAY_SIZE(ncpXXxh103);
629                 break;
630         default:
631                 dev_err(dev, "Unknown device type: %lu(%s)\n",
632                                 pdev_id->driver_data, pdev_id->name);
633                 return -EINVAL;
634         }
635
636         hwmon_dev = devm_hwmon_device_register_with_groups(dev, pdev_id->name,
637                                                            data, ntc_groups);
638         if (IS_ERR(hwmon_dev)) {
639                 dev_err(dev, "unable to register as hwmon device.\n");
640                 return PTR_ERR(hwmon_dev);
641         }
642
643         dev_info(dev, "Thermistor type: %s successfully probed.\n",
644                  pdev_id->name);
645
646         tz = devm_thermal_zone_of_sensor_register(dev, 0, data,
647                                                   &ntc_of_thermal_ops);
648         if (IS_ERR(tz))
649                 dev_dbg(dev, "Failed to register to thermal fw.\n");
650
651         return 0;
652 }
653
654 static struct platform_driver ntc_thermistor_driver = {
655         .driver = {
656                 .name = "ntc-thermistor",
657                 .of_match_table = of_match_ptr(ntc_match),
658         },
659         .probe = ntc_thermistor_probe,
660         .id_table = ntc_thermistor_id,
661 };
662
663 module_platform_driver(ntc_thermistor_driver);
664
665 MODULE_DESCRIPTION("NTC Thermistor Driver");
666 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
667 MODULE_LICENSE("GPL");
668 MODULE_ALIAS("platform:ntc-thermistor");