18ba44710SJeff LaBundy // SPDX-License-Identifier: GPL-2.0+
28ba44710SJeff LaBundy /*
38ba44710SJeff LaBundy * Azoteq IQS620AT Temperature Sensor
48ba44710SJeff LaBundy *
58ba44710SJeff LaBundy * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com>
68ba44710SJeff LaBundy */
78ba44710SJeff LaBundy
88ba44710SJeff LaBundy #include <linux/device.h>
98ba44710SJeff LaBundy #include <linux/iio/iio.h>
108ba44710SJeff LaBundy #include <linux/kernel.h>
118ba44710SJeff LaBundy #include <linux/mfd/iqs62x.h>
128ba44710SJeff LaBundy #include <linux/module.h>
138ba44710SJeff LaBundy #include <linux/platform_device.h>
148ba44710SJeff LaBundy #include <linux/regmap.h>
158ba44710SJeff LaBundy
168ba44710SJeff LaBundy #define IQS620_TEMP_UI_OUT 0x1A
178ba44710SJeff LaBundy
188ba44710SJeff LaBundy #define IQS620_TEMP_SCALE 1000
198ba44710SJeff LaBundy #define IQS620_TEMP_OFFSET (-100)
20*9e444dbfSJeff LaBundy #define IQS620_TEMP_OFFSET_V3 (-40)
218ba44710SJeff LaBundy
iqs620_temp_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)228ba44710SJeff LaBundy static int iqs620_temp_read_raw(struct iio_dev *indio_dev,
238ba44710SJeff LaBundy struct iio_chan_spec const *chan,
248ba44710SJeff LaBundy int *val, int *val2, long mask)
258ba44710SJeff LaBundy {
268ba44710SJeff LaBundy struct iqs62x_core *iqs62x = iio_device_get_drvdata(indio_dev);
278ba44710SJeff LaBundy int ret;
288ba44710SJeff LaBundy __le16 val_buf;
298ba44710SJeff LaBundy
308ba44710SJeff LaBundy switch (mask) {
318ba44710SJeff LaBundy case IIO_CHAN_INFO_RAW:
328ba44710SJeff LaBundy ret = regmap_raw_read(iqs62x->regmap, IQS620_TEMP_UI_OUT,
338ba44710SJeff LaBundy &val_buf, sizeof(val_buf));
348ba44710SJeff LaBundy if (ret)
358ba44710SJeff LaBundy return ret;
368ba44710SJeff LaBundy
378ba44710SJeff LaBundy *val = le16_to_cpu(val_buf);
388ba44710SJeff LaBundy return IIO_VAL_INT;
398ba44710SJeff LaBundy
408ba44710SJeff LaBundy case IIO_CHAN_INFO_SCALE:
418ba44710SJeff LaBundy *val = IQS620_TEMP_SCALE;
428ba44710SJeff LaBundy return IIO_VAL_INT;
438ba44710SJeff LaBundy
448ba44710SJeff LaBundy case IIO_CHAN_INFO_OFFSET:
45*9e444dbfSJeff LaBundy *val = iqs62x->hw_num < IQS620_HW_NUM_V3 ? IQS620_TEMP_OFFSET
46*9e444dbfSJeff LaBundy : IQS620_TEMP_OFFSET_V3;
478ba44710SJeff LaBundy return IIO_VAL_INT;
488ba44710SJeff LaBundy
498ba44710SJeff LaBundy default:
508ba44710SJeff LaBundy return -EINVAL;
518ba44710SJeff LaBundy }
528ba44710SJeff LaBundy }
538ba44710SJeff LaBundy
548ba44710SJeff LaBundy static const struct iio_info iqs620_temp_info = {
558ba44710SJeff LaBundy .read_raw = &iqs620_temp_read_raw,
568ba44710SJeff LaBundy };
578ba44710SJeff LaBundy
588ba44710SJeff LaBundy static const struct iio_chan_spec iqs620_temp_channels[] = {
598ba44710SJeff LaBundy {
608ba44710SJeff LaBundy .type = IIO_TEMP,
618ba44710SJeff LaBundy .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
628ba44710SJeff LaBundy BIT(IIO_CHAN_INFO_SCALE) |
638ba44710SJeff LaBundy BIT(IIO_CHAN_INFO_OFFSET),
648ba44710SJeff LaBundy },
658ba44710SJeff LaBundy };
668ba44710SJeff LaBundy
iqs620_temp_probe(struct platform_device * pdev)678ba44710SJeff LaBundy static int iqs620_temp_probe(struct platform_device *pdev)
688ba44710SJeff LaBundy {
698ba44710SJeff LaBundy struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent);
708ba44710SJeff LaBundy struct iio_dev *indio_dev;
718ba44710SJeff LaBundy
728ba44710SJeff LaBundy indio_dev = devm_iio_device_alloc(&pdev->dev, 0);
738ba44710SJeff LaBundy if (!indio_dev)
748ba44710SJeff LaBundy return -ENOMEM;
758ba44710SJeff LaBundy
768ba44710SJeff LaBundy iio_device_set_drvdata(indio_dev, iqs62x);
778ba44710SJeff LaBundy
788ba44710SJeff LaBundy indio_dev->modes = INDIO_DIRECT_MODE;
798ba44710SJeff LaBundy indio_dev->channels = iqs620_temp_channels;
808ba44710SJeff LaBundy indio_dev->num_channels = ARRAY_SIZE(iqs620_temp_channels);
818ba44710SJeff LaBundy indio_dev->name = iqs62x->dev_desc->dev_name;
828ba44710SJeff LaBundy indio_dev->info = &iqs620_temp_info;
838ba44710SJeff LaBundy
848ba44710SJeff LaBundy return devm_iio_device_register(&pdev->dev, indio_dev);
858ba44710SJeff LaBundy }
868ba44710SJeff LaBundy
878ba44710SJeff LaBundy static struct platform_driver iqs620_temp_platform_driver = {
888ba44710SJeff LaBundy .driver = {
898ba44710SJeff LaBundy .name = "iqs620at-temp",
908ba44710SJeff LaBundy },
918ba44710SJeff LaBundy .probe = iqs620_temp_probe,
928ba44710SJeff LaBundy };
938ba44710SJeff LaBundy module_platform_driver(iqs620_temp_platform_driver);
948ba44710SJeff LaBundy
958ba44710SJeff LaBundy MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
968ba44710SJeff LaBundy MODULE_DESCRIPTION("Azoteq IQS620AT Temperature Sensor");
978ba44710SJeff LaBundy MODULE_LICENSE("GPL");
988ba44710SJeff LaBundy MODULE_ALIAS("platform:iqs620at-temp");
99