Register an IIO channel to allow reading the temperature using the IIO
interface.
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
drivers/thermal/thermal-generic-adc.c | 56 +++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c
index ee3d0aa31406..14aef682e0fb 100644
--- a/drivers/thermal/thermal-generic-adc.c
+++ b/drivers/thermal/thermal-generic-adc.c
@@ -7,6 +7,7 @@
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*/
#include <linux/iio/consumer.h>
+#include <linux/iio/iio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -23,6 +24,10 @@ struct gadc_thermal_info {
int nlookup_table;
};
+struct gadc_iio {
+ struct gadc_thermal_info *gti;
+};
+
static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
{
int temp, temp_hi, temp_lo, adc_hi, adc_lo;
@@ -115,10 +120,44 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev,
return 0;
}
+static int gadc_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct gadc_iio *data = iio_priv(indio_dev);
+ int iio_val;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ ret = iio_read_channel_processed(data->gti->channel, &iio_val);
+ if (ret < 0)
+ return ret;
+
+ *val = gadc_thermal_adc_to_temp(data->gti, iio_val);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info gadc_adc_info = {
+ .read_raw = &gadc_adc_read_raw,
+};
+
+static const struct iio_chan_spec gadc_adc_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+};
+
static int gadc_thermal_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct gadc_thermal_info *gti;
+ struct iio_dev *indio_dev;
+ struct gadc_iio *data;
int ret;
if (!dev->of_node) {
@@ -153,6 +192,23 @@ static int gadc_thermal_probe(struct platform_device *pdev)
devm_thermal_add_hwmon_sysfs(dev, gti->tz_dev);
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->gti = gti;
+
+ indio_dev->name = pdev->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &gadc_adc_info;
+ indio_dev->channels = gadc_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(gadc_adc_channels);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register IIO device\n");
+
return 0;
}
--
2.51.0