Register an IIO channel to allow reading the temperature using the IIO
interface.

Signed-off-by: Luca Weiss <[email protected]>
---
 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 <[email protected]>
  */
 #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


Reply via email to