Skip to content

Commit 9e8269d

Browse files
Naveen Krishna Chatradhigroeck
authored andcommitted
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>
1 parent 4b5e536 commit 9e8269d

File tree

4 files changed

+163
-20
lines changed

4 files changed

+163
-20
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
NTC Thermistor hwmon sensors
2+
-------------------------------
3+
4+
Requires 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+
19+
Read more about iio bindings at
20+
Documentation/devicetree/bindings/iio/iio-bindings.txt
21+
22+
Example:
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+
};

drivers/hwmon/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ config SENSORS_MCP3021
899899

900900
config SENSORS_NTC_THERMISTOR
901901
tristate "NTC thermistor support"
902+
depends on (!OF && !IIO) || (OF && IIO)
902903
help
903904
This driver supports NTC thermistors sensor reading and its
904905
interpretation. The driver can also monitor the temperature and

drivers/hwmon/ntc_thermistor.c

Lines changed: 126 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,16 @@
2626
#include <linux/math64.h>
2727
#include <linux/platform_device.h>
2828
#include <linux/err.h>
29+
#include <linux/of.h>
30+
#include <linux/of_device.h>
2931

3032
#include <linux/platform_data/ntc_thermistor.h>
3133

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+
3239
#include <linux/hwmon.h>
3340
#include <linux/hwmon-sysfs.h>
3441

@@ -37,6 +44,15 @@ struct ntc_compensation {
3744
unsigned int ohm;
3845
};
3946

47+
static 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+
4056
/*
4157
* A compensation table should be sorted by the values of .ohm
4258
* in descending order.
@@ -125,6 +141,92 @@ struct ntc_data {
125141
char name[PLATFORM_NAME_SIZE];
126142
};
127143

144+
#ifdef CONFIG_OF
145+
static 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+
164+
static 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+
};
177+
MODULE_DEVICE_TABLE(of, ntc_match);
178+
179+
static struct ntc_thermistor_platform_data *
180+
ntc_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+
}
214+
static 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
220+
static struct ntc_thermistor_platform_data *
221+
ntc_thermistor_parse_dt(struct platform_device *pdev)
222+
{
223+
return NULL;
224+
}
225+
226+
static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
227+
{ }
228+
#endif
229+
128230
static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
129231
{
130232
if (divisor == 0 && dividend == 0)
@@ -259,7 +361,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
259361
return data->pdata->read_ohm();
260362

261363
if (data->pdata->read_uV) {
262-
read_uV = data->pdata->read_uV();
364+
read_uV = data->pdata->read_uV(data->pdata);
263365
if (read_uV < 0)
264366
return read_uV;
265367
return get_ohm_of_thermistor(data, read_uV);
@@ -311,9 +413,18 @@ static const struct attribute_group ntc_attr_group = {
311413

312414
static int ntc_thermistor_probe(struct platform_device *pdev)
313415
{
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;
314420
struct ntc_data *data;
315-
struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
316-
int ret = 0;
421+
int ret;
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;
317428

318429
if (!pdata) {
319430
dev_err(&pdev->dev, "No platform init data supplied.\n");
@@ -349,11 +460,13 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
349460
if (!data)
350461
return -ENOMEM;
351462

463+
pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
464+
352465
data->dev = &pdev->dev;
353466
data->pdata = pdata;
354-
strlcpy(data->name, pdev->id_entry->name, sizeof(data->name));
467+
strlcpy(data->name, pdev_id->name, sizeof(data->name));
355468

356-
switch (pdev->id_entry->driver_data) {
469+
switch (pdev_id->driver_data) {
357470
case TYPE_NCPXXWB473:
358471
data->comp = ncpXXwb473;
359472
data->n_comp = ARRAY_SIZE(ncpXXwb473);
@@ -364,8 +477,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
364477
break;
365478
default:
366479
dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
367-
pdev->id_entry->driver_data,
368-
pdev->id_entry->name);
480+
pdev_id->driver_data, pdev_id->name);
369481
return -EINVAL;
370482
}
371483

@@ -384,39 +496,34 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
384496
goto err_after_sysfs;
385497
}
386498

387-
dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n",
388-
pdev->name, pdev->id, pdev->id_entry->name,
389-
pdev->id_entry->driver_data);
499+
dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n",
500+
pdev->name);
501+
390502
return 0;
391503
err_after_sysfs:
392504
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
505+
ntc_iio_channel_release(pdata);
393506
return ret;
394507
}
395508

396509
static int ntc_thermistor_remove(struct platform_device *pdev)
397510
{
398511
struct ntc_data *data = platform_get_drvdata(pdev);
512+
struct ntc_thermistor_platform_data *pdata = data->pdata;
399513

400514
hwmon_device_unregister(data->hwmon_dev);
401515
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
516+
ntc_iio_channel_release(pdata);
402517
platform_set_drvdata(pdev, NULL);
403518

404519
return 0;
405520
}
406521

407-
static 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-
416522
static struct platform_driver ntc_thermistor_driver = {
417523
.driver = {
418524
.name = "ntc-thermistor",
419525
.owner = THIS_MODULE,
526+
.of_match_table = of_match_ptr(ntc_match),
420527
},
421528
.probe = ntc_thermistor_probe,
422529
.remove = ntc_thermistor_remove,

include/linux/platform_data/ntc_thermistor.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#ifndef _LINUX_NTC_H
2222
#define _LINUX_NTC_H
2323

24+
struct iio_channel;
25+
2426
enum ntc_thermistor_type {
2527
TYPE_NCPXXWB473,
2628
TYPE_NCPXXWL333,
@@ -39,13 +41,17 @@ struct ntc_thermistor_platform_data {
3941
* described at Documentation/hwmon/ntc_thermistor
4042
*
4143
* 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.
4247
*/
43-
int (*read_uV)(void);
48+
int (*read_uV)(struct ntc_thermistor_platform_data *);
4449
unsigned int pullup_uV;
4550

4651
unsigned int pullup_ohm;
4752
unsigned int pulldown_ohm;
4853
enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
54+
struct iio_channel *chan;
4955

5056
int (*read_ohm)(void);
5157
};

0 commit comments

Comments
 (0)