This patch adds DT support to NTC driver to parse the
platform data.
Also adds the support to work as an iio device.
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 <[email protected]>
---
Changes since v1:
1. Combimed all the IIO and OF/device tree changes under CONFIG_OF
2. parse_dt function now checks for of_node and iio_channels sanity
3. merged both the patches to single, as they cant build independently
4. used pdev_id for proper logging and support of DT and non DT based probing
5. Rebased on linux git tree
6. Added documentation for device tree bindings
Sorry, for posting a patch rebased on local working branch.
Thanks Doug, for pointing out.
.../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 +++++
drivers/hwmon/ntc_thermistor.c | 133 +++++++++++++++++---
include/linux/platform_data/ntc_thermistor.h | 6 +-
3 files changed, 148 insertions(+), 20 deletions(-)
create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
new file mode 100644
index 0000000..731a78f
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -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, value (1) is assigned.
+- "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>;
+ };
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index b5f63f9..81d5bdc 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -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>
@@ -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.
@@ -125,6 +141,76 @@ 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 * (s64) 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 int ntc_thermistor_parse_dt(struct ntc_thermistor_platform_data *pdata,
+ struct platform_device *pdev)
+{
+ struct iio_channel *chan;
+ struct device_node *np = pdev->dev.of_node;
+
+ if (!np)
+ return -ENODEV;
+
+ chan = iio_channel_get(&pdev->dev, NULL);
+ if (IS_ERR(chan))
+ return IS_ERR(chan);
+
+ of_property_read_u32(np, "pullup-uV", &pdata->pullup_uV);
+ of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm);
+ of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm);
+
+ 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 0;
+}
+#else
+static int ntc_thermistor_parse_dt(struct ntc_thermistor_platform_data *pdata,
+ struct platform_device *pdev)
+{
+ return -ENODEV;
+}
+#endif
+
static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
{
if (divisor == 0 && dividend == 0)
@@ -259,7 +345,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);
@@ -311,9 +397,22 @@ 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 = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ ret = ntc_thermistor_parse_dt(pdata, pdev);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ else if (ret < 0)
+ pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "No platform init data supplied.\n");
@@ -349,11 +448,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));
+ strncpy(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);
@@ -364,8 +465,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;
}
@@ -384,39 +484,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);
+ iio_channel_release(pdata->chan);
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);
+ iio_channel_release(pdata->chan);
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,
diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
index 88734e8..6cf5081 100644
--- a/include/linux/platform_data/ntc_thermistor.h
+++ b/include/linux/platform_data/ntc_thermistor.h
@@ -39,13 +39,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);
};
--
1.7.9.5
On Tue, Mar 12, 2013 at 02:09:26PM +0530, Naveen Krishna Chatradhi wrote:
> This patch adds DT support to NTC driver to parse the
> platform data.
>
> Also adds the support to work as an iio device.
>
> 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 <[email protected]>
Much better, but I still have a couple of comments.
> ---
> Changes since v1:
> 1. Combimed all the IIO and OF/device tree changes under CONFIG_OF
> 2. parse_dt function now checks for of_node and iio_channels sanity
> 3. merged both the patches to single, as they cant build independently
> 4. used pdev_id for proper logging and support of DT and non DT based probing
> 5. Rebased on linux git tree
> 6. Added documentation for device tree bindings
>
> Sorry, for posting a patch rebased on local working branch.
> Thanks Doug, for pointing out.
> .../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 +++++
> drivers/hwmon/ntc_thermistor.c | 133 +++++++++++++++++---
> include/linux/platform_data/ntc_thermistor.h | 6 +-
You'll still need the conditional dependency on IIO in Kconfig.
Something like
depends on IIO if OF
if that works, or alternatively
select IIO if OF
if that is acceptable.
> 3 files changed, 148 insertions(+), 20 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
>
> diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> new file mode 100644
> index 0000000..731a78f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> @@ -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, value (1) is assigned.
> +- "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>;
Is uV (uppercase) acceptable in dt bindings ?
> + pullup-ohm = <47000>;
> + pulldown-ohm = <0>;
> + io-channels = <&adc 3>;
> + };
> diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> index b5f63f9..81d5bdc 100644
> --- a/drivers/hwmon/ntc_thermistor.c
> +++ b/drivers/hwmon/ntc_thermistor.c
> @@ -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>
>
> @@ -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.
> @@ -125,6 +141,76 @@ 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 * (s64) val;
result is int, so the s64 typecast does not provide any value.
Should result be s64 to avoid overflow errors ?
> + 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 int ntc_thermistor_parse_dt(struct ntc_thermistor_platform_data *pdata,
> + struct platform_device *pdev)
Common style is to align the second line with '('. Applies everywhere.
> +{
> + struct iio_channel *chan;
> + struct device_node *np = pdev->dev.of_node;
> +
> + if (!np)
> + return -ENODEV;
> +
> + chan = iio_channel_get(&pdev->dev, NULL);
> + if (IS_ERR(chan))
> + return IS_ERR(chan);
return PTR_ERR(chann);
> +
> + of_property_read_u32(np, "pullup-uV", &pdata->pullup_uV);
> + of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm);
> + of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm);
> +
The above properties are mandatory, so you should check the return value
of of_property_read_u32() and return an error if a property is not defined.
> + 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 0;
> +}
> +#else
> +static int ntc_thermistor_parse_dt(struct ntc_thermistor_platform_data *pdata,
> + struct platform_device *pdev)
> +{
> + return -ENODEV;
> +}
> +#endif
> +
> static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
> {
> if (divisor == 0 && dividend == 0)
> @@ -259,7 +345,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);
> @@ -311,9 +397,22 @@ 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 = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata)
> + return -ENOMEM;
> +
That allocation should really be in ntc_thermistor_parse_dt, otherwise
it is wasted in the non-OF case. ntc_thermistor_parse_dt can return a
pointer to it or ERR_PTR on failure or NULL in the non-OF case (or if
np is NULL). Then you don't need to check for -EPROBE_DEFER but can
just use
pdata = ntc_thermistor_parse_dt(pdev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
if (pdata == NULL)
pdata = pdev->dev.platform_data;
This way you also catch other errors returned by iio_channel_get().
> + ret = ntc_thermistor_parse_dt(pdata, pdev);
> + if (ret == -EPROBE_DEFER)
> + return ret;
> + else if (ret < 0)
else is unnecessary here.
> + pdata = pdev->dev.platform_data;
>
> if (!pdata) {
> dev_err(&pdev->dev, "No platform init data supplied.\n");
> @@ -349,11 +448,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));
> + strncpy(data->name, pdev_id->name, sizeof(data->name));
Why strncpy instead of strlcpy ?
That means there is no guarantee that data->name is 0 terminated.
Not that I mind if you have a good reason for not using strlcpy,
but I just don't see it.
>
> - switch (pdev->id_entry->driver_data) {
> + switch (pdev_id->driver_data) {
> case TYPE_NCPXXWB473:
> data->comp = ncpXXwb473;
> data->n_comp = ARRAY_SIZE(ncpXXwb473);
> @@ -364,8 +465,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;
> }
>
> @@ -384,39 +484,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);
> + iio_channel_release(pdata->chan);
With that non-conditional, IIO would be mandatory. Also, iio_channel_release
does not check if the parameter is NULL, so if it is (ie in the non-OF case)
there will be a nice crash.
I would suggest to add a helper function such as
ntc_iio_channel_release()
to be defined in the conditional OF code above. It would be an empty function
for the non-OF case and otherwise call iio_channel_release().
To avoid such problems, you should try to build the driver with IIO disabled.
> 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);
> + iio_channel_release(pdata->chan);
Same here.
> 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,
> diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
> index 88734e8..6cf5081 100644
> --- a/include/linux/platform_data/ntc_thermistor.h
> +++ b/include/linux/platform_data/ntc_thermistor.h
> @@ -39,13 +39,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;
Please specify
struct iio_channel;
at the beginning of the include file.
>
> int (*read_ohm)(void);
> };
> --
> 1.7.9.5
>
>
Hi,
On Tue, Mar 12, 2013 at 6:45 AM, Guenter Roeck <[email protected]> wrote:
> On Tue, Mar 12, 2013 at 02:09:26PM +0530, Naveen Krishna Chatradhi wrote:
>> This patch adds DT support to NTC driver to parse the
>> platform data.
>>
>> Also adds the support to work as an iio device.
>>
>> 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 <[email protected]>
I know that there is still work to do to address Guenter's comments,
but I spent a little time playing with this today to see what else was
missing and actually got it working. :) I'll add a "Tested-by" once
Naveen reposts.
I sent up my patches that I needed to the ADC + device trees to get it
working, but I just realized that I forgot to CC Guenter. Doh! In
case you're curious, you can find them at:
* https://patchwork.kernel.org/patch/2260231/
* https://patchwork.kernel.org/patch/2260211/
* https://patchwork.kernel.org/patch/2260221/
* https://patchwork.kernel.org/patch/2260201/
> You'll still need the conditional dependency on IIO in Kconfig.
> Something like
> depends on IIO if OF
> if that works, or alternatively
> select IIO if OF
> if that is acceptable.
This was important for me. I had IIO setup as a module and adc
configured an in-kernel. Without the above I got a nice linker error.
;)
The syntax that worked for me was 'select IIO if OF'. I don't think
you can do a conditional depends on (it didn't work for me and I
couldn't find any examples like that).
>> +Read more about iio bindings at
>> + Documentation/devicetree/bindings/iio/iio-bindings.txt
>> +
BTW: the above line had a whitespace error on it. Double-check that
it's gone for the next version.
-Doug
This patch adds DT support to NTC driver to parse the
platform data.
Also adds the support to work as an iio device.
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 <[email protected]>
---
Changes since v2:
1. Modified Kconfig to select IIO only if OF is defined
2. changed "pullup-uV" to "pullup-uv" in dt bindings
3. allocate pdata in ntc_thermistor_parse_dt and modify the return
value to platform data pointer, handled other errors for dt bindings.
4. used strlcpy instead of strncpy as the former handles
null termination
5. made a wrapper function for iio_channel release and defined to
null in case of non-DT
6. removed a typecase of (s64) which is not needed.
Guenter Roeck, Thanks for your valuble time and comments. They really
are helping me learn and do better on my future patches.
Doug, Thanks for your support and testing these patches.
.../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 ++++
drivers/hwmon/Kconfig | 1 +
drivers/hwmon/ntc_thermistor.c | 144 +++++++++++++++++---
include/linux/platform_data/ntc_thermistor.h | 8 +-
4 files changed, 162 insertions(+), 20 deletions(-)
create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
new file mode 100644
index 0000000..c6f6667
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -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>;
+ };
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 89ac1cb..cc47c12 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -879,6 +879,7 @@ config SENSORS_MCP3021
config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support"
+ select IIO if OF
help
This driver supports NTC thermistors sensor reading and its
interpretation. The driver can also monitor the temperature and
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index b5f63f9..ba0f7b0 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -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>
@@ -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.
@@ -125,6 +141,91 @@ 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 (struct ntc_thermistor_platform_data *)PTR_ERR(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)
+{
+ 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)
@@ -259,7 +360,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);
@@ -311,9 +412,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);
+ if (pdata == NULL)
+ pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "No platform init data supplied.\n");
@@ -349,11 +459,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);
@@ -364,8 +476,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;
}
@@ -384,39 +495,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,
diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
index 88734e8..fa95f9c 100644
--- a/include/linux/platform_data/ntc_thermistor.h
+++ b/include/linux/platform_data/ntc_thermistor.h
@@ -21,6 +21,8 @@
#ifndef _LINUX_NTC_H
#define _LINUX_NTC_H
+struct iio_channel;
+
enum ntc_thermistor_type {
TYPE_NCPXXWB473,
TYPE_NCPXXWL333,
@@ -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);
};
--
1.7.9.5
On Wed, Mar 13, 2013 at 08:25:09AM +0530, Naveen Krishna Chatradhi wrote:
> This patch adds DT support to NTC driver to parse the
> platform data.
>
> Also adds the support to work as an iio device.
>
> 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 <[email protected]>
Almost there ...
> ---
> Changes since v2:
> 1. Modified Kconfig to select IIO only if OF is defined
> 2. changed "pullup-uV" to "pullup-uv" in dt bindings
> 3. allocate pdata in ntc_thermistor_parse_dt and modify the return
> value to platform data pointer, handled other errors for dt bindings.
> 4. used strlcpy instead of strncpy as the former handles
> null termination
> 5. made a wrapper function for iio_channel release and defined to
> null in case of non-DT
> 6. removed a typecase of (s64) which is not needed.
>
> Guenter Roeck, Thanks for your valuble time and comments. They really
> are helping me learn and do better on my future patches.
>
> Doug, Thanks for your support and testing these patches.
>
> .../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 ++++
> drivers/hwmon/Kconfig | 1 +
> drivers/hwmon/ntc_thermistor.c | 144 +++++++++++++++++---
> include/linux/platform_data/ntc_thermistor.h | 8 +-
> 4 files changed, 162 insertions(+), 20 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
>
> diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> new file mode 100644
> index 0000000..c6f6667
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> @@ -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>;
> + };
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 89ac1cb..cc47c12 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -879,6 +879,7 @@ config SENSORS_MCP3021
>
> config SENSORS_NTC_THERMISTOR
> tristate "NTC thermistor support"
> + select IIO if OF
> help
> This driver supports NTC thermistors sensor reading and its
> interpretation. The driver can also monitor the temperature and
> diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> index b5f63f9..ba0f7b0 100644
> --- a/drivers/hwmon/ntc_thermistor.c
> +++ b/drivers/hwmon/ntc_thermistor.c
> @@ -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>
>
> @@ -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.
> @@ -125,6 +141,91 @@ 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 (struct ntc_thermistor_platform_data *)PTR_ERR(chan);
That should probably be
return ERR_PTR(PTR_ERR(chan));
There are a couple of similar cases elsewhere in the code.
> +
> + 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)
> +{
> + iio_channel_release(pdata->chan);
Imagine the case where OF is defined but np == NULL, ie there was no devicetree
data and platform data was provided. In this case, pdata->chan will be NULL,
and you'll have a nice crash at hand. So you'll need to add a NULL check before
calling iio_channel_release.
Thanks,
Guenter
> +}
> +#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)
> @@ -259,7 +360,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);
> @@ -311,9 +412,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);
> + if (pdata == NULL)
> + pdata = pdev->dev.platform_data;
>
> if (!pdata) {
> dev_err(&pdev->dev, "No platform init data supplied.\n");
> @@ -349,11 +459,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);
> @@ -364,8 +476,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;
> }
>
> @@ -384,39 +495,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,
> diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
> index 88734e8..fa95f9c 100644
> --- a/include/linux/platform_data/ntc_thermistor.h
> +++ b/include/linux/platform_data/ntc_thermistor.h
> @@ -21,6 +21,8 @@
> #ifndef _LINUX_NTC_H
> #define _LINUX_NTC_H
>
> +struct iio_channel;
> +
> enum ntc_thermistor_type {
> TYPE_NCPXXWB473,
> TYPE_NCPXXWL333,
> @@ -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);
> };
> --
> 1.7.9.5
>
>
This patch adds DT support to NTC driver to parse the
platform data.
Also adds the support to work as an iio device.
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 <[email protected]>
---
Changes since v3:
1. Added a NULL check before iio_channel_release
2. Modified a return statement
Guenter Roeck, Its wonderful working with you. Thanks.
.../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 ++++
drivers/hwmon/Kconfig | 1 +
drivers/hwmon/ntc_thermistor.c | 145 +++++++++++++++++---
include/linux/platform_data/ntc_thermistor.h | 8 +-
4 files changed, 163 insertions(+), 20 deletions(-)
create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
new file mode 100644
index 0000000..c6f6667
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -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>;
+ };
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 89ac1cb..cc47c12 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -879,6 +879,7 @@ config SENSORS_MCP3021
config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support"
+ select IIO if OF
help
This driver supports NTC thermistors sensor reading and its
interpretation. The driver can also monitor the temperature and
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index b5f63f9..a6997a1 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -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>
@@ -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.
@@ -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_PTR(PTR_ERR(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)
@@ -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);
@@ -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");
@@ -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);
@@ -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;
}
@@ -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,
diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
index 88734e8..fa95f9c 100644
--- a/include/linux/platform_data/ntc_thermistor.h
+++ b/include/linux/platform_data/ntc_thermistor.h
@@ -21,6 +21,8 @@
#ifndef _LINUX_NTC_H
#define _LINUX_NTC_H
+struct iio_channel;
+
enum ntc_thermistor_type {
TYPE_NCPXXWB473,
TYPE_NCPXXWL333,
@@ -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);
};
--
1.7.9.5
On Wed, Mar 13, 2013 at 09:38:20AM +0530, Naveen Krishna Chatradhi wrote:
> This patch adds DT support to NTC driver to parse the
> platform data.
>
> Also adds the support to work as an iio device.
>
> 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 <[email protected]>
> ---
> Changes since v3:
> 1. Added a NULL check before iio_channel_release
> 2. Modified a return statement
>
> Guenter Roeck, Its wonderful working with you. Thanks.
>
My pleasure.
Patch looks ok to me now. I'll wait a couple of days to see if there is some
feedback from the devicetree folks. Unless there are objections, I'll then queue
it for 3.10.
Thanks,
Guenter
> .../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 ++++
> drivers/hwmon/Kconfig | 1 +
> drivers/hwmon/ntc_thermistor.c | 145 +++++++++++++++++---
> include/linux/platform_data/ntc_thermistor.h | 8 +-
> 4 files changed, 163 insertions(+), 20 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
>
> diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> new file mode 100644
> index 0000000..c6f6667
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> @@ -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>;
> + };
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 89ac1cb..cc47c12 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -879,6 +879,7 @@ config SENSORS_MCP3021
>
> config SENSORS_NTC_THERMISTOR
> tristate "NTC thermistor support"
> + select IIO if OF
> help
> This driver supports NTC thermistors sensor reading and its
> interpretation. The driver can also monitor the temperature and
> diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> index b5f63f9..a6997a1 100644
> --- a/drivers/hwmon/ntc_thermistor.c
> +++ b/drivers/hwmon/ntc_thermistor.c
> @@ -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>
>
> @@ -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.
> @@ -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_PTR(PTR_ERR(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)
> @@ -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);
> @@ -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");
> @@ -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);
> @@ -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;
> }
>
> @@ -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,
> diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
> index 88734e8..fa95f9c 100644
> --- a/include/linux/platform_data/ntc_thermistor.h
> +++ b/include/linux/platform_data/ntc_thermistor.h
> @@ -21,6 +21,8 @@
> #ifndef _LINUX_NTC_H
> #define _LINUX_NTC_H
>
> +struct iio_channel;
> +
> enum ntc_thermistor_type {
> TYPE_NCPXXWB473,
> TYPE_NCPXXWL333,
> @@ -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);
> };
> --
> 1.7.9.5
>
>
On Wed, Mar 13, 2013 at 09:38:20AM +0530, Naveen Krishna Chatradhi wrote:
> This patch adds DT support to NTC driver to parse the
> platform data.
>
> Also adds the support to work as an iio device.
>
> 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 <[email protected]>
Unfortunately there is still something we'll need to sort out:
fs/sysfs/Kconfig:1: symbol SYSFS is selected by AT91_ADC
drivers/iio/adc/Kconfig:85: symbol AT91_ADC depends on IIO
drivers/iio/Kconfig:5: symbol IIO is selected by SENSORS_NTC_THERMISTOR
drivers/hwmon/Kconfig:900: symbol SENSORS_NTC_THERMISTOR depends on HWMON
drivers/hwmon/Kconfig:5: symbol HWMON is selected by EEEPC_LAPTOP
drivers/platform/x86/Kconfig:477: symbol EEEPC_LAPTOP depends on
HOTPLUG_PCI
drivers/pci/hotplug/Kconfig:5: symbol HOTPLUG_PCI depends on SYSFS
So we can not just select IIO. I'll see if I can find a solution.
Guenter
> ---
> Changes since v3:
> 1. Added a NULL check before iio_channel_release
> 2. Modified a return statement
>
> Guenter Roeck, Its wonderful working with you. Thanks.
>
> .../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 ++++
> drivers/hwmon/Kconfig | 1 +
> drivers/hwmon/ntc_thermistor.c | 145 +++++++++++++++++---
> include/linux/platform_data/ntc_thermistor.h | 8 +-
> 4 files changed, 163 insertions(+), 20 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
>
> diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> new file mode 100644
> index 0000000..c6f6667
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
> @@ -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>;
> + };
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 89ac1cb..cc47c12 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -879,6 +879,7 @@ config SENSORS_MCP3021
>
> config SENSORS_NTC_THERMISTOR
> tristate "NTC thermistor support"
> + select IIO if OF
> help
> This driver supports NTC thermistors sensor reading and its
> interpretation. The driver can also monitor the temperature and
> diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> index b5f63f9..a6997a1 100644
> --- a/drivers/hwmon/ntc_thermistor.c
> +++ b/drivers/hwmon/ntc_thermistor.c
> @@ -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>
>
> @@ -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.
> @@ -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_PTR(PTR_ERR(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)
> @@ -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);
> @@ -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");
> @@ -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);
> @@ -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;
> }
>
> @@ -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,
> diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h
> index 88734e8..fa95f9c 100644
> --- a/include/linux/platform_data/ntc_thermistor.h
> +++ b/include/linux/platform_data/ntc_thermistor.h
> @@ -21,6 +21,8 @@
> #ifndef _LINUX_NTC_H
> #define _LINUX_NTC_H
>
> +struct iio_channel;
> +
> enum ntc_thermistor_type {
> TYPE_NCPXXWB473,
> TYPE_NCPXXWL333,
> @@ -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);
> };
> --
> 1.7.9.5
>
>
On Tue, Mar 12, 2013 at 09:52:26PM -0700, Guenter Roeck wrote:
> On Wed, Mar 13, 2013 at 09:38:20AM +0530, Naveen Krishna Chatradhi wrote:
> > This patch adds DT support to NTC driver to parse the
> > platform data.
> >
> > Also adds the support to work as an iio device.
> >
> > 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 <[email protected]>
>
> Unfortunately there is still something we'll need to sort out:
>
> fs/sysfs/Kconfig:1: symbol SYSFS is selected by AT91_ADC
> drivers/iio/adc/Kconfig:85: symbol AT91_ADC depends on IIO
> drivers/iio/Kconfig:5: symbol IIO is selected by SENSORS_NTC_THERMISTOR
> drivers/hwmon/Kconfig:900: symbol SENSORS_NTC_THERMISTOR depends on HWMON
> drivers/hwmon/Kconfig:5: symbol HWMON is selected by EEEPC_LAPTOP
> drivers/platform/x86/Kconfig:477: symbol EEEPC_LAPTOP depends on
> HOTPLUG_PCI
> drivers/pci/hotplug/Kconfig:5: symbol HOTPLUG_PCI depends on SYSFS
>
> So we can not just select IIO. I'll see if I can find a solution.
>
Here it is:
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f7adbe8..47d2176 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -899,7 +899,7 @@ config SENSORS_MCP3021
config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support"
- select IIO if OF
+ 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
I'll modify the patch accordingly. No need to resubmit.
Thanks,
Guenter
Hi,
On Tue, Mar 12, 2013 at 9:08 PM, Naveen Krishna Chatradhi
<[email protected]> wrote:
> This patch adds DT support to NTC driver to parse the
> platform data.
>
> Also adds the support to work as an iio device.
>
> 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 <[email protected]>
> ---
> Changes since v3:
> 1. Added a NULL check before iio_channel_release
> 2. Modified a return statement
>
> Guenter Roeck, Its wonderful working with you. Thanks.
>
> .../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 ++++
> drivers/hwmon/Kconfig | 1 +
> drivers/hwmon/ntc_thermistor.c | 145 +++++++++++++++++---
> include/linux/platform_data/ntc_thermistor.h | 8 +-
> 4 files changed, 163 insertions(+), 20 deletions(-)
I haven't done a full review of this code, but it I built it in (along
with other CLs to enable it on exynos5250-snow) and the thermistors
are accessible and report reasonable values.
localhost hwmon # grep "" /sys/class/hwmon/*/device/temp1_input
/sys/class/hwmon/hwmon0/device/temp1_input:37890
/sys/class/hwmon/hwmon1/device/temp1_input:38393
/sys/class/hwmon/hwmon2/device/temp1_input:37148
/sys/class/hwmon/hwmon3/device/temp1_input:38059
Tested-by: Doug Anderson <[email protected]>
On Wed, Mar 13, 2013 at 01:52:35PM -0700, Doug Anderson wrote:
> Hi,
>
> On Tue, Mar 12, 2013 at 9:08 PM, Naveen Krishna Chatradhi
> <[email protected]> wrote:
> > This patch adds DT support to NTC driver to parse the
> > platform data.
> >
> > Also adds the support to work as an iio device.
> >
> > 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 <[email protected]>
> > ---
> > Changes since v3:
> > 1. Added a NULL check before iio_channel_release
> > 2. Modified a return statement
> >
> > Guenter Roeck, Its wonderful working with you. Thanks.
> >
> > .../devicetree/bindings/hwmon/ntc_thermistor.txt | 29 ++++
> > drivers/hwmon/Kconfig | 1 +
> > drivers/hwmon/ntc_thermistor.c | 145 +++++++++++++++++---
> > include/linux/platform_data/ntc_thermistor.h | 8 +-
> > 4 files changed, 163 insertions(+), 20 deletions(-)
>
> I haven't done a full review of this code, but it I built it in (along
> with other CLs to enable it on exynos5250-snow) and the thermistors
> are accessible and report reasonable values.
>
> localhost hwmon # grep "" /sys/class/hwmon/*/device/temp1_input
> /sys/class/hwmon/hwmon0/device/temp1_input:37890
> /sys/class/hwmon/hwmon1/device/temp1_input:38393
> /sys/class/hwmon/hwmon2/device/temp1_input:37148
> /sys/class/hwmon/hwmon3/device/temp1_input:38059
>
> Tested-by: Doug Anderson <[email protected]>
>
Thanks!
Guenter