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 ®, 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, ®);
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 ®, 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