Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 363030
b: refs/heads/master
c: 9e8269d
h: refs/heads/master
v: v3
  • Loading branch information
Naveen Krishna Chatradhi authored and Guenter Roeck committed Apr 8, 2013
1 parent 70004ff commit 65a00ee
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 21 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4b5e536b0e948b5c756aa1d57218371c242f768d
refs/heads/master: 9e8269de100dd0be1199778dc175ff22417aebd2
29 changes: 29 additions & 0 deletions trunk/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
NTC Thermistor hwmon sensors
-------------------------------

Requires node properties:
- "compatible" value : one of
"ntc,ncp15wb473"
"ntc,ncp18wb473"
"ntc,ncp21wb473"
"ntc,ncp03wb473"
"ntc,ncp15wl333"
- "pullup-uv" Pull up voltage in micro volts
- "pullup-ohm" Pull up resistor value in ohms
- "pulldown-ohm" Pull down resistor value in ohms
- "connected-positive" Always ON, If not specified.
Status change is possible.
- "io-channels" Channel node of ADC to be used for
conversion.

Read more about iio bindings at
Documentation/devicetree/bindings/iio/iio-bindings.txt

Example:
ncp15wb473@0 {
compatible = "ntc,ncp15wb473";
pullup-uv = <1800000>;
pullup-ohm = <47000>;
pulldown-ohm = <0>;
io-channels = <&adc 3>;
};
1 change: 1 addition & 0 deletions trunk/drivers/hwmon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ config SENSORS_MCP3021

config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support"
depends on (!OF && !IIO) || (OF && IIO)
help
This driver supports NTC thermistors sensor reading and its
interpretation. The driver can also monitor the temperature and
Expand Down
145 changes: 126 additions & 19 deletions trunk/drivers/hwmon/ntc_thermistor.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,16 @@
#include <linux/math64.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_device.h>

#include <linux/platform_data/ntc_thermistor.h>

#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#include <linux/iio/consumer.h>

#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>

Expand All @@ -37,6 +44,15 @@ struct ntc_compensation {
unsigned int ohm;
};

static const struct platform_device_id ntc_thermistor_id[] = {
{ "ncp15wb473", TYPE_NCPXXWB473 },
{ "ncp18wb473", TYPE_NCPXXWB473 },
{ "ncp21wb473", TYPE_NCPXXWB473 },
{ "ncp03wb473", TYPE_NCPXXWB473 },
{ "ncp15wl333", TYPE_NCPXXWL333 },
{ },
};

/*
* A compensation table should be sorted by the values of .ohm
* in descending order.
Expand Down Expand Up @@ -125,6 +141,92 @@ struct ntc_data {
char name[PLATFORM_NAME_SIZE];
};

#ifdef CONFIG_OF
static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
{
struct iio_channel *channel = pdata->chan;
unsigned int result;
int val, ret;

ret = iio_read_channel_raw(channel, &val);
if (ret < 0) {
pr_err("read channel() error: %d\n", ret);
return ret;
}

/* unit: mV */
result = pdata->pullup_uV * val;
result >>= 12;

return result;
}

static const struct of_device_id ntc_match[] = {
{ .compatible = "ntc,ncp15wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp18wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp21wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp03wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp15wl333",
.data = &ntc_thermistor_id[TYPE_NCPXXWL333] },
{ },
};
MODULE_DEVICE_TABLE(of, ntc_match);

static struct ntc_thermistor_platform_data *
ntc_thermistor_parse_dt(struct platform_device *pdev)
{
struct iio_channel *chan;
struct device_node *np = pdev->dev.of_node;
struct ntc_thermistor_platform_data *pdata;

if (!np)
return NULL;

pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);

chan = iio_channel_get(&pdev->dev, NULL);
if (IS_ERR(chan))
return ERR_CAST(chan);

if (of_property_read_u32(np, "pullup-uv", &pdata->pullup_uV))
return ERR_PTR(-ENODEV);
if (of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm))
return ERR_PTR(-ENODEV);
if (of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm))
return ERR_PTR(-ENODEV);

if (of_find_property(np, "connected-positive", NULL))
pdata->connect = NTC_CONNECTED_POSITIVE;
else /* status change should be possible if not always on. */
pdata->connect = NTC_CONNECTED_GROUND;

