1d6ad8058SMatt Ranostay // SPDX-License-Identifier: GPL-2.0+ 267e17300SMatt Ranostay /* 367e17300SMatt Ranostay * lmp91000.c - Support for Texas Instruments digital potentiostats 467e17300SMatt Ranostay * 5d6ad8058SMatt Ranostay * Copyright (C) 2016, 2018 6d6ad8058SMatt Ranostay * Author: Matt Ranostay <matt.ranostay@konsulko.com> 767e17300SMatt Ranostay * 867e17300SMatt Ranostay * TODO: bias voltage + polarity control, and multiple chip support 967e17300SMatt Ranostay */ 1067e17300SMatt Ranostay 1167e17300SMatt Ranostay #include <linux/module.h> 1267e17300SMatt Ranostay #include <linux/i2c.h> 1367e17300SMatt Ranostay #include <linux/delay.h> 144c55fb8cSJonathan Cameron #include <linux/mod_devicetable.h> 1567e17300SMatt Ranostay #include <linux/regmap.h> 1667e17300SMatt Ranostay #include <linux/iio/iio.h> 1767e17300SMatt Ranostay #include <linux/iio/buffer.h> 1867e17300SMatt Ranostay #include <linux/iio/consumer.h> 1967e17300SMatt Ranostay #include <linux/iio/trigger.h> 2067e17300SMatt Ranostay #include <linux/iio/trigger_consumer.h> 2167e17300SMatt Ranostay #include <linux/iio/triggered_buffer.h> 2267e17300SMatt Ranostay 2367e17300SMatt Ranostay #define LMP91000_REG_LOCK 0x01 2467e17300SMatt Ranostay #define LMP91000_REG_TIACN 0x10 2567e17300SMatt Ranostay #define LMP91000_REG_TIACN_GAIN_SHIFT 2 2667e17300SMatt Ranostay 2767e17300SMatt Ranostay #define LMP91000_REG_REFCN 0x11 2867e17300SMatt Ranostay #define LMP91000_REG_REFCN_EXT_REF 0x20 2967e17300SMatt Ranostay #define LMP91000_REG_REFCN_50_ZERO 0x80 3067e17300SMatt Ranostay 3167e17300SMatt Ranostay #define LMP91000_REG_MODECN 0x12 3267e17300SMatt Ranostay #define LMP91000_REG_MODECN_3LEAD 0x03 3367e17300SMatt Ranostay #define LMP91000_REG_MODECN_TEMP 0x07 3467e17300SMatt Ranostay 3567e17300SMatt Ranostay #define LMP91000_DRV_NAME "lmp91000" 3667e17300SMatt Ranostay 3767e17300SMatt Ranostay static const int lmp91000_tia_gain[] = { 0, 2750, 3500, 7000, 14000, 35000, 3867e17300SMatt Ranostay 120000, 350000 }; 3967e17300SMatt Ranostay 4067e17300SMatt Ranostay static const int lmp91000_rload[] = { 10, 33, 50, 100 }; 4167e17300SMatt Ranostay 4267e17300SMatt Ranostay #define LMP91000_TEMP_BASE -40 4367e17300SMatt Ranostay 4467e17300SMatt Ranostay static const u16 lmp91000_temp_lut[] = { 4567e17300SMatt Ranostay 1875, 1867, 1860, 1852, 1844, 1836, 1828, 1821, 1813, 1805, 4667e17300SMatt Ranostay 1797, 1789, 1782, 1774, 1766, 1758, 1750, 1742, 1734, 1727, 4767e17300SMatt Ranostay 1719, 1711, 1703, 1695, 1687, 1679, 1671, 1663, 1656, 1648, 4867e17300SMatt Ranostay 1640, 1632, 1624, 1616, 1608, 1600, 1592, 1584, 1576, 1568, 4967e17300SMatt Ranostay 1560, 1552, 1544, 1536, 1528, 1520, 1512, 1504, 1496, 1488, 5067e17300SMatt Ranostay 1480, 1472, 1464, 1456, 1448, 1440, 1432, 1424, 1415, 1407, 5167e17300SMatt Ranostay 1399, 1391, 1383, 1375, 1367, 1359, 1351, 1342, 1334, 1326, 5267e17300SMatt Ranostay 1318, 1310, 1302, 1293, 1285, 1277, 1269, 1261, 1253, 1244, 5367e17300SMatt Ranostay 1236, 1228, 1220, 1212, 1203, 1195, 1187, 1179, 1170, 1162, 5467e17300SMatt Ranostay 1154, 1146, 1137, 1129, 1121, 1112, 1104, 1096, 1087, 1079, 5567e17300SMatt Ranostay 1071, 1063, 1054, 1046, 1038, 1029, 1021, 1012, 1004, 996, 5667e17300SMatt Ranostay 987, 979, 971, 962, 954, 945, 937, 929, 920, 912, 5767e17300SMatt Ranostay 903, 895, 886, 878, 870, 861 }; 5867e17300SMatt Ranostay 5967e17300SMatt Ranostay static const struct regmap_config lmp91000_regmap_config = { 6067e17300SMatt Ranostay .reg_bits = 8, 6167e17300SMatt Ranostay .val_bits = 8, 6267e17300SMatt Ranostay }; 6367e17300SMatt Ranostay 6467e17300SMatt Ranostay struct lmp91000_data { 6567e17300SMatt Ranostay struct regmap *regmap; 6667e17300SMatt Ranostay struct device *dev; 6767e17300SMatt Ranostay 6867e17300SMatt Ranostay struct iio_trigger *trig; 6967e17300SMatt Ranostay struct iio_cb_buffer *cb_buffer; 7067e17300SMatt Ranostay struct iio_channel *adc_chan; 7167e17300SMatt Ranostay 7267e17300SMatt Ranostay struct completion completion; 7367e17300SMatt Ranostay u8 chan_select; 74*8979b67eSJonathan Cameron /* 64-bit data + 64-bit naturally aligned timestamp */ 75*8979b67eSJonathan Cameron u32 buffer[4] __aligned(8); 7667e17300SMatt Ranostay }; 7767e17300SMatt Ranostay 7867e17300SMatt Ranostay static const struct iio_chan_spec lmp91000_channels[] = { 7967e17300SMatt Ranostay { /* chemical channel mV */ 8067e17300SMatt Ranostay .type = IIO_VOLTAGE, 8167e17300SMatt Ranostay .channel = 0, 8267e17300SMatt Ranostay .address = LMP91000_REG_MODECN_3LEAD, 8367e17300SMatt Ranostay .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 8467e17300SMatt Ranostay BIT(IIO_CHAN_INFO_OFFSET) | 8567e17300SMatt Ranostay BIT(IIO_CHAN_INFO_SCALE), 8667e17300SMatt Ranostay .scan_index = 0, 8767e17300SMatt Ranostay .scan_type = { 8867e17300SMatt Ranostay .sign = 's', 8967e17300SMatt Ranostay .realbits = 32, 9067e17300SMatt Ranostay .storagebits = 32, 9167e17300SMatt Ranostay }, 9267e17300SMatt Ranostay }, 9367e17300SMatt Ranostay IIO_CHAN_SOFT_TIMESTAMP(1), 9467e17300SMatt Ranostay { /* temperature channel mV */ 9567e17300SMatt Ranostay .type = IIO_TEMP, 9667e17300SMatt Ranostay .channel = 1, 9767e17300SMatt Ranostay .address = LMP91000_REG_MODECN_TEMP, 9867e17300SMatt Ranostay .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 9967e17300SMatt Ranostay .scan_index = -1, 10067e17300SMatt Ranostay }, 10167e17300SMatt Ranostay }; 10267e17300SMatt Ranostay 10367e17300SMatt Ranostay static int lmp91000_read(struct lmp91000_data *data, int channel, int *val) 10467e17300SMatt Ranostay { 10567e17300SMatt Ranostay int state, ret; 10667e17300SMatt Ranostay 10767e17300SMatt Ranostay ret = regmap_read(data->regmap, LMP91000_REG_MODECN, &state); 10867e17300SMatt Ranostay if (ret) 10967e17300SMatt Ranostay return -EINVAL; 11067e17300SMatt Ranostay 11167e17300SMatt Ranostay ret = regmap_write(data->regmap, LMP91000_REG_MODECN, channel); 11267e17300SMatt Ranostay if (ret) 11367e17300SMatt Ranostay return -EINVAL; 11467e17300SMatt Ranostay 11567e17300SMatt Ranostay /* delay till first temperature reading is complete */ 116681ca447SLucas Oshiro if (state != channel && channel == LMP91000_REG_MODECN_TEMP) 11767e17300SMatt Ranostay usleep_range(3000, 4000); 11867e17300SMatt Ranostay 11967e17300SMatt Ranostay data->chan_select = channel != LMP91000_REG_MODECN_3LEAD; 12067e17300SMatt Ranostay 12167e17300SMatt Ranostay iio_trigger_poll_chained(data->trig); 12267e17300SMatt Ranostay 12367e17300SMatt Ranostay ret = wait_for_completion_timeout(&data->completion, HZ); 12467e17300SMatt Ranostay reinit_completion(&data->completion); 12567e17300SMatt Ranostay 12667e17300SMatt Ranostay if (!ret) 12767e17300SMatt Ranostay return -ETIMEDOUT; 12867e17300SMatt Ranostay 12967e17300SMatt Ranostay *val = data->buffer[data->chan_select]; 13067e17300SMatt Ranostay 13167e17300SMatt Ranostay return 0; 13267e17300SMatt Ranostay } 13367e17300SMatt Ranostay 13467e17300SMatt Ranostay static irqreturn_t lmp91000_buffer_handler(int irq, void *private) 13567e17300SMatt Ranostay { 13667e17300SMatt Ranostay struct iio_poll_func *pf = private; 13767e17300SMatt Ranostay struct iio_dev *indio_dev = pf->indio_dev; 13867e17300SMatt Ranostay struct lmp91000_data *data = iio_priv(indio_dev); 13967e17300SMatt Ranostay int ret, val; 14067e17300SMatt Ranostay 14167e17300SMatt Ranostay memset(data->buffer, 0, sizeof(data->buffer)); 14267e17300SMatt Ranostay 14367e17300SMatt Ranostay ret = lmp91000_read(data, LMP91000_REG_MODECN_3LEAD, &val); 14467e17300SMatt Ranostay if (!ret) { 14567e17300SMatt Ranostay data->buffer[0] = val; 14667e17300SMatt Ranostay iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, 14767e17300SMatt Ranostay iio_get_time_ns(indio_dev)); 14867e17300SMatt Ranostay } 14967e17300SMatt Ranostay 15067e17300SMatt Ranostay iio_trigger_notify_done(indio_dev->trig); 15167e17300SMatt Ranostay 15267e17300SMatt Ranostay return IRQ_HANDLED; 15367e17300SMatt Ranostay } 15467e17300SMatt Ranostay 15567e17300SMatt Ranostay static int lmp91000_read_raw(struct iio_dev *indio_dev, 15667e17300SMatt Ranostay struct iio_chan_spec const *chan, 15767e17300SMatt Ranostay int *val, int *val2, long mask) 15867e17300SMatt Ranostay { 15967e17300SMatt Ranostay struct lmp91000_data *data = iio_priv(indio_dev); 16067e17300SMatt Ranostay 16167e17300SMatt Ranostay switch (mask) { 16267e17300SMatt Ranostay case IIO_CHAN_INFO_RAW: 16367e17300SMatt Ranostay case IIO_CHAN_INFO_PROCESSED: { 16467e17300SMatt Ranostay int ret = iio_channel_start_all_cb(data->cb_buffer); 16567e17300SMatt Ranostay 16667e17300SMatt Ranostay if (ret) 16767e17300SMatt Ranostay return ret; 16867e17300SMatt Ranostay 16967e17300SMatt Ranostay ret = lmp91000_read(data, chan->address, val); 17067e17300SMatt Ranostay 17167e17300SMatt Ranostay iio_channel_stop_all_cb(data->cb_buffer); 17267e17300SMatt Ranostay 17367e17300SMatt Ranostay if (ret) 17467e17300SMatt Ranostay return ret; 17567e17300SMatt Ranostay 17667e17300SMatt Ranostay if (mask == IIO_CHAN_INFO_PROCESSED) { 17767e17300SMatt Ranostay int tmp, i; 17867e17300SMatt Ranostay 17967e17300SMatt Ranostay ret = iio_convert_raw_to_processed(data->adc_chan, 18067e17300SMatt Ranostay *val, &tmp, 1); 18167e17300SMatt Ranostay if (ret) 18267e17300SMatt Ranostay return ret; 18367e17300SMatt Ranostay 18467e17300SMatt Ranostay for (i = 0; i < ARRAY_SIZE(lmp91000_temp_lut); i++) 18567e17300SMatt Ranostay if (lmp91000_temp_lut[i] < tmp) 18667e17300SMatt Ranostay break; 18767e17300SMatt Ranostay 18867e17300SMatt Ranostay *val = (LMP91000_TEMP_BASE + i) * 1000; 18967e17300SMatt Ranostay } 19067e17300SMatt Ranostay return IIO_VAL_INT; 19167e17300SMatt Ranostay } 19267e17300SMatt Ranostay case IIO_CHAN_INFO_OFFSET: 19367e17300SMatt Ranostay return iio_read_channel_offset(data->adc_chan, val, val2); 19467e17300SMatt Ranostay case IIO_CHAN_INFO_SCALE: 19567e17300SMatt Ranostay return iio_read_channel_scale(data->adc_chan, val, val2); 19667e17300SMatt Ranostay } 19767e17300SMatt Ranostay 19867e17300SMatt Ranostay return -EINVAL; 19967e17300SMatt Ranostay } 20067e17300SMatt Ranostay 20167e17300SMatt Ranostay static const struct iio_info lmp91000_info = { 20267e17300SMatt Ranostay .read_raw = lmp91000_read_raw, 20367e17300SMatt Ranostay }; 20467e17300SMatt Ranostay 20567e17300SMatt Ranostay static int lmp91000_read_config(struct lmp91000_data *data) 20667e17300SMatt Ranostay { 20767e17300SMatt Ranostay struct device *dev = data->dev; 20867e17300SMatt Ranostay unsigned int reg, val; 20967e17300SMatt Ranostay int i, ret; 21067e17300SMatt Ranostay 2114c55fb8cSJonathan Cameron ret = device_property_read_u32(dev, "ti,tia-gain-ohm", &val); 21267e17300SMatt Ranostay if (ret) { 2134c55fb8cSJonathan Cameron if (!device_property_read_bool(dev, "ti,external-tia-resistor")) { 21471a7766bSAnderson Reis dev_err(dev, "no ti,tia-gain-ohm defined and external resistor not specified\n"); 21567e17300SMatt Ranostay return ret; 21667e17300SMatt Ranostay } 217b11a89d5SAnderson Reis val = 0; 21867e17300SMatt Ranostay } 21967e17300SMatt Ranostay 22067e17300SMatt Ranostay ret = -EINVAL; 22167e17300SMatt Ranostay for (i = 0; i < ARRAY_SIZE(lmp91000_tia_gain); i++) { 22267e17300SMatt Ranostay if (lmp91000_tia_gain[i] == val) { 22367e17300SMatt Ranostay reg = i << LMP91000_REG_TIACN_GAIN_SHIFT; 22467e17300SMatt Ranostay ret = 0; 22567e17300SMatt Ranostay break; 22667e17300SMatt Ranostay } 22767e17300SMatt Ranostay } 22867e17300SMatt Ranostay 22967e17300SMatt Ranostay if (ret) { 23067e17300SMatt Ranostay dev_err(dev, "invalid ti,tia-gain-ohm %d\n", val); 23167e17300SMatt Ranostay return ret; 23267e17300SMatt Ranostay } 23367e17300SMatt Ranostay 2344c55fb8cSJonathan Cameron ret = device_property_read_u32(dev, "ti,rload-ohm", &val); 23567e17300SMatt Ranostay if (ret) { 23667e17300SMatt Ranostay val = 100; 23767e17300SMatt Ranostay dev_info(dev, "no ti,rload-ohm defined, default to %d\n", val); 23867e17300SMatt Ranostay } 23967e17300SMatt Ranostay 24067e17300SMatt Ranostay ret = -EINVAL; 24167e17300SMatt Ranostay for (i = 0; i < ARRAY_SIZE(lmp91000_rload); i++) { 24267e17300SMatt Ranostay if (lmp91000_rload[i] == val) { 24367e17300SMatt Ranostay reg |= i; 24467e17300SMatt Ranostay ret = 0; 24567e17300SMatt Ranostay break; 24667e17300SMatt Ranostay } 24767e17300SMatt Ranostay } 24867e17300SMatt Ranostay 24967e17300SMatt Ranostay if (ret) { 25067e17300SMatt Ranostay dev_err(dev, "invalid ti,rload-ohm %d\n", val); 25167e17300SMatt Ranostay return ret; 25267e17300SMatt Ranostay } 25367e17300SMatt Ranostay 25467e17300SMatt Ranostay regmap_write(data->regmap, LMP91000_REG_LOCK, 0); 25567e17300SMatt Ranostay regmap_write(data->regmap, LMP91000_REG_TIACN, reg); 256cd4779f1SAnderson Reis regmap_write(data->regmap, LMP91000_REG_REFCN, 257cd4779f1SAnderson Reis LMP91000_REG_REFCN_EXT_REF | LMP91000_REG_REFCN_50_ZERO); 25867e17300SMatt Ranostay regmap_write(data->regmap, LMP91000_REG_LOCK, 1); 25967e17300SMatt Ranostay 26067e17300SMatt Ranostay return 0; 26167e17300SMatt Ranostay } 26267e17300SMatt Ranostay 26367e17300SMatt Ranostay static int lmp91000_buffer_cb(const void *val, void *private) 26467e17300SMatt Ranostay { 26567e17300SMatt Ranostay struct iio_dev *indio_dev = private; 26667e17300SMatt Ranostay struct lmp91000_data *data = iio_priv(indio_dev); 26767e17300SMatt Ranostay 26867e17300SMatt Ranostay data->buffer[data->chan_select] = *((int *)val); 26967e17300SMatt Ranostay complete_all(&data->completion); 27067e17300SMatt Ranostay 27167e17300SMatt Ranostay return 0; 27267e17300SMatt Ranostay } 27367e17300SMatt Ranostay 27467e17300SMatt Ranostay static const struct iio_trigger_ops lmp91000_trigger_ops = { 27567e17300SMatt Ranostay }; 27667e17300SMatt Ranostay 277d7cf5f60SAlexandru Ardelean static int lmp91000_buffer_postenable(struct iio_dev *indio_dev) 27867e17300SMatt Ranostay { 27967e17300SMatt Ranostay struct lmp91000_data *data = iio_priv(indio_dev); 28067e17300SMatt Ranostay 281f11d59d8SLars-Peter Clausen return iio_channel_start_all_cb(data->cb_buffer); 28267e17300SMatt Ranostay } 28367e17300SMatt Ranostay 28467e17300SMatt Ranostay static int lmp91000_buffer_predisable(struct iio_dev *indio_dev) 28567e17300SMatt Ranostay { 28667e17300SMatt Ranostay struct lmp91000_data *data = iio_priv(indio_dev); 28767e17300SMatt Ranostay 28867e17300SMatt Ranostay iio_channel_stop_all_cb(data->cb_buffer); 28967e17300SMatt Ranostay 290f11d59d8SLars-Peter Clausen return 0; 29167e17300SMatt Ranostay } 29267e17300SMatt Ranostay 29367e17300SMatt Ranostay static const struct iio_buffer_setup_ops lmp91000_buffer_setup_ops = { 294d7cf5f60SAlexandru Ardelean .postenable = lmp91000_buffer_postenable, 29567e17300SMatt Ranostay .predisable = lmp91000_buffer_predisable, 29667e17300SMatt Ranostay }; 29767e17300SMatt Ranostay 29867e17300SMatt Ranostay static int lmp91000_probe(struct i2c_client *client, 29967e17300SMatt Ranostay const struct i2c_device_id *id) 30067e17300SMatt Ranostay { 30167e17300SMatt Ranostay struct device *dev = &client->dev; 30267e17300SMatt Ranostay struct lmp91000_data *data; 30367e17300SMatt Ranostay struct iio_dev *indio_dev; 30467e17300SMatt Ranostay int ret; 30567e17300SMatt Ranostay 30667e17300SMatt Ranostay indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 30767e17300SMatt Ranostay if (!indio_dev) 30867e17300SMatt Ranostay return -ENOMEM; 30967e17300SMatt Ranostay 31067e17300SMatt Ranostay indio_dev->info = &lmp91000_info; 31167e17300SMatt Ranostay indio_dev->channels = lmp91000_channels; 31267e17300SMatt Ranostay indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels); 31367e17300SMatt Ranostay indio_dev->name = LMP91000_DRV_NAME; 31467e17300SMatt Ranostay indio_dev->modes = INDIO_DIRECT_MODE; 31567e17300SMatt Ranostay i2c_set_clientdata(client, indio_dev); 31667e17300SMatt Ranostay 31767e17300SMatt Ranostay data = iio_priv(indio_dev); 31867e17300SMatt Ranostay data->dev = dev; 31967e17300SMatt Ranostay data->regmap = devm_regmap_init_i2c(client, &lmp91000_regmap_config); 32067e17300SMatt Ranostay if (IS_ERR(data->regmap)) { 32167e17300SMatt Ranostay dev_err(dev, "regmap initialization failed.\n"); 32267e17300SMatt Ranostay return PTR_ERR(data->regmap); 32367e17300SMatt Ranostay } 32467e17300SMatt Ranostay 3254d031666SGwendal Grignou data->trig = devm_iio_trigger_alloc(dev, "%s-mux%d", 32615ea2878SJonathan Cameron indio_dev->name, 32715ea2878SJonathan Cameron iio_device_id(indio_dev)); 32867e17300SMatt Ranostay if (!data->trig) { 32967e17300SMatt Ranostay dev_err(dev, "cannot allocate iio trigger.\n"); 33067e17300SMatt Ranostay return -ENOMEM; 33167e17300SMatt Ranostay } 33267e17300SMatt Ranostay 33367e17300SMatt Ranostay data->trig->ops = &lmp91000_trigger_ops; 33467e17300SMatt Ranostay init_completion(&data->completion); 33567e17300SMatt Ranostay 33667e17300SMatt Ranostay ret = lmp91000_read_config(data); 33767e17300SMatt Ranostay if (ret) 33867e17300SMatt Ranostay return ret; 33967e17300SMatt Ranostay 34067e17300SMatt Ranostay ret = iio_trigger_set_immutable(iio_channel_cb_get_iio_dev(data->cb_buffer), 34167e17300SMatt Ranostay data->trig); 34267e17300SMatt Ranostay if (ret) { 34367e17300SMatt Ranostay dev_err(dev, "cannot set immutable trigger.\n"); 34467e17300SMatt Ranostay return ret; 34567e17300SMatt Ranostay } 34667e17300SMatt Ranostay 34767e17300SMatt Ranostay ret = iio_trigger_register(data->trig); 34867e17300SMatt Ranostay if (ret) { 34967e17300SMatt Ranostay dev_err(dev, "cannot register iio trigger.\n"); 35067e17300SMatt Ranostay return ret; 35167e17300SMatt Ranostay } 35267e17300SMatt Ranostay 35367e17300SMatt Ranostay ret = iio_triggered_buffer_setup(indio_dev, NULL, 35467e17300SMatt Ranostay &lmp91000_buffer_handler, 35567e17300SMatt Ranostay &lmp91000_buffer_setup_ops); 35667e17300SMatt Ranostay if (ret) 35767e17300SMatt Ranostay goto error_unreg_trigger; 35867e17300SMatt Ranostay 35967e17300SMatt Ranostay data->cb_buffer = iio_channel_get_all_cb(dev, &lmp91000_buffer_cb, 36067e17300SMatt Ranostay indio_dev); 36167e17300SMatt Ranostay 36267e17300SMatt Ranostay if (IS_ERR(data->cb_buffer)) { 36367e17300SMatt Ranostay if (PTR_ERR(data->cb_buffer) == -ENODEV) 36467e17300SMatt Ranostay ret = -EPROBE_DEFER; 36567e17300SMatt Ranostay else 36667e17300SMatt Ranostay ret = PTR_ERR(data->cb_buffer); 36767e17300SMatt Ranostay 36867e17300SMatt Ranostay goto error_unreg_buffer; 36967e17300SMatt Ranostay } 37067e17300SMatt Ranostay 37167e17300SMatt Ranostay data->adc_chan = iio_channel_cb_get_channels(data->cb_buffer); 37267e17300SMatt Ranostay 37367e17300SMatt Ranostay ret = iio_device_register(indio_dev); 37467e17300SMatt Ranostay if (ret) 37567e17300SMatt Ranostay goto error_unreg_cb_buffer; 37667e17300SMatt Ranostay 37767e17300SMatt Ranostay return 0; 37867e17300SMatt Ranostay 37967e17300SMatt Ranostay error_unreg_cb_buffer: 38067e17300SMatt Ranostay iio_channel_release_all_cb(data->cb_buffer); 38167e17300SMatt Ranostay 38267e17300SMatt Ranostay error_unreg_buffer: 38367e17300SMatt Ranostay iio_triggered_buffer_cleanup(indio_dev); 38467e17300SMatt Ranostay 38567e17300SMatt Ranostay error_unreg_trigger: 38667e17300SMatt Ranostay iio_trigger_unregister(data->trig); 38767e17300SMatt Ranostay 38867e17300SMatt Ranostay return ret; 38967e17300SMatt Ranostay } 39067e17300SMatt Ranostay 39167e17300SMatt Ranostay static int lmp91000_remove(struct i2c_client *client) 39267e17300SMatt Ranostay { 39367e17300SMatt Ranostay struct iio_dev *indio_dev = i2c_get_clientdata(client); 39467e17300SMatt Ranostay struct lmp91000_data *data = iio_priv(indio_dev); 39567e17300SMatt Ranostay 39667e17300SMatt Ranostay iio_device_unregister(indio_dev); 39767e17300SMatt Ranostay 39867e17300SMatt Ranostay iio_channel_stop_all_cb(data->cb_buffer); 39967e17300SMatt Ranostay iio_channel_release_all_cb(data->cb_buffer); 40067e17300SMatt Ranostay 40167e17300SMatt Ranostay iio_triggered_buffer_cleanup(indio_dev); 40267e17300SMatt Ranostay iio_trigger_unregister(data->trig); 40367e17300SMatt Ranostay 40467e17300SMatt Ranostay return 0; 40567e17300SMatt Ranostay } 40667e17300SMatt Ranostay 40767e17300SMatt Ranostay static const struct of_device_id lmp91000_of_match[] = { 40867e17300SMatt Ranostay { .compatible = "ti,lmp91000", }, 4090cb2aab8SMatt Ranostay { .compatible = "ti,lmp91002", }, 41067e17300SMatt Ranostay { }, 41167e17300SMatt Ranostay }; 41267e17300SMatt Ranostay MODULE_DEVICE_TABLE(of, lmp91000_of_match); 41367e17300SMatt Ranostay 41467e17300SMatt Ranostay static const struct i2c_device_id lmp91000_id[] = { 41567e17300SMatt Ranostay { "lmp91000", 0 }, 4160cb2aab8SMatt Ranostay { "lmp91002", 0 }, 41767e17300SMatt Ranostay {} 41867e17300SMatt Ranostay }; 41967e17300SMatt Ranostay MODULE_DEVICE_TABLE(i2c, lmp91000_id); 42067e17300SMatt Ranostay 42167e17300SMatt Ranostay static struct i2c_driver lmp91000_driver = { 42267e17300SMatt Ranostay .driver = { 42367e17300SMatt Ranostay .name = LMP91000_DRV_NAME, 4244c55fb8cSJonathan Cameron .of_match_table = lmp91000_of_match, 42567e17300SMatt Ranostay }, 42667e17300SMatt Ranostay .probe = lmp91000_probe, 42767e17300SMatt Ranostay .remove = lmp91000_remove, 42867e17300SMatt Ranostay .id_table = lmp91000_id, 42967e17300SMatt Ranostay }; 43067e17300SMatt Ranostay module_i2c_driver(lmp91000_driver); 43167e17300SMatt Ranostay 432d6ad8058SMatt Ranostay MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); 43367e17300SMatt Ranostay MODULE_DESCRIPTION("LMP91000 digital potentiostat"); 43467e17300SMatt Ranostay MODULE_LICENSE("GPL"); 435