1d6ad8058SMatt Ranostay // SPDX-License-Identifier: GPL-2.0+ 227dec00eSMatt Ranostay /* 30d15190fSMatt Ranostay * atlas-sensor.c - Support for Atlas Scientific OEM SM sensors 427dec00eSMatt Ranostay * 50d15190fSMatt Ranostay * Copyright (C) 2015-2019 Konsulko Group 6d6ad8058SMatt Ranostay * Author: Matt Ranostay <matt.ranostay@konsulko.com> 727dec00eSMatt Ranostay */ 827dec00eSMatt Ranostay 927dec00eSMatt Ranostay #include <linux/module.h> 1027dec00eSMatt Ranostay #include <linux/init.h> 1127dec00eSMatt Ranostay #include <linux/interrupt.h> 1227dec00eSMatt Ranostay #include <linux/delay.h> 1327dec00eSMatt Ranostay #include <linux/mutex.h> 1427dec00eSMatt Ranostay #include <linux/err.h> 1527dec00eSMatt Ranostay #include <linux/irq.h> 1627dec00eSMatt Ranostay #include <linux/irq_work.h> 1727dec00eSMatt Ranostay #include <linux/i2c.h> 187103b99bSMatt Ranostay #include <linux/of_device.h> 1927dec00eSMatt Ranostay #include <linux/regmap.h> 2027dec00eSMatt Ranostay #include <linux/iio/iio.h> 2127dec00eSMatt Ranostay #include <linux/iio/buffer.h> 2227dec00eSMatt Ranostay #include <linux/iio/trigger.h> 2327dec00eSMatt Ranostay #include <linux/iio/trigger_consumer.h> 2427dec00eSMatt Ranostay #include <linux/iio/triggered_buffer.h> 2527dec00eSMatt Ranostay #include <linux/pm_runtime.h> 2627dec00eSMatt Ranostay 270d15190fSMatt Ranostay #define ATLAS_REGMAP_NAME "atlas_regmap" 280d15190fSMatt Ranostay #define ATLAS_DRV_NAME "atlas" 2927dec00eSMatt Ranostay 3027dec00eSMatt Ranostay #define ATLAS_REG_DEV_TYPE 0x00 3127dec00eSMatt Ranostay #define ATLAS_REG_DEV_VERSION 0x01 3227dec00eSMatt Ranostay 3327dec00eSMatt Ranostay #define ATLAS_REG_INT_CONTROL 0x04 3427dec00eSMatt Ranostay #define ATLAS_REG_INT_CONTROL_EN BIT(3) 3527dec00eSMatt Ranostay 3627dec00eSMatt Ranostay #define ATLAS_REG_PWR_CONTROL 0x06 3727dec00eSMatt Ranostay 387103b99bSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS 0x0d 397103b99bSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_MASK 0x07 407103b99bSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_LOW BIT(0) 417103b99bSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_MID BIT(1) 427103b99bSMatt Ranostay #define ATLAS_REG_PH_CALIB_STATUS_HIGH BIT(2) 4327dec00eSMatt Ranostay 44e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS 0x0f 45e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_MASK 0x0f 46e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_DRY BIT(0) 47e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_SINGLE BIT(1) 48e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_LOW BIT(2) 49e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_CALIB_STATUS_HIGH BIT(3) 50e8dd92bfSMatt Ranostay 517103b99bSMatt Ranostay #define ATLAS_REG_PH_TEMP_DATA 0x0e 5227dec00eSMatt Ranostay #define ATLAS_REG_PH_DATA 0x16 5327dec00eSMatt Ranostay 54e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_PROBE 0x08 55e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_TEMP_DATA 0x10 56e8dd92bfSMatt Ranostay #define ATLAS_REG_EC_DATA 0x18 57e8dd92bfSMatt Ranostay #define ATLAS_REG_TDS_DATA 0x1c 58e8dd92bfSMatt Ranostay #define ATLAS_REG_PSS_DATA 0x20 59e8dd92bfSMatt Ranostay 60ce08cc98SMatt Ranostay #define ATLAS_REG_ORP_CALIB_STATUS 0x0d 61ce08cc98SMatt Ranostay #define ATLAS_REG_ORP_DATA 0x0e 62ce08cc98SMatt Ranostay 6302112260SMatt Ranostay #define ATLAS_PH_INT_TIME_IN_MS 450 6402112260SMatt Ranostay #define ATLAS_EC_INT_TIME_IN_MS 650 6502112260SMatt Ranostay #define ATLAS_ORP_INT_TIME_IN_MS 450 6627dec00eSMatt Ranostay 677103b99bSMatt Ranostay enum { 687103b99bSMatt Ranostay ATLAS_PH_SM, 69e8dd92bfSMatt Ranostay ATLAS_EC_SM, 70ce08cc98SMatt Ranostay ATLAS_ORP_SM, 717103b99bSMatt Ranostay }; 727103b99bSMatt Ranostay 7327dec00eSMatt Ranostay struct atlas_data { 7427dec00eSMatt Ranostay struct i2c_client *client; 7527dec00eSMatt Ranostay struct iio_trigger *trig; 767103b99bSMatt Ranostay struct atlas_device *chip; 7727dec00eSMatt Ranostay struct regmap *regmap; 7827dec00eSMatt Ranostay struct irq_work work; 7927dec00eSMatt Ranostay 80e8dd92bfSMatt Ranostay __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ 8127dec00eSMatt Ranostay }; 8227dec00eSMatt Ranostay 8327dec00eSMatt Ranostay static const struct regmap_config atlas_regmap_config = { 8427dec00eSMatt Ranostay .name = ATLAS_REGMAP_NAME, 8527dec00eSMatt Ranostay .reg_bits = 8, 8627dec00eSMatt Ranostay .val_bits = 8, 8727dec00eSMatt Ranostay }; 8827dec00eSMatt Ranostay 89*4766897aSMatt Ranostay static int atlas_buffer_num_channels(const struct iio_chan_spec *spec) 90*4766897aSMatt Ranostay { 91*4766897aSMatt Ranostay int idx = 0; 92*4766897aSMatt Ranostay 93*4766897aSMatt Ranostay for (; spec->type != IIO_TIMESTAMP; spec++) 94*4766897aSMatt Ranostay idx++; 95*4766897aSMatt Ranostay 96*4766897aSMatt Ranostay return idx; 97*4766897aSMatt Ranostay }; 98*4766897aSMatt Ranostay 997103b99bSMatt Ranostay static const struct iio_chan_spec atlas_ph_channels[] = { 10027dec00eSMatt Ranostay { 10127dec00eSMatt Ranostay .type = IIO_PH, 1027103b99bSMatt Ranostay .address = ATLAS_REG_PH_DATA, 10327dec00eSMatt Ranostay .info_mask_separate = 10427dec00eSMatt Ranostay BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 10527dec00eSMatt Ranostay .scan_index = 0, 10627dec00eSMatt Ranostay .scan_type = { 10727dec00eSMatt Ranostay .sign = 'u', 10827dec00eSMatt Ranostay .realbits = 32, 10927dec00eSMatt Ranostay .storagebits = 32, 11027dec00eSMatt Ranostay .endianness = IIO_BE, 11127dec00eSMatt Ranostay }, 11227dec00eSMatt Ranostay }, 11327dec00eSMatt Ranostay IIO_CHAN_SOFT_TIMESTAMP(1), 11427dec00eSMatt Ranostay { 11527dec00eSMatt Ranostay .type = IIO_TEMP, 1167103b99bSMatt Ranostay .address = ATLAS_REG_PH_TEMP_DATA, 11727dec00eSMatt Ranostay .info_mask_separate = 11827dec00eSMatt Ranostay BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 11927dec00eSMatt Ranostay .output = 1, 12027dec00eSMatt Ranostay .scan_index = -1 12127dec00eSMatt Ranostay }, 12227dec00eSMatt Ranostay }; 12327dec00eSMatt Ranostay 124e8dd92bfSMatt Ranostay #define ATLAS_EC_CHANNEL(_idx, _addr) \ 125e8dd92bfSMatt Ranostay {\ 126e8dd92bfSMatt Ranostay .type = IIO_CONCENTRATION, \ 127e8dd92bfSMatt Ranostay .indexed = 1, \ 128e8dd92bfSMatt Ranostay .channel = _idx, \ 129e8dd92bfSMatt Ranostay .address = _addr, \ 130e8dd92bfSMatt Ranostay .info_mask_separate = \ 131e8dd92bfSMatt Ranostay BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \ 132e8dd92bfSMatt Ranostay .scan_index = _idx + 1, \ 133e8dd92bfSMatt Ranostay .scan_type = { \ 134e8dd92bfSMatt Ranostay .sign = 'u', \ 135e8dd92bfSMatt Ranostay .realbits = 32, \ 136e8dd92bfSMatt Ranostay .storagebits = 32, \ 137e8dd92bfSMatt Ranostay .endianness = IIO_BE, \ 138e8dd92bfSMatt Ranostay }, \ 139e8dd92bfSMatt Ranostay } 140e8dd92bfSMatt Ranostay 141e8dd92bfSMatt Ranostay static const struct iio_chan_spec atlas_ec_channels[] = { 142e8dd92bfSMatt Ranostay { 143e8dd92bfSMatt Ranostay .type = IIO_ELECTRICALCONDUCTIVITY, 144e8dd92bfSMatt Ranostay .address = ATLAS_REG_EC_DATA, 145e8dd92bfSMatt Ranostay .info_mask_separate = 146e8dd92bfSMatt Ranostay BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 147e8dd92bfSMatt Ranostay .scan_index = 0, 148e8dd92bfSMatt Ranostay .scan_type = { 149e8dd92bfSMatt Ranostay .sign = 'u', 150e8dd92bfSMatt Ranostay .realbits = 32, 151e8dd92bfSMatt Ranostay .storagebits = 32, 152e8dd92bfSMatt Ranostay .endianness = IIO_BE, 153e8dd92bfSMatt Ranostay }, 154e8dd92bfSMatt Ranostay }, 155e8dd92bfSMatt Ranostay ATLAS_EC_CHANNEL(0, ATLAS_REG_TDS_DATA), 156e8dd92bfSMatt Ranostay ATLAS_EC_CHANNEL(1, ATLAS_REG_PSS_DATA), 157e8dd92bfSMatt Ranostay IIO_CHAN_SOFT_TIMESTAMP(3), 158e8dd92bfSMatt Ranostay { 159e8dd92bfSMatt Ranostay .type = IIO_TEMP, 160e8dd92bfSMatt Ranostay .address = ATLAS_REG_EC_TEMP_DATA, 161e8dd92bfSMatt Ranostay .info_mask_separate = 162e8dd92bfSMatt Ranostay BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 163e8dd92bfSMatt Ranostay .output = 1, 164e8dd92bfSMatt Ranostay .scan_index = -1 165e8dd92bfSMatt Ranostay }, 166e8dd92bfSMatt Ranostay }; 167e8dd92bfSMatt Ranostay 168ce08cc98SMatt Ranostay static const struct iio_chan_spec atlas_orp_channels[] = { 169ce08cc98SMatt Ranostay { 170ce08cc98SMatt Ranostay .type = IIO_VOLTAGE, 171ce08cc98SMatt Ranostay .address = ATLAS_REG_ORP_DATA, 172ce08cc98SMatt Ranostay .info_mask_separate = 173ce08cc98SMatt Ranostay BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 174ce08cc98SMatt Ranostay .scan_index = 0, 175ce08cc98SMatt Ranostay .scan_type = { 176ce08cc98SMatt Ranostay .sign = 's', 177ce08cc98SMatt Ranostay .realbits = 32, 178ce08cc98SMatt Ranostay .storagebits = 32, 179ce08cc98SMatt Ranostay .endianness = IIO_BE, 180ce08cc98SMatt Ranostay }, 181ce08cc98SMatt Ranostay }, 182ce08cc98SMatt Ranostay IIO_CHAN_SOFT_TIMESTAMP(1), 183ce08cc98SMatt Ranostay }; 184ce08cc98SMatt Ranostay 1857103b99bSMatt Ranostay static int atlas_check_ph_calibration(struct atlas_data *data) 1867103b99bSMatt Ranostay { 1877103b99bSMatt Ranostay struct device *dev = &data->client->dev; 1887103b99bSMatt Ranostay int ret; 1897103b99bSMatt Ranostay unsigned int val; 1907103b99bSMatt Ranostay 1917103b99bSMatt Ranostay ret = regmap_read(data->regmap, ATLAS_REG_PH_CALIB_STATUS, &val); 1927103b99bSMatt Ranostay if (ret) 1937103b99bSMatt Ranostay return ret; 1947103b99bSMatt Ranostay 1957103b99bSMatt Ranostay if (!(val & ATLAS_REG_PH_CALIB_STATUS_MASK)) { 1967103b99bSMatt Ranostay dev_warn(dev, "device has not been calibrated\n"); 1977103b99bSMatt Ranostay return 0; 1987103b99bSMatt Ranostay } 1997103b99bSMatt Ranostay 2007103b99bSMatt Ranostay if (!(val & ATLAS_REG_PH_CALIB_STATUS_LOW)) 2017103b99bSMatt Ranostay dev_warn(dev, "device missing low point calibration\n"); 2027103b99bSMatt Ranostay 2037103b99bSMatt Ranostay if (!(val & ATLAS_REG_PH_CALIB_STATUS_MID)) 2047103b99bSMatt Ranostay dev_warn(dev, "device missing mid point calibration\n"); 2057103b99bSMatt Ranostay 2067103b99bSMatt Ranostay if (!(val & ATLAS_REG_PH_CALIB_STATUS_HIGH)) 2077103b99bSMatt Ranostay dev_warn(dev, "device missing high point calibration\n"); 2087103b99bSMatt Ranostay 2097103b99bSMatt Ranostay return 0; 2107103b99bSMatt Ranostay } 2117103b99bSMatt Ranostay 212e8dd92bfSMatt Ranostay static int atlas_check_ec_calibration(struct atlas_data *data) 213e8dd92bfSMatt Ranostay { 214e8dd92bfSMatt Ranostay struct device *dev = &data->client->dev; 215e8dd92bfSMatt Ranostay int ret; 216e8dd92bfSMatt Ranostay unsigned int val; 217d1fe85ecSSandhya Bankar __be16 rval; 218e8dd92bfSMatt Ranostay 219d1fe85ecSSandhya Bankar ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &rval, 2); 220e8dd92bfSMatt Ranostay if (ret) 221e8dd92bfSMatt Ranostay return ret; 222e8dd92bfSMatt Ranostay 223d1fe85ecSSandhya Bankar val = be16_to_cpu(rval); 224d1fe85ecSSandhya Bankar dev_info(dev, "probe set to K = %d.%.2d", val / 100, val % 100); 225e8dd92bfSMatt Ranostay 226e8dd92bfSMatt Ranostay ret = regmap_read(data->regmap, ATLAS_REG_EC_CALIB_STATUS, &val); 227e8dd92bfSMatt Ranostay if (ret) 228e8dd92bfSMatt Ranostay return ret; 229e8dd92bfSMatt Ranostay 230e8dd92bfSMatt Ranostay if (!(val & ATLAS_REG_EC_CALIB_STATUS_MASK)) { 231e8dd92bfSMatt Ranostay dev_warn(dev, "device has not been calibrated\n"); 232e8dd92bfSMatt Ranostay return 0; 233e8dd92bfSMatt Ranostay } 234e8dd92bfSMatt Ranostay 235e8dd92bfSMatt Ranostay if (!(val & ATLAS_REG_EC_CALIB_STATUS_DRY)) 236e8dd92bfSMatt Ranostay dev_warn(dev, "device missing dry point calibration\n"); 237e8dd92bfSMatt Ranostay 238e8dd92bfSMatt Ranostay if (val & ATLAS_REG_EC_CALIB_STATUS_SINGLE) { 239e8dd92bfSMatt Ranostay dev_warn(dev, "device using single point calibration\n"); 240e8dd92bfSMatt Ranostay } else { 241e8dd92bfSMatt Ranostay if (!(val & ATLAS_REG_EC_CALIB_STATUS_LOW)) 242e8dd92bfSMatt Ranostay dev_warn(dev, "device missing low point calibration\n"); 243e8dd92bfSMatt Ranostay 244e8dd92bfSMatt Ranostay if (!(val & ATLAS_REG_EC_CALIB_STATUS_HIGH)) 245e8dd92bfSMatt Ranostay dev_warn(dev, "device missing high point calibration\n"); 246e8dd92bfSMatt Ranostay } 247e8dd92bfSMatt Ranostay 248e8dd92bfSMatt Ranostay return 0; 249e8dd92bfSMatt Ranostay } 250e8dd92bfSMatt Ranostay 251ce08cc98SMatt Ranostay static int atlas_check_orp_calibration(struct atlas_data *data) 252ce08cc98SMatt Ranostay { 253ce08cc98SMatt Ranostay struct device *dev = &data->client->dev; 254ce08cc98SMatt Ranostay int ret; 255ce08cc98SMatt Ranostay unsigned int val; 256ce08cc98SMatt Ranostay 257ce08cc98SMatt Ranostay ret = regmap_read(data->regmap, ATLAS_REG_ORP_CALIB_STATUS, &val); 258ce08cc98SMatt Ranostay if (ret) 259ce08cc98SMatt Ranostay return ret; 260ce08cc98SMatt Ranostay 261ce08cc98SMatt Ranostay if (!val) 262ce08cc98SMatt Ranostay dev_warn(dev, "device has not been calibrated\n"); 263ce08cc98SMatt Ranostay 264ce08cc98SMatt Ranostay return 0; 265ce08cc98SMatt Ranostay }; 266ce08cc98SMatt Ranostay 2677103b99bSMatt Ranostay struct atlas_device { 2687103b99bSMatt Ranostay const struct iio_chan_spec *channels; 2697103b99bSMatt Ranostay int num_channels; 2707103b99bSMatt Ranostay int data_reg; 2717103b99bSMatt Ranostay 2727103b99bSMatt Ranostay int (*calibration)(struct atlas_data *data); 2737103b99bSMatt Ranostay int delay; 2747103b99bSMatt Ranostay }; 2757103b99bSMatt Ranostay 2767103b99bSMatt Ranostay static struct atlas_device atlas_devices[] = { 2777103b99bSMatt Ranostay [ATLAS_PH_SM] = { 2787103b99bSMatt Ranostay .channels = atlas_ph_channels, 2797103b99bSMatt Ranostay .num_channels = 3, 2807103b99bSMatt Ranostay .data_reg = ATLAS_REG_PH_DATA, 2817103b99bSMatt Ranostay .calibration = &atlas_check_ph_calibration, 28202112260SMatt Ranostay .delay = ATLAS_PH_INT_TIME_IN_MS, 2837103b99bSMatt Ranostay }, 284e8dd92bfSMatt Ranostay [ATLAS_EC_SM] = { 285e8dd92bfSMatt Ranostay .channels = atlas_ec_channels, 286e8dd92bfSMatt Ranostay .num_channels = 5, 287e8dd92bfSMatt Ranostay .data_reg = ATLAS_REG_EC_DATA, 288e8dd92bfSMatt Ranostay .calibration = &atlas_check_ec_calibration, 28902112260SMatt Ranostay .delay = ATLAS_EC_INT_TIME_IN_MS, 290e8dd92bfSMatt Ranostay }, 291ce08cc98SMatt Ranostay [ATLAS_ORP_SM] = { 292ce08cc98SMatt Ranostay .channels = atlas_orp_channels, 293ce08cc98SMatt Ranostay .num_channels = 2, 294ce08cc98SMatt Ranostay .data_reg = ATLAS_REG_ORP_DATA, 295ce08cc98SMatt Ranostay .calibration = &atlas_check_orp_calibration, 29602112260SMatt Ranostay .delay = ATLAS_ORP_INT_TIME_IN_MS, 297ce08cc98SMatt Ranostay }, 2987103b99bSMatt Ranostay }; 2997103b99bSMatt Ranostay 30027dec00eSMatt Ranostay static int atlas_set_powermode(struct atlas_data *data, int on) 30127dec00eSMatt Ranostay { 30227dec00eSMatt Ranostay return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on); 30327dec00eSMatt Ranostay } 30427dec00eSMatt Ranostay 30527dec00eSMatt Ranostay static int atlas_set_interrupt(struct atlas_data *data, bool state) 30627dec00eSMatt Ranostay { 30727dec00eSMatt Ranostay return regmap_update_bits(data->regmap, ATLAS_REG_INT_CONTROL, 30827dec00eSMatt Ranostay ATLAS_REG_INT_CONTROL_EN, 30927dec00eSMatt Ranostay state ? ATLAS_REG_INT_CONTROL_EN : 0); 31027dec00eSMatt Ranostay } 31127dec00eSMatt Ranostay 31227dec00eSMatt Ranostay static int atlas_buffer_postenable(struct iio_dev *indio_dev) 31327dec00eSMatt Ranostay { 31427dec00eSMatt Ranostay struct atlas_data *data = iio_priv(indio_dev); 31527dec00eSMatt Ranostay int ret; 31627dec00eSMatt Ranostay 31727dec00eSMatt Ranostay ret = iio_triggered_buffer_postenable(indio_dev); 31827dec00eSMatt Ranostay if (ret) 31927dec00eSMatt Ranostay return ret; 32027dec00eSMatt Ranostay 32127dec00eSMatt Ranostay ret = pm_runtime_get_sync(&data->client->dev); 32227dec00eSMatt Ranostay if (ret < 0) { 32327dec00eSMatt Ranostay pm_runtime_put_noidle(&data->client->dev); 32427dec00eSMatt Ranostay return ret; 32527dec00eSMatt Ranostay } 32627dec00eSMatt Ranostay 32727dec00eSMatt Ranostay return atlas_set_interrupt(data, true); 32827dec00eSMatt Ranostay } 32927dec00eSMatt Ranostay 33027dec00eSMatt Ranostay static int atlas_buffer_predisable(struct iio_dev *indio_dev) 33127dec00eSMatt Ranostay { 33227dec00eSMatt Ranostay struct atlas_data *data = iio_priv(indio_dev); 33327dec00eSMatt Ranostay int ret; 33427dec00eSMatt Ranostay 33527dec00eSMatt Ranostay ret = atlas_set_interrupt(data, false); 33627dec00eSMatt Ranostay if (ret) 33727dec00eSMatt Ranostay return ret; 33827dec00eSMatt Ranostay 33927dec00eSMatt Ranostay pm_runtime_mark_last_busy(&data->client->dev); 3400c8a6e72SAlexandru Ardelean ret = pm_runtime_put_autosuspend(&data->client->dev); 3410c8a6e72SAlexandru Ardelean if (ret) 3420c8a6e72SAlexandru Ardelean return ret; 3430c8a6e72SAlexandru Ardelean 3440c8a6e72SAlexandru Ardelean return iio_triggered_buffer_predisable(indio_dev); 34527dec00eSMatt Ranostay } 34627dec00eSMatt Ranostay 34727dec00eSMatt Ranostay static const struct iio_trigger_ops atlas_interrupt_trigger_ops = { 34827dec00eSMatt Ranostay }; 34927dec00eSMatt Ranostay 35027dec00eSMatt Ranostay static const struct iio_buffer_setup_ops atlas_buffer_setup_ops = { 35127dec00eSMatt Ranostay .postenable = atlas_buffer_postenable, 35227dec00eSMatt Ranostay .predisable = atlas_buffer_predisable, 35327dec00eSMatt Ranostay }; 35427dec00eSMatt Ranostay 35527dec00eSMatt Ranostay static void atlas_work_handler(struct irq_work *work) 35627dec00eSMatt Ranostay { 35727dec00eSMatt Ranostay struct atlas_data *data = container_of(work, struct atlas_data, work); 35827dec00eSMatt Ranostay 35927dec00eSMatt Ranostay iio_trigger_poll(data->trig); 36027dec00eSMatt Ranostay } 36127dec00eSMatt Ranostay 36227dec00eSMatt Ranostay static irqreturn_t atlas_trigger_handler(int irq, void *private) 36327dec00eSMatt Ranostay { 36427dec00eSMatt Ranostay struct iio_poll_func *pf = private; 36527dec00eSMatt Ranostay struct iio_dev *indio_dev = pf->indio_dev; 36627dec00eSMatt Ranostay struct atlas_data *data = iio_priv(indio_dev); 367*4766897aSMatt Ranostay int channels = atlas_buffer_num_channels(data->chip->channels); 36827dec00eSMatt Ranostay int ret; 36927dec00eSMatt Ranostay 3707103b99bSMatt Ranostay ret = regmap_bulk_read(data->regmap, data->chip->data_reg, 3717103b99bSMatt Ranostay (u8 *) &data->buffer, 372*4766897aSMatt Ranostay sizeof(__be32) * channels); 37327dec00eSMatt Ranostay 37498e55e93SMatt Ranostay if (!ret) 37527dec00eSMatt Ranostay iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, 376bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev)); 37727dec00eSMatt Ranostay 37827dec00eSMatt Ranostay iio_trigger_notify_done(indio_dev->trig); 37927dec00eSMatt Ranostay 38027dec00eSMatt Ranostay return IRQ_HANDLED; 38127dec00eSMatt Ranostay } 38227dec00eSMatt Ranostay 38327dec00eSMatt Ranostay static irqreturn_t atlas_interrupt_handler(int irq, void *private) 38427dec00eSMatt Ranostay { 38527dec00eSMatt Ranostay struct iio_dev *indio_dev = private; 38627dec00eSMatt Ranostay struct atlas_data *data = iio_priv(indio_dev); 38727dec00eSMatt Ranostay 38827dec00eSMatt Ranostay irq_work_queue(&data->work); 38927dec00eSMatt Ranostay 39027dec00eSMatt Ranostay return IRQ_HANDLED; 39127dec00eSMatt Ranostay } 39227dec00eSMatt Ranostay 3937103b99bSMatt Ranostay static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val) 39427dec00eSMatt Ranostay { 39527dec00eSMatt Ranostay struct device *dev = &data->client->dev; 39627dec00eSMatt Ranostay int suspended = pm_runtime_suspended(dev); 39727dec00eSMatt Ranostay int ret; 39827dec00eSMatt Ranostay 39927dec00eSMatt Ranostay ret = pm_runtime_get_sync(dev); 40027dec00eSMatt Ranostay if (ret < 0) { 40127dec00eSMatt Ranostay pm_runtime_put_noidle(dev); 40227dec00eSMatt Ranostay return ret; 40327dec00eSMatt Ranostay } 40427dec00eSMatt Ranostay 40527dec00eSMatt Ranostay if (suspended) 40602112260SMatt Ranostay msleep(data->chip->delay); 40727dec00eSMatt Ranostay 4087103b99bSMatt Ranostay ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val)); 40927dec00eSMatt Ranostay 41027dec00eSMatt Ranostay pm_runtime_mark_last_busy(dev); 41127dec00eSMatt Ranostay pm_runtime_put_autosuspend(dev); 41227dec00eSMatt Ranostay 41327dec00eSMatt Ranostay return ret; 41427dec00eSMatt Ranostay } 41527dec00eSMatt Ranostay 41627dec00eSMatt Ranostay static int atlas_read_raw(struct iio_dev *indio_dev, 41727dec00eSMatt Ranostay struct iio_chan_spec const *chan, 41827dec00eSMatt Ranostay int *val, int *val2, long mask) 41927dec00eSMatt Ranostay { 42027dec00eSMatt Ranostay struct atlas_data *data = iio_priv(indio_dev); 42127dec00eSMatt Ranostay 42227dec00eSMatt Ranostay switch (mask) { 42327dec00eSMatt Ranostay case IIO_CHAN_INFO_RAW: { 42427dec00eSMatt Ranostay int ret; 42527dec00eSMatt Ranostay __be32 reg; 42627dec00eSMatt Ranostay 42727dec00eSMatt Ranostay switch (chan->type) { 42827dec00eSMatt Ranostay case IIO_TEMP: 42927dec00eSMatt Ranostay ret = regmap_bulk_read(data->regmap, chan->address, 43027dec00eSMatt Ranostay (u8 *) ®, sizeof(reg)); 43127dec00eSMatt Ranostay break; 43227dec00eSMatt Ranostay case IIO_PH: 433e8dd92bfSMatt Ranostay case IIO_CONCENTRATION: 434e8dd92bfSMatt Ranostay case IIO_ELECTRICALCONDUCTIVITY: 435ce08cc98SMatt Ranostay case IIO_VOLTAGE: 436b015b3e3SMatt Ranostay ret = iio_device_claim_direct_mode(indio_dev); 437b015b3e3SMatt Ranostay if (ret) 438b015b3e3SMatt Ranostay return ret; 43927dec00eSMatt Ranostay 440b015b3e3SMatt Ranostay ret = atlas_read_measurement(data, chan->address, ®); 44127dec00eSMatt Ranostay 442b015b3e3SMatt Ranostay iio_device_release_direct_mode(indio_dev); 44327dec00eSMatt Ranostay break; 44427dec00eSMatt Ranostay default: 44527dec00eSMatt Ranostay ret = -EINVAL; 44627dec00eSMatt Ranostay } 44727dec00eSMatt Ranostay 44827dec00eSMatt Ranostay if (!ret) { 44927dec00eSMatt Ranostay *val = be32_to_cpu(reg); 45027dec00eSMatt Ranostay ret = IIO_VAL_INT; 45127dec00eSMatt Ranostay } 45227dec00eSMatt Ranostay return ret; 45327dec00eSMatt Ranostay } 45427dec00eSMatt Ranostay case IIO_CHAN_INFO_SCALE: 45527dec00eSMatt Ranostay switch (chan->type) { 45627dec00eSMatt Ranostay case IIO_TEMP: 4570808831dSMatt Ranostay *val = 10; 4580808831dSMatt Ranostay return IIO_VAL_INT; 45927dec00eSMatt Ranostay case IIO_PH: 46027dec00eSMatt Ranostay *val = 1; /* 0.001 */ 46127dec00eSMatt Ranostay *val2 = 1000; 46227dec00eSMatt Ranostay break; 463e8dd92bfSMatt Ranostay case IIO_ELECTRICALCONDUCTIVITY: 464e8dd92bfSMatt Ranostay *val = 1; /* 0.00001 */ 465ca64d4bcSColin Ian King *val2 = 100000; 466e8dd92bfSMatt Ranostay break; 467e8dd92bfSMatt Ranostay case IIO_CONCENTRATION: 468e8dd92bfSMatt Ranostay *val = 0; /* 0.000000001 */ 469e8dd92bfSMatt Ranostay *val2 = 1000; 470e8dd92bfSMatt Ranostay return IIO_VAL_INT_PLUS_NANO; 471ce08cc98SMatt Ranostay case IIO_VOLTAGE: 472ce08cc98SMatt Ranostay *val = 1; /* 0.1 */ 473ce08cc98SMatt Ranostay *val2 = 10; 474ce08cc98SMatt Ranostay break; 47527dec00eSMatt Ranostay default: 47627dec00eSMatt Ranostay return -EINVAL; 47727dec00eSMatt Ranostay } 47827dec00eSMatt Ranostay return IIO_VAL_FRACTIONAL; 47927dec00eSMatt Ranostay } 48027dec00eSMatt Ranostay 48127dec00eSMatt Ranostay return -EINVAL; 48227dec00eSMatt Ranostay } 48327dec00eSMatt Ranostay 48427dec00eSMatt Ranostay static int atlas_write_raw(struct iio_dev *indio_dev, 48527dec00eSMatt Ranostay struct iio_chan_spec const *chan, 48627dec00eSMatt Ranostay int val, int val2, long mask) 48727dec00eSMatt Ranostay { 48827dec00eSMatt Ranostay struct atlas_data *data = iio_priv(indio_dev); 4890808831dSMatt Ranostay __be32 reg = cpu_to_be32(val / 10); 49027dec00eSMatt Ranostay 49127dec00eSMatt Ranostay if (val2 != 0 || val < 0 || val > 20000) 49227dec00eSMatt Ranostay return -EINVAL; 49327dec00eSMatt Ranostay 49427dec00eSMatt Ranostay if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_TEMP) 49527dec00eSMatt Ranostay return -EINVAL; 49627dec00eSMatt Ranostay 49727dec00eSMatt Ranostay return regmap_bulk_write(data->regmap, chan->address, 49827dec00eSMatt Ranostay ®, sizeof(reg)); 49927dec00eSMatt Ranostay } 50027dec00eSMatt Ranostay 50127dec00eSMatt Ranostay static const struct iio_info atlas_info = { 50227dec00eSMatt Ranostay .read_raw = atlas_read_raw, 50327dec00eSMatt Ranostay .write_raw = atlas_write_raw, 50427dec00eSMatt Ranostay }; 50527dec00eSMatt Ranostay 5067103b99bSMatt Ranostay static const struct i2c_device_id atlas_id[] = { 5077103b99bSMatt Ranostay { "atlas-ph-sm", ATLAS_PH_SM}, 508e8dd92bfSMatt Ranostay { "atlas-ec-sm", ATLAS_EC_SM}, 509ce08cc98SMatt Ranostay { "atlas-orp-sm", ATLAS_ORP_SM}, 5107103b99bSMatt Ranostay {} 51127dec00eSMatt Ranostay }; 5127103b99bSMatt Ranostay MODULE_DEVICE_TABLE(i2c, atlas_id); 5137103b99bSMatt Ranostay 5147103b99bSMatt Ranostay static const struct of_device_id atlas_dt_ids[] = { 5157103b99bSMatt Ranostay { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, 516e8dd92bfSMatt Ranostay { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, 517ce08cc98SMatt Ranostay { .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, }, 5187103b99bSMatt Ranostay { } 5197103b99bSMatt Ranostay }; 5207103b99bSMatt Ranostay MODULE_DEVICE_TABLE(of, atlas_dt_ids); 52127dec00eSMatt Ranostay 52227dec00eSMatt Ranostay static int atlas_probe(struct i2c_client *client, 52327dec00eSMatt Ranostay const struct i2c_device_id *id) 52427dec00eSMatt Ranostay { 52527dec00eSMatt Ranostay struct atlas_data *data; 5267103b99bSMatt Ranostay struct atlas_device *chip; 5277103b99bSMatt Ranostay const struct of_device_id *of_id; 52827dec00eSMatt Ranostay struct iio_trigger *trig; 52927dec00eSMatt Ranostay struct iio_dev *indio_dev; 53027dec00eSMatt Ranostay int ret; 53127dec00eSMatt Ranostay 53227dec00eSMatt Ranostay indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 53327dec00eSMatt Ranostay if (!indio_dev) 53427dec00eSMatt Ranostay return -ENOMEM; 53527dec00eSMatt Ranostay 5367103b99bSMatt Ranostay of_id = of_match_device(atlas_dt_ids, &client->dev); 5377103b99bSMatt Ranostay if (!of_id) 5387103b99bSMatt Ranostay chip = &atlas_devices[id->driver_data]; 5397103b99bSMatt Ranostay else 5407103b99bSMatt Ranostay chip = &atlas_devices[(unsigned long)of_id->data]; 5417103b99bSMatt Ranostay 54227dec00eSMatt Ranostay indio_dev->info = &atlas_info; 54327dec00eSMatt Ranostay indio_dev->name = ATLAS_DRV_NAME; 5447103b99bSMatt Ranostay indio_dev->channels = chip->channels; 5457103b99bSMatt Ranostay indio_dev->num_channels = chip->num_channels; 54627dec00eSMatt Ranostay indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; 54727dec00eSMatt Ranostay indio_dev->dev.parent = &client->dev; 54827dec00eSMatt Ranostay 54927dec00eSMatt Ranostay trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", 55027dec00eSMatt Ranostay indio_dev->name, indio_dev->id); 55127dec00eSMatt Ranostay 55227dec00eSMatt Ranostay if (!trig) 55327dec00eSMatt Ranostay return -ENOMEM; 55427dec00eSMatt Ranostay 55527dec00eSMatt Ranostay data = iio_priv(indio_dev); 55627dec00eSMatt Ranostay data->client = client; 55727dec00eSMatt Ranostay data->trig = trig; 5587103b99bSMatt Ranostay data->chip = chip; 55927dec00eSMatt Ranostay trig->dev.parent = indio_dev->dev.parent; 56027dec00eSMatt Ranostay trig->ops = &atlas_interrupt_trigger_ops; 56127dec00eSMatt Ranostay iio_trigger_set_drvdata(trig, indio_dev); 56227dec00eSMatt Ranostay 56327dec00eSMatt Ranostay i2c_set_clientdata(client, indio_dev); 56427dec00eSMatt Ranostay 56527dec00eSMatt Ranostay data->regmap = devm_regmap_init_i2c(client, &atlas_regmap_config); 56627dec00eSMatt Ranostay if (IS_ERR(data->regmap)) { 56727dec00eSMatt Ranostay dev_err(&client->dev, "regmap initialization failed\n"); 56827dec00eSMatt Ranostay return PTR_ERR(data->regmap); 56927dec00eSMatt Ranostay } 57027dec00eSMatt Ranostay 57127dec00eSMatt Ranostay ret = pm_runtime_set_active(&client->dev); 57227dec00eSMatt Ranostay if (ret) 57327dec00eSMatt Ranostay return ret; 57427dec00eSMatt Ranostay 57527dec00eSMatt Ranostay if (client->irq <= 0) { 57627dec00eSMatt Ranostay dev_err(&client->dev, "no valid irq defined\n"); 57727dec00eSMatt Ranostay return -EINVAL; 57827dec00eSMatt Ranostay } 57927dec00eSMatt Ranostay 5807103b99bSMatt Ranostay ret = chip->calibration(data); 58127dec00eSMatt Ranostay if (ret) 58227dec00eSMatt Ranostay return ret; 58327dec00eSMatt Ranostay 58427dec00eSMatt Ranostay ret = iio_trigger_register(trig); 58527dec00eSMatt Ranostay if (ret) { 58627dec00eSMatt Ranostay dev_err(&client->dev, "failed to register trigger\n"); 58727dec00eSMatt Ranostay return ret; 58827dec00eSMatt Ranostay } 58927dec00eSMatt Ranostay 59027dec00eSMatt Ranostay ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, 59127dec00eSMatt Ranostay &atlas_trigger_handler, &atlas_buffer_setup_ops); 59227dec00eSMatt Ranostay if (ret) { 59327dec00eSMatt Ranostay dev_err(&client->dev, "cannot setup iio trigger\n"); 59427dec00eSMatt Ranostay goto unregister_trigger; 59527dec00eSMatt Ranostay } 59627dec00eSMatt Ranostay 59727dec00eSMatt Ranostay init_irq_work(&data->work, atlas_work_handler); 59827dec00eSMatt Ranostay 59927dec00eSMatt Ranostay /* interrupt pin toggles on new conversion */ 60027dec00eSMatt Ranostay ret = devm_request_threaded_irq(&client->dev, client->irq, 60127dec00eSMatt Ranostay NULL, atlas_interrupt_handler, 60227dec00eSMatt Ranostay IRQF_TRIGGER_RISING | 60327dec00eSMatt Ranostay IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 60427dec00eSMatt Ranostay "atlas_irq", 60527dec00eSMatt Ranostay indio_dev); 60627dec00eSMatt Ranostay if (ret) { 60727dec00eSMatt Ranostay dev_err(&client->dev, "request irq (%d) failed\n", client->irq); 60827dec00eSMatt Ranostay goto unregister_buffer; 60927dec00eSMatt Ranostay } 61027dec00eSMatt Ranostay 61127dec00eSMatt Ranostay ret = atlas_set_powermode(data, 1); 61227dec00eSMatt Ranostay if (ret) { 61327dec00eSMatt Ranostay dev_err(&client->dev, "cannot power device on"); 61427dec00eSMatt Ranostay goto unregister_buffer; 61527dec00eSMatt Ranostay } 61627dec00eSMatt Ranostay 61727dec00eSMatt Ranostay pm_runtime_enable(&client->dev); 61827dec00eSMatt Ranostay pm_runtime_set_autosuspend_delay(&client->dev, 2500); 61927dec00eSMatt Ranostay pm_runtime_use_autosuspend(&client->dev); 62027dec00eSMatt Ranostay 62127dec00eSMatt Ranostay ret = iio_device_register(indio_dev); 62227dec00eSMatt Ranostay if (ret) { 62327dec00eSMatt Ranostay dev_err(&client->dev, "unable to register device\n"); 62427dec00eSMatt Ranostay goto unregister_pm; 62527dec00eSMatt Ranostay } 62627dec00eSMatt Ranostay 62727dec00eSMatt Ranostay return 0; 62827dec00eSMatt Ranostay 62927dec00eSMatt Ranostay unregister_pm: 63027dec00eSMatt Ranostay pm_runtime_disable(&client->dev); 63127dec00eSMatt Ranostay atlas_set_powermode(data, 0); 63227dec00eSMatt Ranostay 63327dec00eSMatt Ranostay unregister_buffer: 63427dec00eSMatt Ranostay iio_triggered_buffer_cleanup(indio_dev); 63527dec00eSMatt Ranostay 63627dec00eSMatt Ranostay unregister_trigger: 63727dec00eSMatt Ranostay iio_trigger_unregister(data->trig); 63827dec00eSMatt Ranostay 63927dec00eSMatt Ranostay return ret; 64027dec00eSMatt Ranostay } 64127dec00eSMatt Ranostay 64227dec00eSMatt Ranostay static int atlas_remove(struct i2c_client *client) 64327dec00eSMatt Ranostay { 64427dec00eSMatt Ranostay struct iio_dev *indio_dev = i2c_get_clientdata(client); 64527dec00eSMatt Ranostay struct atlas_data *data = iio_priv(indio_dev); 64627dec00eSMatt Ranostay 64727dec00eSMatt Ranostay iio_device_unregister(indio_dev); 64827dec00eSMatt Ranostay iio_triggered_buffer_cleanup(indio_dev); 64927dec00eSMatt Ranostay iio_trigger_unregister(data->trig); 65027dec00eSMatt Ranostay 65127dec00eSMatt Ranostay pm_runtime_disable(&client->dev); 65227dec00eSMatt Ranostay pm_runtime_set_suspended(&client->dev); 65327dec00eSMatt Ranostay pm_runtime_put_noidle(&client->dev); 65427dec00eSMatt Ranostay 65527dec00eSMatt Ranostay return atlas_set_powermode(data, 0); 65627dec00eSMatt Ranostay } 65727dec00eSMatt Ranostay 65827dec00eSMatt Ranostay #ifdef CONFIG_PM 65927dec00eSMatt Ranostay static int atlas_runtime_suspend(struct device *dev) 66027dec00eSMatt Ranostay { 66127dec00eSMatt Ranostay struct atlas_data *data = 66227dec00eSMatt Ranostay iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 66327dec00eSMatt Ranostay 66427dec00eSMatt Ranostay return atlas_set_powermode(data, 0); 66527dec00eSMatt Ranostay } 66627dec00eSMatt Ranostay 66727dec00eSMatt Ranostay static int atlas_runtime_resume(struct device *dev) 66827dec00eSMatt Ranostay { 66927dec00eSMatt Ranostay struct atlas_data *data = 67027dec00eSMatt Ranostay iio_priv(i2c_get_clientdata(to_i2c_client(dev))); 67127dec00eSMatt Ranostay 67227dec00eSMatt Ranostay return atlas_set_powermode(data, 1); 67327dec00eSMatt Ranostay } 67427dec00eSMatt Ranostay #endif 67527dec00eSMatt Ranostay 67627dec00eSMatt Ranostay static const struct dev_pm_ops atlas_pm_ops = { 67727dec00eSMatt Ranostay SET_RUNTIME_PM_OPS(atlas_runtime_suspend, 67827dec00eSMatt Ranostay atlas_runtime_resume, NULL) 67927dec00eSMatt Ranostay }; 68027dec00eSMatt Ranostay 68127dec00eSMatt Ranostay static struct i2c_driver atlas_driver = { 68227dec00eSMatt Ranostay .driver = { 68327dec00eSMatt Ranostay .name = ATLAS_DRV_NAME, 68427dec00eSMatt Ranostay .of_match_table = of_match_ptr(atlas_dt_ids), 68527dec00eSMatt Ranostay .pm = &atlas_pm_ops, 68627dec00eSMatt Ranostay }, 68727dec00eSMatt Ranostay .probe = atlas_probe, 68827dec00eSMatt Ranostay .remove = atlas_remove, 68927dec00eSMatt Ranostay .id_table = atlas_id, 69027dec00eSMatt Ranostay }; 69127dec00eSMatt Ranostay module_i2c_driver(atlas_driver); 69227dec00eSMatt Ranostay 693d6ad8058SMatt Ranostay MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); 6940d15190fSMatt Ranostay MODULE_DESCRIPTION("Atlas Scientific SM sensors"); 69527dec00eSMatt Ranostay MODULE_LICENSE("GPL"); 696