aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
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 /drivers/hwmon
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>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/hwmon/ntc_thermistor.c145
2 files changed, 127 insertions, 19 deletions
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,