aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNaveen Krishna Chatradhi <ch.naveen@samsung.com>2013-03-13 00:08:20 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-04-08 00:16:38 -0400
commit9e8269de100dd0be1199778dc175ff22417aebd2 (patch)
tree743aa1c1d90be98c11d297e055c557162e98d8c3
parent4b5e536b0e948b5c756aa1d57218371c242f768d (diff)
hwmon: (ntc_thermistor) Add DT with IIO support to NTC thermistor driver
This patch adds DT support to NTC driver to parse the platform data. Also adds the support to work as an iio device client. During the probe ntc driver gets the respective channels of ADC and uses iio_raw_read calls to get the ADC converted value. Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com> [Guenter Roeck: fixed Kconfig dependencies; use ERR_CAST] Tested-by: Doug Anderson <dianders@chromium.org> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt29
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/hwmon/ntc_thermistor.c145
-rw-r--r--include/linux/platform_data/ntc_thermistor.h8
4 files changed, 163 insertions, 20 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
new file mode 100644
index 000000000000..c6f66674f19c
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -0,0 +1,29 @@
1NTC Thermistor hwmon sensors
2-------------------------------
3
4Requires node properties:
5- "compatible" value : one of
6 "ntc,ncp15wb473"
7 "ntc,ncp18wb473"
8 "ntc,ncp21wb473"
9 "ntc,ncp03wb473"
10 "ntc,ncp15wl333"
11- "pullup-uv" Pull up voltage in micro volts
12- "pullup-ohm" Pull up resistor value in ohms
13- "pulldown-ohm" Pull down resistor value in ohms
14- "connected-positive" Always ON, If not specified.
15 Status change is possible.
16- "io-channels" Channel node of ADC to be used for
17 conversion.
18
19Read more about iio bindings at
20 Documentation/devicetree/bindings/iio/iio-bindings.txt
21
22Example:
23 ncp15wb473@0 {
24 compatible = "ntc,ncp15wb473";
25 pullup-uv = <1800000>;
26 pullup-ohm = <47000>;
27 pulldown-ohm = <0>;
28 io-channels = <&adc 3>;
29 };
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index aaa14f4a0f7d..47d2176957a0 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -899,6 +899,7 @@ config SENSORS_MCP3021
899 899
900config SENSORS_NTC_THERMISTOR 900config SENSORS_NTC_THERMISTOR
901 tristate "NTC thermistor support" 901 tristate "NTC thermistor support"
902 depends on (!OF && !IIO) || (OF && IIO)
902 help 903 help
903 This driver supports NTC thermistors sensor reading and its 904 This driver supports NTC thermistors sensor reading and its
904 interpretation. The driver can also monitor the temperature and 905 interpretation. The driver can also monitor the temperature and
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index b5f63f9c0ce1..d399197655e6 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -26,9 +26,16 @@
26#include <linux/math64.h> 26#include <linux/math64.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/err.h> 28#include <linux/err.h>
29#include <linux/of.h>
30#include <linux/of_device.h>
29 31
30#include <linux/platform_data/ntc_thermistor.h> 32#include <linux/platform_data/ntc_thermistor.h>
31 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
32#include <linux/hwmon.h> 39#include <linux/hwmon.h>
33#include <linux/hwmon-sysfs.h> 40#include <linux/hwmon-sysfs.h>
34 41
@@ -37,6 +44,15 @@ struct ntc_compensation {
37 unsigned int ohm; 44 unsigned int ohm;
38}; 45};
39 46
47static const struct platform_device_id ntc_thermistor_id[] = {
48 { "ncp15wb473", TYPE_NCPXXWB473 },
49 { "ncp18wb473", TYPE_NCPXXWB473 },
50 { "ncp21wb473", TYPE_NCPXXWB473 },
51 { "ncp03wb473", TYPE_NCPXXWB473 },
52 { "ncp15wl333", TYPE_NCPXXWL333 },
53 { },
54};
55
40/* 56/*
41 * A compensation table should be sorted by the values of .ohm 57 * A compensation table should be sorted by the values of .ohm
42 * in descending order. 58 * in descending order.
@@ -125,6 +141,92 @@ struct ntc_data {
125 char name[PLATFORM_NAME_SIZE]; 141 char name[PLATFORM_NAME_SIZE];
126}; 142};
127 143
144#ifdef CONFIG_OF
145static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
146{
147 struct iio_channel *channel = pdata->chan;
148 unsigned int result;
149 int val, ret;
150
151 ret = iio_read_channel_raw(channel, &val);
152 if (ret < 0) {
153 pr_err("read channel() error: %d\n", ret);
154 return ret;
155 }
156
157 /* unit: mV */
158 result = pdata->pullup_uV * val;
159 result >>= 12;
160
161 return result;
162}
163
164static const struct of_device_id ntc_match[] = {
165 { .compatible = "ntc,ncp15wb473",
166 .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
167 { .compatible = "ntc,ncp18wb473",
168 .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
169 { .compatible = "ntc,ncp21wb473",
170 .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
171 { .compatible = "ntc,ncp03wb473",
172 .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
173 { .compatible = "ntc,ncp15wl333",
174 .data = &ntc_thermistor_id[TYPE_NCPXXWL333] },
175 { },
176};
177MODULE_DEVICE_TABLE(of, ntc_match);
178
179static struct ntc_thermistor_platform_data *
180ntc_thermistor_parse_dt(struct platform_device *pdev)
181{
182 struct iio_channel *chan;
183 struct device_node *np = pdev->dev.of_node;
184 struct ntc_thermistor_platform_data *pdata;
185
186 if (!np)
187 return NULL;
188
189 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
190 if (!pdata)
191 return ERR_PTR(-ENOMEM);
192
193 chan = iio_channel_get(&pdev->dev, NULL);
194 if (IS_ERR(chan))
195 return ERR_CAST(chan);
196
197 if (of_property_read_u32(np, "pullup-uv", &pdata->pullup_uV))
198 return ERR_PTR(-ENODEV);
199 if (of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm))
200 return ERR_PTR(-ENODEV);
201 if (of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm))
202 return ERR_PTR(-ENODEV);
203
204 if (of_find_property(np, "connected-positive", NULL))
205 pdata->connect = NTC_CONNECTED_POSITIVE;
206 else /* status change should be possible if not always on. */
207 pdata->connect = NTC_CONNECTED_GROUND;
208
209 pdata->chan = chan;
210 pdata->read_uV = ntc_adc_iio_read;
211
212 return pdata;
213}
214static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
215{
216 if (pdata->chan)
217 iio_channel_release(pdata->chan);
218}
219#else
220static struct ntc_thermistor_platform_data *
221ntc_thermistor_parse_dt(struct platform_device *pdev)
222{
223 return NULL;
224}
225
226static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
227{ }
228#endif
229
128static inline u64 div64_u64_safe(u64 dividend, u64 divisor) 230static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
129{ 231{
130 if (divisor == 0 && dividend == 0) 232 if (divisor == 0 && dividend == 0)
@@ -259,7 +361,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
259 return data->pdata->read_ohm(); 361 return data->pdata->read_ohm();
260 362
261 if (data->pdata->read_uV) { 363 if (data->pdata->read_uV) {
262 read_uV = data->pdata->read_uV(); 364 read_uV = data->pdata->read_uV(data->pdata);
263 if (read_uV < 0) 365 if (read_uV < 0)
264 return read_uV; 366 return read_uV;
265 return get_ohm_of_thermistor(data, read_uV); 367 return get_ohm_of_thermistor(data, read_uV);
@@ -311,9 +413,18 @@ static const struct attribute_group ntc_attr_group = {
311 413
312static int ntc_thermistor_probe(struct platform_device *pdev) 414static int ntc_thermistor_probe(struct platform_device *pdev)
313{ 415{
416 const struct of_device_id *of_id =
417 of_match_device(of_match_ptr(ntc_match), &pdev->dev);
418 const struct platform_device_id *pdev_id;
419 struct ntc_thermistor_platform_data *pdata;
314 struct ntc_data *data; 420 struct ntc_data *data;
315 struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data; 421 int ret;
316 int ret = 0; 422
423 pdata = ntc_thermistor_parse_dt(pdev);
424 if (IS_ERR(pdata))
425 return PTR_ERR(pdata);
426 else if (pdata == NULL)
427 pdata = pdev->dev.platform_data;
317 428
318 if (!pdata) { 429 if (!pdata) {
319 dev_err(&pdev->dev, "No platform init data supplied.\n"); 430 dev_err(&pdev->dev, "No platform init data supplied.\n");
@@ -349,11 +460,13 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
349 if (!data) 460 if (!data)
350 return -ENOMEM; 461 return -ENOMEM;
351 462
463 pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
464
352 data->dev = &pdev->dev; 465 data->dev = &pdev->dev;
353 data->pdata = pdata; 466 data->pdata = pdata;
354 strlcpy(data->name, pdev->id_entry->name, sizeof(data->name)); 467 strlcpy(data->name, pdev_id->name, sizeof(data->name));
355 468
356 switch (pdev->id_entry->driver_data) { 469 switch (pdev_id->driver_data) {
357 case TYPE_NCPXXWB473: 470 case TYPE_NCPXXWB473:
358 data->comp = ncpXXwb473; 471 data->comp = ncpXXwb473;
359 data->n_comp = ARRAY_SIZE(ncpXXwb473); 472 data->n_comp = ARRAY_SIZE(ncpXXwb473);
@@ -364,8 +477,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
364 break; 477 break;
365 default: 478 default:
366 dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n", 479 dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
367 pdev->id_entry->driver_data, 480 pdev_id->driver_data, pdev_id->name);
368 pdev->id_entry->name);
369 return -EINVAL; 481 return -EINVAL;
370 } 482 }
371 483
@@ -384,39 +496,34 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
384 goto err_after_sysfs; 496 goto err_after_sysfs;
385 } 497 }
386 498
387 dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n", 499 dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n",
388 pdev->name, pdev->id, pdev->id_entry->name, 500 pdev->name);
389 pdev->id_entry->driver_data); 501
390 return 0; 502 return 0;
391err_after_sysfs: 503err_after_sysfs:
392 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); 504 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
505 ntc_iio_channel_release(pdata);
393 return ret; 506 return ret;
394} 507}
395 508
396static int ntc_thermistor_remove(struct platform_device *pdev) 509static int ntc_thermistor_remove(struct platform_device *pdev)
397{ 510{
398 struct ntc_data *data = platform_get_drvdata(pdev); 511 struct ntc_data *data = platform_get_drvdata(pdev);
512 struct ntc_thermistor_platform_data *pdata = data->pdata;
399 513
400 hwmon_device_unregister(data->hwmon_dev); 514 hwmon_device_unregister(data->hwmon_dev);
401 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); 515 sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
516 ntc_iio_channel_release(pdata);
402 platform_set_drvdata(pdev, NULL); 517 platform_set_drvdata(pdev, NULL);
403 518
404 return 0; 519 return 0;
405} 520}
406 521
407static const struct platform_device_id ntc_thermistor_id[] = {
408 { "ncp15wb473", TYPE_NCPXXWB473 },
409 { "ncp18wb473", TYPE_NCPXXWB473 },
410 { "ncp21wb473", TYPE_NCPXXWB473 },
411 { "ncp03wb473", TYPE_NCPXXWB473 },
412 { "ncp15wl333", TYPE_NCPXXWL333 },
413 { },
414};
415
416static struct platform_driver ntc_thermistor_driver = { 522static struct platform_driver ntc_thermistor_driver = {
417 .driver = { 523 .driver = {
418 .name = "ntc-thermistor", 524 .name = "ntc-thermistor",
419 .owner = THIS_MODULE, 525 .owner = THIS_MODULE,
526 .of_match_table = of_match_ptr(ntc_match),
420 }, 527 },
421 .probe = ntc_thermistor_probe, 528 .probe = ntc_thermistor_probe,
422 .remove = ntc_thermistor_remove, 529 .remove = ntc_thermistor_remove,
diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
index 88734e871e3a..fa95f9cbe7ea 100644
--- a/include/linux/platform_data/ntc_thermistor.h
+++ b/include/linux/platform_data/ntc_thermistor.h
@@ -21,6 +21,8 @@
21#ifndef _LINUX_NTC_H 21#ifndef _LINUX_NTC_H
22#define _LINUX_NTC_H 22#define _LINUX_NTC_H
23 23
24struct iio_channel;
25
24enum ntc_thermistor_type { 26enum ntc_thermistor_type {
25 TYPE_NCPXXWB473, 27 TYPE_NCPXXWB473,
26 TYPE_NCPXXWL333, 28 TYPE_NCPXXWL333,
@@ -39,13 +41,17 @@ struct ntc_thermistor_platform_data {
39 * described at Documentation/hwmon/ntc_thermistor 41 * described at Documentation/hwmon/ntc_thermistor
40 * 42 *
41 * pullup/down_ohm: 0 for infinite / not-connected 43 * pullup/down_ohm: 0 for infinite / not-connected
44 *
45 * chan: iio_channel pointer to communicate with the ADC which the
46 * thermistor is using for conversion of the analog values.
42 */ 47 */
43 int (*read_uV)(void); 48 int (*read_uV)(struct ntc_thermistor_platform_data *);
44 unsigned int pullup_uV; 49 unsigned int pullup_uV;
45 50
46 unsigned int pullup_ohm; 51 unsigned int pullup_ohm;
47 unsigned int pulldown_ohm; 52 unsigned int pulldown_ohm;
48 enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect; 53 enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
54 struct iio_channel *chan;
49 55
50 int (*read_ohm)(void); 56 int (*read_ohm)(void);
51}; 57};