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