pdata->chan = chan;
pdata->read_uV = ntc_adc_iio_read;

return pdata;
}
static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
{
if (pdata->chan)
iio_channel_release(pdata->chan);
}
#else
static struct ntc_thermistor_platform_data *
ntc_thermistor_parse_dt(struct platform_device *pdev)
{
return NULL;
}

static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
{ }
#endif

static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
{
if (divisor == 0 && dividend == 0)
Expand Down Expand Up @@ -259,7 +361,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
return data->pdata->read_ohm();

if (data->pdata->read_uV) {
read_uV = data->pdata->read_uV();
read_uV = data->pdata->read_uV(data->pdata);
if (read_uV < 0)
return read_uV;
return get_ohm_of_thermistor(data, read_uV);
Expand Down Expand Up @@ -311,9 +413,18 @@ static const struct attribute_group ntc_attr_group = {

static int ntc_thermistor_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(of_match_ptr(ntc_match), &pdev->dev);
const struct platform_device_id *pdev_id;
struct ntc_thermistor_platform_data *pdata;
struct ntc_data *data;
struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
int ret = 0;
int ret;

pdata = ntc_thermistor_parse_dt(pdev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
else if (pdata == NULL)
pdata = pdev->dev.platform_data;

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

pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);

data->dev = &pdev->dev;
data->pdata = pdata;
strlcpy(data->name, pdev->id_entry->name, sizeof(data->name));
strlcpy(data->name, pdev_id->name, sizeof(data->name));

switch (pdev->id_entry->driver_data) {
switch (pdev_id->driver_data) {
case TYPE_NCPXXWB473:
data->comp = ncpXXwb473;
data->n_comp = ARRAY_SIZE(ncpXXwb473);
Expand All @@ -364,8 +477,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
break;
default:
dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
pdev->id_entry->driver_data,
pdev->id_entry->name);
pdev_id->driver_data, pdev_id->name);
return -EINVAL;
}

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

dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n",
pdev->name, pdev->id, pdev->id_entry->name,
pdev->id_entry->driver_data);
dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n",
pdev->name);

return 0;
err_after_sysfs:
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
ntc_iio_channel_release(pdata);
return ret;
}

static int ntc_thermistor_remove(struct platform_device *pdev)
{
struct ntc_data *data = platform_get_drvdata(pdev);
struct ntc_thermistor_platform_data *pdata = data->pdata;

hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
ntc_iio_channel_release(pdata);
platform_set_drvdata(pdev, NULL);

return 0;
}

static const struct platform_device_id ntc_thermistor_id[] = {
{ "ncp15wb473", TYPE_NCPXXWB473 },
{ "ncp18wb473", TYPE_NCPXXWB473 },
{ "ncp21wb473", TYPE_NCPXXWB473 },
{ "ncp03wb473", TYPE_NCPXXWB473 },
{ "ncp15wl333", TYPE_NCPXXWL333 },
{ },
};

static struct platform_driver ntc_thermistor_driver = {
.driver = {
.name = "ntc-thermistor",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(ntc_match),
},
.probe = ntc_thermistor_probe,
.remove = ntc_thermistor_remove,
Expand Down
8 changes: 7 additions & 1 deletion trunk/include/linux/platform_data/ntc_thermistor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#ifndef _LINUX_NTC_H
#define _LINUX_NTC_H

struct iio_channel;

enum ntc_thermistor_type {
TYPE_NCPXXWB473,
TYPE_NCPXXWL333,
Expand All @@ -39,13 +41,17 @@ struct ntc_thermistor_platform_data {
* described at Documentation/hwmon/ntc_thermistor
*
* pullup/down_ohm: 0 for infinite / not-connected
*
* chan: iio_channel pointer to communicate with the ADC which the
* thermistor is using for conversion of the analog values.
*/
int (*read_uV)(void);
int (*read_uV)(struct ntc_thermistor_platform_data *);
unsigned int pullup_uV;

unsigned int pullup_ohm;
unsigned int pulldown_ohm;
enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
struct iio_channel *chan;

int (*read_ohm)(void);
};
Expand Down

0 comments on commit 65a00ee

Please sign in to comment.