xref: /linux/drivers/iio/temperature/iqs620at-temp.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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