xref: /openbmc/linux/drivers/iio/chemical/atlas-sensor.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
10d15190fSMatt Ranostay // SPDX-License-Identifier: GPL-2.0+
20d15190fSMatt Ranostay /*
30d15190fSMatt Ranostay  * atlas-sensor.c - Support for Atlas Scientific OEM SM sensors
40d15190fSMatt Ranostay  *
50d15190fSMatt Ranostay  * Copyright (C) 2015-2019 Konsulko Group
60d15190fSMatt Ranostay  * Author: Matt Ranostay <matt.ranostay@konsulko.com>
70d15190fSMatt Ranostay  */
80d15190fSMatt Ranostay 
90d15190fSMatt Ranostay #include <linux/module.h>
100d15190fSMatt Ranostay #include <linux/init.h>
110d15190fSMatt Ranostay #include <linux/interrupt.h>
120d15190fSMatt Ranostay #include <linux/delay.h>
130d15190fSMatt Ranostay #include <linux/mutex.h>
140d15190fSMatt Ranostay #include <linux/err.h>
150d15190fSMatt Ranostay #include <linux/irq.h>
160d15190fSMatt Ranostay #include <linux/irq_work.h>
170d15190fSMatt Ranostay #include <linux/i2c.h>
18a867e898SJonathan Cameron #include <linux/mod_devicetable.h>
190d15190fSMatt Ranostay #include <linux/regmap.h>
200d15190fSMatt Ranostay #include <linux/iio/iio.h>
210d15190fSMatt Ranostay #include <linux/iio/buffer.h>
220d15190fSMatt Ranostay #include <linux/iio/trigger.h>
230d15190fSMatt Ranostay #include <linux/iio/trigger_consumer.h>
240d15190fSMatt Ranostay #include <linux/iio/triggered_buffer.h>
250d15190fSMatt Ranostay #include <linux/pm_runtime.h>
260d15190fSMatt Ranostay 
270d15190fSMatt Ranostay #define ATLAS_REGMAP_NAME	"atlas_regmap"
280d15190fSMatt Ranostay #define ATLAS_DRV_NAME		"atlas"
290d15190fSMatt Ranostay 
300d15190fSMatt Ranostay #define ATLAS_REG_DEV_TYPE		0x00
310d15190fSMatt Ranostay #define ATLAS_REG_DEV_VERSION		0x01
320d15190fSMatt Ranostay 
330d15190fSMatt Ranostay #define ATLAS_REG_INT_CONTROL		0x04
340d15190fSMatt Ranostay #define ATLAS_REG_INT_CONTROL_EN	BIT(3)
350d15190fSMatt Ranostay 
360d15190fSMatt Ranostay #define ATLAS_REG_PWR_CONTROL		0x06
370d15190fSMatt Ranostay 
380d15190fSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS	0x0d
390d15190fSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_MASK	0x07
400d15190fSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_LOW	BIT(0)
410d15190fSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_MID	BIT(1)
420d15190fSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_HIGH	BIT(2)
430d15190fSMatt Ranostay 
440d15190fSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS		0x0f
450d15190fSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_MASK		0x0f
460d15190fSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_DRY		BIT(0)
470d15190fSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_SINGLE	BIT(1)
480d15190fSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_LOW		BIT(2)
490d15190fSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_HIGH		BIT(3)
500d15190fSMatt Ranostay 
51a751b8e4SMatt Ranostay #define ATLAS_REG_DO_CALIB_STATUS		0x09
52a751b8e4SMatt Ranostay #define ATLAS_REG_DO_CALIB_STATUS_MASK		0x03
53a751b8e4SMatt Ranostay #define ATLAS_REG_DO_CALIB_STATUS_PRESSURE	BIT(0)
54a751b8e4SMatt Ranostay #define ATLAS_REG_DO_CALIB_STATUS_DO		BIT(1)
55a751b8e4SMatt Ranostay 
56b101c93cSMatt Ranostay #define ATLAS_REG_RTD_DATA		0x0e
57b101c93cSMatt Ranostay 
580d15190fSMatt Ranostay #define ATLAS_REG_PH_TEMP_DATA		0x0e
590d15190fSMatt Ranostay #define ATLAS_REG_PH_DATA		0x16
600d15190fSMatt Ranostay 
610d15190fSMatt Ranostay #define ATLAS_REG_EC_PROBE		0x08
620d15190fSMatt Ranostay #define ATLAS_REG_EC_TEMP_DATA		0x10
630d15190fSMatt Ranostay #define ATLAS_REG_EC_DATA		0x18
640d15190fSMatt Ranostay #define ATLAS_REG_TDS_DATA		0x1c
650d15190fSMatt Ranostay #define ATLAS_REG_PSS_DATA		0x20
660d15190fSMatt Ranostay 
670d15190fSMatt Ranostay #define ATLAS_REG_ORP_CALIB_STATUS	0x0d
680d15190fSMatt Ranostay #define ATLAS_REG_ORP_DATA		0x0e
690d15190fSMatt Ranostay 
70a751b8e4SMatt Ranostay #define ATLAS_REG_DO_TEMP_DATA		0x12
71a751b8e4SMatt Ranostay #define ATLAS_REG_DO_DATA		0x22
72a751b8e4SMatt Ranostay 
730d15190fSMatt Ranostay #define ATLAS_PH_INT_TIME_IN_MS		450
740d15190fSMatt Ranostay #define ATLAS_EC_INT_TIME_IN_MS		650
750d15190fSMatt Ranostay #define ATLAS_ORP_INT_TIME_IN_MS	450
76a751b8e4SMatt Ranostay #define ATLAS_DO_INT_TIME_IN_MS		450
77b101c93cSMatt Ranostay #define ATLAS_RTD_INT_TIME_IN_MS	450
780d15190fSMatt Ranostay 
790d15190fSMatt Ranostay enum {
800d15190fSMatt Ranostay 	ATLAS_PH_SM,
810d15190fSMatt Ranostay 	ATLAS_EC_SM,
820d15190fSMatt Ranostay 	ATLAS_ORP_SM,
83a751b8e4SMatt Ranostay 	ATLAS_DO_SM,
84b101c93cSMatt Ranostay 	ATLAS_RTD_SM,
850d15190fSMatt Ranostay };
860d15190fSMatt Ranostay 
870d15190fSMatt Ranostay struct atlas_data {
880d15190fSMatt Ranostay 	struct i2c_client *client;
890d15190fSMatt Ranostay 	struct iio_trigger *trig;
900d15190fSMatt Ranostay 	struct atlas_device *chip;
910d15190fSMatt Ranostay 	struct regmap *regmap;
920d15190fSMatt Ranostay 	struct irq_work work;
93d4578dc0SMatt Ranostay 	unsigned int interrupt_enabled;
94b0f5d8dbSJonathan Cameron 	/* 96-bit data + 32-bit pad + 64-bit timestamp */
95b0f5d8dbSJonathan Cameron 	__be32 buffer[6] __aligned(8);
960d15190fSMatt Ranostay };
970d15190fSMatt Ranostay 
980d15190fSMatt Ranostay static const struct regmap_config atlas_regmap_config = {
990d15190fSMatt Ranostay 	.name = ATLAS_REGMAP_NAME,
1000d15190fSMatt Ranostay 	.reg_bits = 8,
1010d15190fSMatt Ranostay 	.val_bits = 8,
1020d15190fSMatt Ranostay };
1030d15190fSMatt Ranostay 
atlas_buffer_num_channels(const struct iio_chan_spec * spec)1044766897aSMatt Ranostay static int atlas_buffer_num_channels(const struct iio_chan_spec *spec)
1054766897aSMatt Ranostay {
1064766897aSMatt Ranostay 	int idx = 0;
1074766897aSMatt Ranostay 
1084766897aSMatt Ranostay 	for (; spec->type != IIO_TIMESTAMP; spec++)
1094766897aSMatt Ranostay 		idx++;
1104766897aSMatt Ranostay 
1114766897aSMatt Ranostay 	return idx;
1124766897aSMatt Ranostay };
1134766897aSMatt Ranostay 
1140d15190fSMatt Ranostay static const struct iio_chan_spec atlas_ph_channels[] = {
1150d15190fSMatt Ranostay 	{
1160d15190fSMatt Ranostay 		.type = IIO_PH,
1170d15190fSMatt Ranostay 		.address = ATLAS_REG_PH_DATA,
1180d15190fSMatt Ranostay 		.info_mask_separate =
1190d15190fSMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
1200d15190fSMatt Ranostay 		.scan_index = 0,
1210d15190fSMatt Ranostay 		.scan_type = {
1220d15190fSMatt Ranostay 			.sign = 'u',
1230d15190fSMatt Ranostay 			.realbits = 32,
1240d15190fSMatt Ranostay 			.storagebits = 32,
1250d15190fSMatt Ranostay 			.endianness = IIO_BE,
1260d15190fSMatt Ranostay 		},
1270d15190fSMatt Ranostay 	},
1280d15190fSMatt Ranostay 	IIO_CHAN_SOFT_TIMESTAMP(1),
1290d15190fSMatt Ranostay 	{
1300d15190fSMatt Ranostay 		.type = IIO_TEMP,
1310d15190fSMatt Ranostay 		.address = ATLAS_REG_PH_TEMP_DATA,
1320d15190fSMatt Ranostay 		.info_mask_separate =
1330d15190fSMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
1340d15190fSMatt Ranostay 		.output = 1,
1350d15190fSMatt Ranostay 		.scan_index = -1
1360d15190fSMatt Ranostay 	},
1370d15190fSMatt Ranostay };
1380d15190fSMatt Ranostay 
139a751b8e4SMatt Ranostay #define ATLAS_CONCENTRATION_CHANNEL(_idx, _addr) \
1400d15190fSMatt Ranostay 	{\
1410d15190fSMatt Ranostay 		.type = IIO_CONCENTRATION, \
1420d15190fSMatt Ranostay 		.indexed = 1, \
1430d15190fSMatt Ranostay 		.channel = _idx, \
1440d15190fSMatt Ranostay 		.address = _addr, \
1450d15190fSMatt Ranostay 		.info_mask_separate = \
1460d15190fSMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
1470d15190fSMatt Ranostay 		.scan_index = _idx + 1, \
1480d15190fSMatt Ranostay 		.scan_type = { \
1490d15190fSMatt Ranostay 			.sign = 'u', \
1500d15190fSMatt Ranostay 			.realbits = 32, \
1510d15190fSMatt Ranostay 			.storagebits = 32, \
1520d15190fSMatt Ranostay 			.endianness = IIO_BE, \
1530d15190fSMatt Ranostay 		}, \
1540d15190fSMatt Ranostay 	}
1550d15190fSMatt Ranostay 
1560d15190fSMatt Ranostay static const struct iio_chan_spec atlas_ec_channels[] = {
1570d15190fSMatt Ranostay 	{
1580d15190fSMatt Ranostay 		.type = IIO_ELECTRICALCONDUCTIVITY,
1590d15190fSMatt Ranostay 		.address = ATLAS_REG_EC_DATA,
1600d15190fSMatt Ranostay 		.info_mask_separate =
1610d15190fSMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
1620d15190fSMatt Ranostay 		.scan_index = 0,
1630d15190fSMatt Ranostay 		.scan_type = {
1640d15190fSMatt Ranostay 			.sign = 'u',
1650d15190fSMatt Ranostay 			.realbits = 32,
1660d15190fSMatt Ranostay 			.storagebits = 32,
1670d15190fSMatt Ranostay 			.endianness = IIO_BE,
1680d15190fSMatt Ranostay 		},
1690d15190fSMatt Ranostay 	},
170a751b8e4SMatt Ranostay 	ATLAS_CONCENTRATION_CHANNEL(0, ATLAS_REG_TDS_DATA),
171a751b8e4SMatt Ranostay 	ATLAS_CONCENTRATION_CHANNEL(1, ATLAS_REG_PSS_DATA),
1720d15190fSMatt Ranostay 	IIO_CHAN_SOFT_TIMESTAMP(3),
1730d15190fSMatt Ranostay 	{
1740d15190fSMatt Ranostay 		.type = IIO_TEMP,
1750d15190fSMatt Ranostay 		.address = ATLAS_REG_EC_TEMP_DATA,
1760d15190fSMatt Ranostay 		.info_mask_separate =
1770d15190fSMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
1780d15190fSMatt Ranostay 		.output = 1,
1790d15190fSMatt Ranostay 		.scan_index = -1
1800d15190fSMatt Ranostay 	},
1810d15190fSMatt Ranostay };
1820d15190fSMatt Ranostay 
1830d15190fSMatt Ranostay static const struct iio_chan_spec atlas_orp_channels[] = {
1840d15190fSMatt Ranostay 	{
1850d15190fSMatt Ranostay 		.type = IIO_VOLTAGE,
1860d15190fSMatt Ranostay 		.address = ATLAS_REG_ORP_DATA,
1870d15190fSMatt Ranostay 		.info_mask_separate =
1880d15190fSMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
1890d15190fSMatt Ranostay 		.scan_index = 0,
1900d15190fSMatt Ranostay 		.scan_type = {
1910d15190fSMatt Ranostay 			.sign = 's',
1920d15190fSMatt Ranostay 			.realbits = 32,
1930d15190fSMatt Ranostay 			.storagebits = 32,
1940d15190fSMatt Ranostay 			.endianness = IIO_BE,
1950d15190fSMatt Ranostay 		},
1960d15190fSMatt Ranostay 	},
1970d15190fSMatt Ranostay 	IIO_CHAN_SOFT_TIMESTAMP(1),
1980d15190fSMatt Ranostay };
1990d15190fSMatt Ranostay 
200a751b8e4SMatt Ranostay static const struct iio_chan_spec atlas_do_channels[] = {
20198bcead0SMatt Ranostay 	{
20298bcead0SMatt Ranostay 		.type = IIO_CONCENTRATION,
20398bcead0SMatt Ranostay 		.address = ATLAS_REG_DO_DATA,
20498bcead0SMatt Ranostay 		.info_mask_separate =
20598bcead0SMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
20698bcead0SMatt Ranostay 		.scan_index = 0,
20798bcead0SMatt Ranostay 		.scan_type = {
20898bcead0SMatt Ranostay 			.sign = 'u',
20998bcead0SMatt Ranostay 			.realbits = 32,
21098bcead0SMatt Ranostay 			.storagebits = 32,
21198bcead0SMatt Ranostay 			.endianness = IIO_BE,
21298bcead0SMatt Ranostay 		},
21398bcead0SMatt Ranostay 	},
214a751b8e4SMatt Ranostay 	IIO_CHAN_SOFT_TIMESTAMP(1),
215a751b8e4SMatt Ranostay 	{
216a751b8e4SMatt Ranostay 		.type = IIO_TEMP,
217a751b8e4SMatt Ranostay 		.address = ATLAS_REG_DO_TEMP_DATA,
218a751b8e4SMatt Ranostay 		.info_mask_separate =
219a751b8e4SMatt Ranostay 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
220a751b8e4SMatt Ranostay 		.output = 1,
221a751b8e4SMatt Ranostay 		.scan_index = -1
222a751b8e4SMatt Ranostay 	},
223a751b8e4SMatt Ranostay };
224a751b8e4SMatt Ranostay 
225b101c93cSMatt Ranostay static const struct iio_chan_spec atlas_rtd_channels[] = {
226b101c93cSMatt Ranostay 	{
227b101c93cSMatt Ranostay 		.type = IIO_TEMP,
228b101c93cSMatt Ranostay 		.address = ATLAS_REG_RTD_DATA,
229b101c93cSMatt Ranostay 		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
230b101c93cSMatt Ranostay 		.scan_index = 0,
231b101c93cSMatt Ranostay 		.scan_type = {
232b101c93cSMatt Ranostay 			.sign = 's',
233b101c93cSMatt Ranostay 			.realbits = 32,
234b101c93cSMatt Ranostay 			.storagebits = 32,
235b101c93cSMatt Ranostay 			.endianness = IIO_BE,
236b101c93cSMatt Ranostay 		},
237b101c93cSMatt Ranostay 	},
238b101c93cSMatt Ranostay 	IIO_CHAN_SOFT_TIMESTAMP(1),
239b101c93cSMatt Ranostay };
240b101c93cSMatt Ranostay 
atlas_check_ph_calibration(struct atlas_data * data)2410d15190fSMatt Ranostay static int atlas_check_ph_calibration(struct atlas_data *data)
2420d15190fSMatt Ranostay {
2430d15190fSMatt Ranostay 	struct device *dev = &data->client->dev;
2440d15190fSMatt Ranostay 	int ret;
2450d15190fSMatt Ranostay 	unsigned int val;
2460d15190fSMatt Ranostay 
2470d15190fSMatt Ranostay 	ret = regmap_read(data->regmap, ATLAS_REG_PH_CALIB_STATUS, &val);
2480d15190fSMatt Ranostay 	if (ret)
2490d15190fSMatt Ranostay 		return ret;
2500d15190fSMatt Ranostay 
2510d15190fSMatt Ranostay 	if (!(val & ATLAS_REG_PH_CALIB_STATUS_MASK)) {
2520d15190fSMatt Ranostay 		dev_warn(dev, "device has not been calibrated\n");
2530d15190fSMatt Ranostay 		return 0;
2540d15190fSMatt Ranostay 	}
2550d15190fSMatt Ranostay 
2560d15190fSMatt Ranostay 	if (!(val & ATLAS_REG_PH_CALIB_STATUS_LOW))
2570d15190fSMatt Ranostay 		dev_warn(dev, "device missing low point calibration\n");
2580d15190fSMatt Ranostay 
2590d15190fSMatt Ranostay 	if (!(val & ATLAS_REG_PH_CALIB_STATUS_MID))
2600d15190fSMatt Ranostay 		dev_warn(dev, "device missing mid point calibration\n");
2610d15190fSMatt Ranostay 
2620d15190fSMatt Ranostay 	if (!(val & ATLAS_REG_PH_CALIB_STATUS_HIGH))
2630d15190fSMatt Ranostay 		dev_warn(dev, "device missing high point calibration\n");
2640d15190fSMatt Ranostay 
2650d15190fSMatt Ranostay 	return 0;
2660d15190fSMatt Ranostay }
2670d15190fSMatt Ranostay 
atlas_check_ec_calibration(struct atlas_data * data)2680d15190fSMatt Ranostay static int atlas_check_ec_calibration(struct atlas_data *data)
2690d15190fSMatt Ranostay {
2700d15190fSMatt Ranostay 	struct device *dev = &data->client->dev;
2710d15190fSMatt Ranostay 	int ret;
2720d15190fSMatt Ranostay 	unsigned int val;
2730d15190fSMatt Ranostay 	__be16	rval;
2740d15190fSMatt Ranostay 
2750d15190fSMatt Ranostay 	ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &rval, 2);
2760d15190fSMatt Ranostay 	if (ret)
2770d15190fSMatt Ranostay 		return ret;
2780d15190fSMatt Ranostay 
2790d15190fSMatt Ranostay 	val = be16_to_cpu(rval);
2800d15190fSMatt Ranostay 	dev_info(dev, "probe set to K = %d.%.2d", val / 100, val % 100);
2810d15190fSMatt Ranostay 
2820d15190fSMatt Ranostay 	ret = regmap_read(data->regmap, ATLAS_REG_EC_CALIB_STATUS, &val);
2830d15190fSMatt Ranostay 	if (ret)
2840d15190fSMatt Ranostay 		return ret;
2850d15190fSMatt Ranostay 
2860d15190fSMatt Ranostay 	if (!(val & ATLAS_REG_EC_CALIB_STATUS_MASK)) {
2870d15190fSMatt Ranostay 		dev_warn(dev, "device has not been calibrated\n");
2880d15190fSMatt Ranostay 		return 0;
2890d15190fSMatt Ranostay 	}
2900d15190fSMatt Ranostay 
2910d15190fSMatt Ranostay 	if (!(val & ATLAS_REG_EC_CALIB_STATUS_DRY))
2920d15190fSMatt Ranostay 		dev_warn(dev, "device missing dry point calibration\n");
2930d15190fSMatt Ranostay 
2940d15190fSMatt Ranostay 	if (val & ATLAS_REG_EC_CALIB_STATUS_SINGLE) {
2950d15190fSMatt Ranostay 		dev_warn(dev, "device using single point calibration\n");
2960d15190fSMatt Ranostay 	} else {
2970d15190fSMatt Ranostay 		if (!(val & ATLAS_REG_EC_CALIB_STATUS_LOW))
2980d15190fSMatt Ranostay 			dev_warn(dev, "device missing low point calibration\n");
2990d15190fSMatt Ranostay 
3000d15190fSMatt Ranostay 		if (!(val & ATLAS_REG_EC_CALIB_STATUS_HIGH))
3010d15190fSMatt Ranostay 			dev_warn(dev, "device missing high point calibration\n");
3020d15190fSMatt Ranostay 	}
3030d15190fSMatt Ranostay 
3040d15190fSMatt Ranostay 	return 0;
3050d15190fSMatt Ranostay }
3060d15190fSMatt Ranostay 
atlas_check_orp_calibration(struct atlas_data * data)3070d15190fSMatt Ranostay static int atlas_check_orp_calibration(struct atlas_data *data)
3080d15190fSMatt Ranostay {
3090d15190fSMatt Ranostay 	struct device *dev = &data->client->dev;
3100d15190fSMatt Ranostay 	int ret;
3110d15190fSMatt Ranostay 	unsigned int val;
3120d15190fSMatt Ranostay 
3130d15190fSMatt Ranostay 	ret = regmap_read(data->regmap, ATLAS_REG_ORP_CALIB_STATUS, &val);
3140d15190fSMatt Ranostay 	if (ret)
3150d15190fSMatt Ranostay 		return ret;
3160d15190fSMatt Ranostay 
3170d15190fSMatt Ranostay 	if (!val)
3180d15190fSMatt Ranostay 		dev_warn(dev, "device has not been calibrated\n");
3190d15190fSMatt Ranostay 
3200d15190fSMatt Ranostay 	return 0;
321a751b8e4SMatt Ranostay }
322a751b8e4SMatt Ranostay 
atlas_check_do_calibration(struct atlas_data * data)323a751b8e4SMatt Ranostay static int atlas_check_do_calibration(struct atlas_data *data)
324a751b8e4SMatt Ranostay {
325a751b8e4SMatt Ranostay 	struct device *dev = &data->client->dev;
326a751b8e4SMatt Ranostay 	int ret;
327a751b8e4SMatt Ranostay 	unsigned int val;
328a751b8e4SMatt Ranostay 
329a751b8e4SMatt Ranostay 	ret = regmap_read(data->regmap, ATLAS_REG_DO_CALIB_STATUS, &val);
330a751b8e4SMatt Ranostay 	if (ret)
331a751b8e4SMatt Ranostay 		return ret;
332a751b8e4SMatt Ranostay 
333a751b8e4SMatt Ranostay 	if (!(val & ATLAS_REG_DO_CALIB_STATUS_MASK)) {
334a751b8e4SMatt Ranostay 		dev_warn(dev, "device has not been calibrated\n");
335a751b8e4SMatt Ranostay 		return 0;
336a751b8e4SMatt Ranostay 	}
337a751b8e4SMatt Ranostay 
338a751b8e4SMatt Ranostay 	if (!(val & ATLAS_REG_DO_CALIB_STATUS_PRESSURE))
339a751b8e4SMatt Ranostay 		dev_warn(dev, "device missing atmospheric pressure calibration\n");
340a751b8e4SMatt Ranostay 
341a751b8e4SMatt Ranostay 	if (!(val & ATLAS_REG_DO_CALIB_STATUS_DO))
342a751b8e4SMatt Ranostay 		dev_warn(dev, "device missing dissolved oxygen calibration\n");
343a751b8e4SMatt Ranostay 
344a751b8e4SMatt Ranostay 	return 0;
345a751b8e4SMatt Ranostay }
3460d15190fSMatt Ranostay 
3470d15190fSMatt Ranostay struct atlas_device {
3480d15190fSMatt Ranostay 	const struct iio_chan_spec *channels;
3490d15190fSMatt Ranostay 	int num_channels;
3500d15190fSMatt Ranostay 	int data_reg;
3510d15190fSMatt Ranostay 
3520d15190fSMatt Ranostay 	int (*calibration)(struct atlas_data *data);
3530d15190fSMatt Ranostay 	int delay;
3540d15190fSMatt Ranostay };
3550d15190fSMatt Ranostay 
3560d15190fSMatt Ranostay static struct atlas_device atlas_devices[] = {
3570d15190fSMatt Ranostay 	[ATLAS_PH_SM] = {
3580d15190fSMatt Ranostay 				.channels = atlas_ph_channels,
3590d15190fSMatt Ranostay 				.num_channels = 3,
3600d15190fSMatt Ranostay 				.data_reg = ATLAS_REG_PH_DATA,
3610d15190fSMatt Ranostay 				.calibration = &atlas_check_ph_calibration,
3620d15190fSMatt Ranostay 				.delay = ATLAS_PH_INT_TIME_IN_MS,
3630d15190fSMatt Ranostay 	},
3640d15190fSMatt Ranostay 	[ATLAS_EC_SM] = {
3650d15190fSMatt Ranostay 				.channels = atlas_ec_channels,
3660d15190fSMatt Ranostay 				.num_channels = 5,
3670d15190fSMatt Ranostay 				.data_reg = ATLAS_REG_EC_DATA,
3680d15190fSMatt Ranostay 				.calibration = &atlas_check_ec_calibration,
3690d15190fSMatt Ranostay 				.delay = ATLAS_EC_INT_TIME_IN_MS,
3700d15190fSMatt Ranostay 	},
3710d15190fSMatt Ranostay 	[ATLAS_ORP_SM] = {
3720d15190fSMatt Ranostay 				.channels = atlas_orp_channels,
3730d15190fSMatt Ranostay 				.num_channels = 2,
3740d15190fSMatt Ranostay 				.data_reg = ATLAS_REG_ORP_DATA,
3750d15190fSMatt Ranostay 				.calibration = &atlas_check_orp_calibration,
3760d15190fSMatt Ranostay 				.delay = ATLAS_ORP_INT_TIME_IN_MS,
3770d15190fSMatt Ranostay 	},
378a751b8e4SMatt Ranostay 	[ATLAS_DO_SM] = {
379a751b8e4SMatt Ranostay 				.channels = atlas_do_channels,
380a751b8e4SMatt Ranostay 				.num_channels = 3,
381a751b8e4SMatt Ranostay 				.data_reg = ATLAS_REG_DO_DATA,
382a751b8e4SMatt Ranostay 				.calibration = &atlas_check_do_calibration,
383a751b8e4SMatt Ranostay 				.delay = ATLAS_DO_INT_TIME_IN_MS,
384a751b8e4SMatt Ranostay 	},
385b101c93cSMatt Ranostay 	[ATLAS_RTD_SM] = {
386b101c93cSMatt Ranostay 				.channels = atlas_rtd_channels,
387b101c93cSMatt Ranostay 				.num_channels = 2,
388b101c93cSMatt Ranostay 				.data_reg = ATLAS_REG_RTD_DATA,
389b101c93cSMatt Ranostay 				.delay = ATLAS_RTD_INT_TIME_IN_MS,
390b101c93cSMatt Ranostay 	},
3910d15190fSMatt Ranostay };
3920d15190fSMatt Ranostay 
atlas_set_powermode(struct atlas_data * data,int on)3930d15190fSMatt Ranostay static int atlas_set_powermode(struct atlas_data *data, int on)
3940d15190fSMatt Ranostay {
3950d15190fSMatt Ranostay 	return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on);
3960d15190fSMatt Ranostay }
3970d15190fSMatt Ranostay 
atlas_set_interrupt(struct atlas_data * data,bool state)3980d15190fSMatt Ranostay static int atlas_set_interrupt(struct atlas_data *data, bool state)
3990d15190fSMatt Ranostay {
400d4578dc0SMatt Ranostay 	if (!data->interrupt_enabled)
401d4578dc0SMatt Ranostay 		return 0;
402d4578dc0SMatt Ranostay 
4030d15190fSMatt Ranostay 	return regmap_update_bits(data->regmap, ATLAS_REG_INT_CONTROL,
4040d15190fSMatt Ranostay 				  ATLAS_REG_INT_CONTROL_EN,
4050d15190fSMatt Ranostay 				  state ? ATLAS_REG_INT_CONTROL_EN : 0);
4060d15190fSMatt Ranostay }
4070d15190fSMatt Ranostay 
atlas_buffer_postenable(struct iio_dev * indio_dev)4080d15190fSMatt Ranostay static int atlas_buffer_postenable(struct iio_dev *indio_dev)
4090d15190fSMatt Ranostay {
4100d15190fSMatt Ranostay 	struct atlas_data *data = iio_priv(indio_dev);
4110d15190fSMatt Ranostay 	int ret;
4120d15190fSMatt Ranostay 
4130e4f336fSJonathan Cameron 	ret = pm_runtime_resume_and_get(&data->client->dev);
4140e4f336fSJonathan Cameron 	if (ret)
4150d15190fSMatt Ranostay 		return ret;
4160d15190fSMatt Ranostay 
4170d15190fSMatt Ranostay 	return atlas_set_interrupt(data, true);
4180d15190fSMatt Ranostay }
4190d15190fSMatt Ranostay 
atlas_buffer_predisable(struct iio_dev * indio_dev)4200d15190fSMatt Ranostay static int atlas_buffer_predisable(struct iio_dev *indio_dev)
4210d15190fSMatt Ranostay {
4220d15190fSMatt Ranostay 	struct atlas_data *data = iio_priv(indio_dev);
4230d15190fSMatt Ranostay 	int ret;
4240d15190fSMatt Ranostay 
4250d15190fSMatt Ranostay 	ret = atlas_set_interrupt(data, false);
4260d15190fSMatt Ranostay 	if (ret)
4270d15190fSMatt Ranostay 		return ret;
4280d15190fSMatt Ranostay 
4290d15190fSMatt Ranostay 	pm_runtime_mark_last_busy(&data->client->dev);
4300d15190fSMatt Ranostay 	ret = pm_runtime_put_autosuspend(&data->client->dev);
4310d15190fSMatt Ranostay 	if (ret)
4320d15190fSMatt Ranostay 		return ret;
4330d15190fSMatt Ranostay 
434f11d59d8SLars-Peter Clausen 	return 0;
4350d15190fSMatt Ranostay }
4360d15190fSMatt Ranostay 
4370d15190fSMatt Ranostay static const struct iio_buffer_setup_ops atlas_buffer_setup_ops = {
4380d15190fSMatt Ranostay 	.postenable = atlas_buffer_postenable,
4390d15190fSMatt Ranostay 	.predisable = atlas_buffer_predisable,
4400d15190fSMatt Ranostay };
4410d15190fSMatt Ranostay 
atlas_work_handler(struct irq_work * work)4420d15190fSMatt Ranostay static void atlas_work_handler(struct irq_work *work)
4430d15190fSMatt Ranostay {
4440d15190fSMatt Ranostay 	struct atlas_data *data = container_of(work, struct atlas_data, work);
4450d15190fSMatt Ranostay 
4460d15190fSMatt Ranostay 	iio_trigger_poll(data->trig);
4470d15190fSMatt Ranostay }
4480d15190fSMatt Ranostay 
atlas_trigger_handler(int irq,void * private)4490d15190fSMatt Ranostay static irqreturn_t atlas_trigger_handler(int irq, void *private)
4500d15190fSMatt Ranostay {
4510d15190fSMatt Ranostay 	struct iio_poll_func *pf = private;
4520d15190fSMatt Ranostay 	struct iio_dev *indio_dev = pf->indio_dev;
4530d15190fSMatt Ranostay 	struct atlas_data *data = iio_priv(indio_dev);
4544766897aSMatt Ranostay 	int channels = atlas_buffer_num_channels(data->chip->channels);
4550d15190fSMatt Ranostay 	int ret;
4560d15190fSMatt Ranostay 
4570d15190fSMatt Ranostay 	ret = regmap_bulk_read(data->regmap, data->chip->data_reg,
4580f92afeeSJonathan Cameron 			      &data->buffer, sizeof(__be32) * channels);
4590d15190fSMatt Ranostay 
4600d15190fSMatt Ranostay 	if (!ret)
4610d15190fSMatt Ranostay 		iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
4620d15190fSMatt Ranostay 				iio_get_time_ns(indio_dev));
4630d15190fSMatt Ranostay 
4640d15190fSMatt Ranostay 	iio_trigger_notify_done(indio_dev->trig);
4650d15190fSMatt Ranostay 
4660d15190fSMatt Ranostay 	return IRQ_HANDLED;
4670d15190fSMatt Ranostay }
4680d15190fSMatt Ranostay 
atlas_interrupt_handler(int irq,void * private)4690d15190fSMatt Ranostay static irqreturn_t atlas_interrupt_handler(int irq, void *private)
4700d15190fSMatt Ranostay {
4710d15190fSMatt Ranostay 	struct iio_dev *indio_dev = private;
4720d15190fSMatt Ranostay 	struct atlas_data *data = iio_priv(indio_dev);
4730d15190fSMatt Ranostay 
4740d15190fSMatt Ranostay 	irq_work_queue(&data->work);
4750d15190fSMatt Ranostay 
4760d15190fSMatt Ranostay 	return IRQ_HANDLED;
4770d15190fSMatt Ranostay }
4780d15190fSMatt Ranostay 
atlas_read_measurement(struct atlas_data * data,int reg,__be32 * val)4790d15190fSMatt Ranostay static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
4800d15190fSMatt Ranostay {
4810d15190fSMatt Ranostay 	struct device *dev = &data->client->dev;
4820d15190fSMatt Ranostay 	int suspended = pm_runtime_suspended(dev);
4830d15190fSMatt Ranostay 	int ret;
4840d15190fSMatt Ranostay 
4850e4f336fSJonathan Cameron 	ret = pm_runtime_resume_and_get(dev);
4860e4f336fSJonathan Cameron 	if (ret)
4870d15190fSMatt Ranostay 		return ret;
4880d15190fSMatt Ranostay 
4890d15190fSMatt Ranostay 	if (suspended)
4900d15190fSMatt Ranostay 		msleep(data->chip->delay);
4910d15190fSMatt Ranostay 
4920f92afeeSJonathan Cameron 	ret = regmap_bulk_read(data->regmap, reg, val, sizeof(*val));
4930d15190fSMatt Ranostay 
4940d15190fSMatt Ranostay 	pm_runtime_mark_last_busy(dev);
4950d15190fSMatt Ranostay 	pm_runtime_put_autosuspend(dev);
4960d15190fSMatt Ranostay 
4970d15190fSMatt Ranostay 	return ret;
4980d15190fSMatt Ranostay }
4990d15190fSMatt Ranostay 
atlas_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)5000d15190fSMatt Ranostay static int atlas_read_raw(struct iio_dev *indio_dev,
5010d15190fSMatt Ranostay 			  struct iio_chan_spec const *chan,
5020d15190fSMatt Ranostay 			  int *val, int *val2, long mask)
5030d15190fSMatt Ranostay {
5040d15190fSMatt Ranostay 	struct atlas_data *data = iio_priv(indio_dev);
5050d15190fSMatt Ranostay 
5060d15190fSMatt Ranostay 	switch (mask) {
507b101c93cSMatt Ranostay 	case IIO_CHAN_INFO_PROCESSED:
5080d15190fSMatt Ranostay 	case IIO_CHAN_INFO_RAW: {
5090d15190fSMatt Ranostay 		int ret;
5100d15190fSMatt Ranostay 		__be32 reg;
5110d15190fSMatt Ranostay 
5120d15190fSMatt Ranostay 		switch (chan->type) {
5130d15190fSMatt Ranostay 		case IIO_TEMP:
5140d15190fSMatt Ranostay 			ret = regmap_bulk_read(data->regmap, chan->address,
5150f92afeeSJonathan Cameron 					       &reg, sizeof(reg));
5160d15190fSMatt Ranostay 			break;
5170d15190fSMatt Ranostay 		case IIO_PH:
5180d15190fSMatt Ranostay 		case IIO_CONCENTRATION:
5190d15190fSMatt Ranostay 		case IIO_ELECTRICALCONDUCTIVITY:
5200d15190fSMatt Ranostay 		case IIO_VOLTAGE:
5210d15190fSMatt Ranostay 			ret = iio_device_claim_direct_mode(indio_dev);
5220d15190fSMatt Ranostay 			if (ret)
5230d15190fSMatt Ranostay 				return ret;
5240d15190fSMatt Ranostay 
5250d15190fSMatt Ranostay 			ret = atlas_read_measurement(data, chan->address, &reg);
5260d15190fSMatt Ranostay 
5270d15190fSMatt Ranostay 			iio_device_release_direct_mode(indio_dev);
5280d15190fSMatt Ranostay 			break;
5290d15190fSMatt Ranostay 		default:
5300d15190fSMatt Ranostay 			ret = -EINVAL;
5310d15190fSMatt Ranostay 		}
5320d15190fSMatt Ranostay 
5330d15190fSMatt Ranostay 		if (!ret) {
5340d15190fSMatt Ranostay 			*val = be32_to_cpu(reg);
5350d15190fSMatt Ranostay 			ret = IIO_VAL_INT;
5360d15190fSMatt Ranostay 		}
5370d15190fSMatt Ranostay 		return ret;
5380d15190fSMatt Ranostay 	}
5390d15190fSMatt Ranostay 	case IIO_CHAN_INFO_SCALE:
5400d15190fSMatt Ranostay 		switch (chan->type) {
5410d15190fSMatt Ranostay 		case IIO_TEMP:
5420d15190fSMatt Ranostay 			*val = 10;
5430d15190fSMatt Ranostay 			return IIO_VAL_INT;
5440d15190fSMatt Ranostay 		case IIO_PH:
5450d15190fSMatt Ranostay 			*val = 1; /* 0.001 */
5460d15190fSMatt Ranostay 			*val2 = 1000;
5470d15190fSMatt Ranostay 			break;
5480d15190fSMatt Ranostay 		case IIO_ELECTRICALCONDUCTIVITY:
5490d15190fSMatt Ranostay 			*val = 1; /* 0.00001 */
5500d15190fSMatt Ranostay 			*val2 = 100000;
5510d15190fSMatt Ranostay 			break;
5520d15190fSMatt Ranostay 		case IIO_CONCENTRATION:
5530d15190fSMatt Ranostay 			*val = 0; /* 0.000000001 */
5540d15190fSMatt Ranostay 			*val2 = 1000;
5550d15190fSMatt Ranostay 			return IIO_VAL_INT_PLUS_NANO;
5560d15190fSMatt Ranostay 		case IIO_VOLTAGE:
5570d15190fSMatt Ranostay 			*val = 1; /* 0.1 */
5580d15190fSMatt Ranostay 			*val2 = 10;
5590d15190fSMatt Ranostay 			break;
5600d15190fSMatt Ranostay 		default:
5610d15190fSMatt Ranostay 			return -EINVAL;
5620d15190fSMatt Ranostay 		}
5630d15190fSMatt Ranostay 		return IIO_VAL_FRACTIONAL;
5640d15190fSMatt Ranostay 	}
5650d15190fSMatt Ranostay 
5660d15190fSMatt Ranostay 	return -EINVAL;
5670d15190fSMatt Ranostay }
5680d15190fSMatt Ranostay 
atlas_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)5690d15190fSMatt Ranostay static int atlas_write_raw(struct iio_dev *indio_dev,
5700d15190fSMatt Ranostay 			   struct iio_chan_spec const *chan,
5710d15190fSMatt Ranostay 			   int val, int val2, long mask)
5720d15190fSMatt Ranostay {
5730d15190fSMatt Ranostay 	struct atlas_data *data = iio_priv(indio_dev);
5740d15190fSMatt Ranostay 	__be32 reg = cpu_to_be32(val / 10);
5750d15190fSMatt Ranostay 
5760d15190fSMatt Ranostay 	if (val2 != 0 || val < 0 || val > 20000)
5770d15190fSMatt Ranostay 		return -EINVAL;
5780d15190fSMatt Ranostay 
5790d15190fSMatt Ranostay 	if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_TEMP)
5800d15190fSMatt Ranostay 		return -EINVAL;
5810d15190fSMatt Ranostay 
5820d15190fSMatt Ranostay 	return regmap_bulk_write(data->regmap, chan->address,
5830d15190fSMatt Ranostay 				 &reg, sizeof(reg));
5840d15190fSMatt Ranostay }
5850d15190fSMatt Ranostay 
5860d15190fSMatt Ranostay static const struct iio_info atlas_info = {
5870d15190fSMatt Ranostay 	.read_raw = atlas_read_raw,
5880d15190fSMatt Ranostay 	.write_raw = atlas_write_raw,
5890d15190fSMatt Ranostay };
5900d15190fSMatt Ranostay 
5910d15190fSMatt Ranostay static const struct i2c_device_id atlas_id[] = {
5920d15190fSMatt Ranostay 	{ "atlas-ph-sm", ATLAS_PH_SM },
5930d15190fSMatt Ranostay 	{ "atlas-ec-sm", ATLAS_EC_SM },
5940d15190fSMatt Ranostay 	{ "atlas-orp-sm", ATLAS_ORP_SM },
595a751b8e4SMatt Ranostay 	{ "atlas-do-sm", ATLAS_DO_SM },
596b101c93cSMatt Ranostay 	{ "atlas-rtd-sm", ATLAS_RTD_SM },
5970d15190fSMatt Ranostay 	{}
5980d15190fSMatt Ranostay };
5990d15190fSMatt Ranostay MODULE_DEVICE_TABLE(i2c, atlas_id);
6000d15190fSMatt Ranostay 
6010d15190fSMatt Ranostay static const struct of_device_id atlas_dt_ids[] = {
6020d15190fSMatt Ranostay 	{ .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
6030d15190fSMatt Ranostay 	{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
6040d15190fSMatt Ranostay 	{ .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, },
605a751b8e4SMatt Ranostay 	{ .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, },
606b101c93cSMatt Ranostay 	{ .compatible = "atlas,rtd-sm", .data = (void *)ATLAS_RTD_SM, },
6070d15190fSMatt Ranostay 	{ }
6080d15190fSMatt Ranostay };
6090d15190fSMatt Ranostay MODULE_DEVICE_TABLE(of, atlas_dt_ids);
6100d15190fSMatt Ranostay 
atlas_probe(struct i2c_client * client)61150c35924SUwe Kleine-König static int atlas_probe(struct i2c_client *client)
6120d15190fSMatt Ranostay {
61350c35924SUwe Kleine-König 	const struct i2c_device_id *id = i2c_client_get_device_id(client);
6140d15190fSMatt Ranostay 	struct atlas_data *data;
6150d15190fSMatt Ranostay 	struct atlas_device *chip;
6160d15190fSMatt Ranostay 	struct iio_trigger *trig;
6170d15190fSMatt Ranostay 	struct iio_dev *indio_dev;
6180d15190fSMatt Ranostay 	int ret;
6190d15190fSMatt Ranostay 
6200d15190fSMatt Ranostay 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
6210d15190fSMatt Ranostay 	if (!indio_dev)
6220d15190fSMatt Ranostay 		return -ENOMEM;
6230d15190fSMatt Ranostay 
624a867e898SJonathan Cameron 	if (!dev_fwnode(&client->dev))
6250d15190fSMatt Ranostay 		chip = &atlas_devices[id->driver_data];
6260d15190fSMatt Ranostay 	else
627a867e898SJonathan Cameron 		chip = &atlas_devices[(unsigned long)device_get_match_data(&client->dev)];
6280d15190fSMatt Ranostay 
6290d15190fSMatt Ranostay 	indio_dev->info = &atlas_info;
6300d15190fSMatt Ranostay 	indio_dev->name = ATLAS_DRV_NAME;
6310d15190fSMatt Ranostay 	indio_dev->channels = chip->channels;
6320d15190fSMatt Ranostay 	indio_dev->num_channels = chip->num_channels;
6330d15190fSMatt Ranostay 	indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;
6340d15190fSMatt Ranostay 
6350d15190fSMatt Ranostay 	trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
63615ea2878SJonathan Cameron 				      indio_dev->name, iio_device_id(indio_dev));
6370d15190fSMatt Ranostay 
6380d15190fSMatt Ranostay 	if (!trig)
6390d15190fSMatt Ranostay 		return -ENOMEM;
6400d15190fSMatt Ranostay 
6410d15190fSMatt Ranostay 	data = iio_priv(indio_dev);
6420d15190fSMatt Ranostay 	data->client = client;
6430d15190fSMatt Ranostay 	data->trig = trig;
6440d15190fSMatt Ranostay 	data->chip = chip;
6450d15190fSMatt Ranostay 	iio_trigger_set_drvdata(trig, indio_dev);
6460d15190fSMatt Ranostay 
6470d15190fSMatt Ranostay 	i2c_set_clientdata(client, indio_dev);
6480d15190fSMatt Ranostay 
6490d15190fSMatt Ranostay 	data->regmap = devm_regmap_init_i2c(client, &atlas_regmap_config);
6500d15190fSMatt Ranostay 	if (IS_ERR(data->regmap)) {
6510d15190fSMatt Ranostay 		dev_err(&client->dev, "regmap initialization failed\n");
6520d15190fSMatt Ranostay 		return PTR_ERR(data->regmap);
6530d15190fSMatt Ranostay 	}
6540d15190fSMatt Ranostay 
6550d15190fSMatt Ranostay 	ret = pm_runtime_set_active(&client->dev);
6560d15190fSMatt Ranostay 	if (ret)
6570d15190fSMatt Ranostay 		return ret;
6580d15190fSMatt Ranostay 
6590d15190fSMatt Ranostay 	ret = chip->calibration(data);
6600d15190fSMatt Ranostay 	if (ret)
6610d15190fSMatt Ranostay 		return ret;
6620d15190fSMatt Ranostay 
6630d15190fSMatt Ranostay 	ret = iio_trigger_register(trig);
6640d15190fSMatt Ranostay 	if (ret) {
6650d15190fSMatt Ranostay 		dev_err(&client->dev, "failed to register trigger\n");
6660d15190fSMatt Ranostay 		return ret;
6670d15190fSMatt Ranostay 	}
6680d15190fSMatt Ranostay 
6690d15190fSMatt Ranostay 	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
6700d15190fSMatt Ranostay 		&atlas_trigger_handler, &atlas_buffer_setup_ops);
6710d15190fSMatt Ranostay 	if (ret) {
6720d15190fSMatt Ranostay 		dev_err(&client->dev, "cannot setup iio trigger\n");
6730d15190fSMatt Ranostay 		goto unregister_trigger;
6740d15190fSMatt Ranostay 	}
6750d15190fSMatt Ranostay 
6760d15190fSMatt Ranostay 	init_irq_work(&data->work, atlas_work_handler);
6770d15190fSMatt Ranostay 
678d4578dc0SMatt Ranostay 	if (client->irq > 0) {
6790d15190fSMatt Ranostay 		/* interrupt pin toggles on new conversion */
6800d15190fSMatt Ranostay 		ret = devm_request_threaded_irq(&client->dev, client->irq,
6810d15190fSMatt Ranostay 				NULL, atlas_interrupt_handler,
6820d15190fSMatt Ranostay 				IRQF_TRIGGER_RISING |
6830d15190fSMatt Ranostay 				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
6840d15190fSMatt Ranostay 				"atlas_irq",
6850d15190fSMatt Ranostay 				indio_dev);
686d4578dc0SMatt Ranostay 
687d4578dc0SMatt Ranostay 		if (ret)
688d4578dc0SMatt Ranostay 			dev_warn(&client->dev,
689d4578dc0SMatt Ranostay 				"request irq (%d) failed\n", client->irq);
690d4578dc0SMatt Ranostay 		else
691d4578dc0SMatt Ranostay 			data->interrupt_enabled = 1;
6920d15190fSMatt Ranostay 	}
6930d15190fSMatt Ranostay 
6940d15190fSMatt Ranostay 	ret = atlas_set_powermode(data, 1);
6950d15190fSMatt Ranostay 	if (ret) {
6960d15190fSMatt Ranostay 		dev_err(&client->dev, "cannot power device on");
6970d15190fSMatt Ranostay 		goto unregister_buffer;
6980d15190fSMatt Ranostay 	}
6990d15190fSMatt Ranostay 
7000d15190fSMatt Ranostay 	pm_runtime_enable(&client->dev);
7010d15190fSMatt Ranostay 	pm_runtime_set_autosuspend_delay(&client->dev, 2500);
7020d15190fSMatt Ranostay 	pm_runtime_use_autosuspend(&client->dev);
7030d15190fSMatt Ranostay 
7040d15190fSMatt Ranostay 	ret = iio_device_register(indio_dev);
7050d15190fSMatt Ranostay 	if (ret) {
7060d15190fSMatt Ranostay 		dev_err(&client->dev, "unable to register device\n");
7070d15190fSMatt Ranostay 		goto unregister_pm;
7080d15190fSMatt Ranostay 	}
7090d15190fSMatt Ranostay 
7100d15190fSMatt Ranostay 	return 0;
7110d15190fSMatt Ranostay 
7120d15190fSMatt Ranostay unregister_pm:
7130d15190fSMatt Ranostay 	pm_runtime_disable(&client->dev);
7140d15190fSMatt Ranostay 	atlas_set_powermode(data, 0);
7150d15190fSMatt Ranostay 
7160d15190fSMatt Ranostay unregister_buffer:
7170d15190fSMatt Ranostay 	iio_triggered_buffer_cleanup(indio_dev);
7180d15190fSMatt Ranostay 
7190d15190fSMatt Ranostay unregister_trigger:
7200d15190fSMatt Ranostay 	iio_trigger_unregister(data->trig);
7210d15190fSMatt Ranostay 
7220d15190fSMatt Ranostay 	return ret;
7230d15190fSMatt Ranostay }
7240d15190fSMatt Ranostay 
atlas_remove(struct i2c_client * client)725ed5c2f5fSUwe Kleine-König static void atlas_remove(struct i2c_client *client)
7260d15190fSMatt Ranostay {
7270d15190fSMatt Ranostay 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
7280d15190fSMatt Ranostay 	struct atlas_data *data = iio_priv(indio_dev);
729a7620924SUwe Kleine-König 	int ret;
7300d15190fSMatt Ranostay 
7310d15190fSMatt Ranostay 	iio_device_unregister(indio_dev);
7320d15190fSMatt Ranostay 	iio_triggered_buffer_cleanup(indio_dev);
7330d15190fSMatt Ranostay 	iio_trigger_unregister(data->trig);
7340d15190fSMatt Ranostay 
7350d15190fSMatt Ranostay 	pm_runtime_disable(&client->dev);
7360d15190fSMatt Ranostay 	pm_runtime_set_suspended(&client->dev);
7370d15190fSMatt Ranostay 
738a7620924SUwe Kleine-König 	ret = atlas_set_powermode(data, 0);
739a7620924SUwe Kleine-König 	if (ret)
740a7620924SUwe Kleine-König 		dev_err(&client->dev, "Failed to power down device (%pe)\n",
741a7620924SUwe Kleine-König 			ERR_PTR(ret));
7420d15190fSMatt Ranostay }
7430d15190fSMatt Ranostay 
atlas_runtime_suspend(struct device * dev)7440d15190fSMatt Ranostay static int atlas_runtime_suspend(struct device *dev)
7450d15190fSMatt Ranostay {
7460d15190fSMatt Ranostay 	struct atlas_data *data =
7470d15190fSMatt Ranostay 		     iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
7480d15190fSMatt Ranostay 
7490d15190fSMatt Ranostay 	return atlas_set_powermode(data, 0);
7500d15190fSMatt Ranostay }
7510d15190fSMatt Ranostay 
atlas_runtime_resume(struct device * dev)7520d15190fSMatt Ranostay static int atlas_runtime_resume(struct device *dev)
7530d15190fSMatt Ranostay {
7540d15190fSMatt Ranostay 	struct atlas_data *data =
7550d15190fSMatt Ranostay 		     iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
7560d15190fSMatt Ranostay 
7570d15190fSMatt Ranostay 	return atlas_set_powermode(data, 1);
7580d15190fSMatt Ranostay }
7590d15190fSMatt Ranostay 
7600d15190fSMatt Ranostay static const struct dev_pm_ops atlas_pm_ops = {
76105a9ddc8SJonathan Cameron 	RUNTIME_PM_OPS(atlas_runtime_suspend, atlas_runtime_resume, NULL)
7620d15190fSMatt Ranostay };
7630d15190fSMatt Ranostay 
7640d15190fSMatt Ranostay static struct i2c_driver atlas_driver = {
7650d15190fSMatt Ranostay 	.driver = {
7660d15190fSMatt Ranostay 		.name	= ATLAS_DRV_NAME,
767a867e898SJonathan Cameron 		.of_match_table	= atlas_dt_ids,
76805a9ddc8SJonathan Cameron 		.pm	= pm_ptr(&atlas_pm_ops),
7690d15190fSMatt Ranostay 	},
770*7cf15f42SUwe Kleine-König 	.probe		= atlas_probe,
7710d15190fSMatt Ranostay 	.remove		= atlas_remove,
7720d15190fSMatt Ranostay 	.id_table	= atlas_id,
7730d15190fSMatt Ranostay };
7740d15190fSMatt Ranostay module_i2c_driver(atlas_driver);
7750d15190fSMatt Ranostay 
7760d15190fSMatt Ranostay MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
7770d15190fSMatt Ranostay MODULE_DESCRIPTION("Atlas Scientific SM sensors");
7780d15190fSMatt Ranostay MODULE_LICENSE("GPL");
779