1fda8d26eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 24eb3ccf1SLars-Peter Clausen /* 34eb3ccf1SLars-Peter Clausen * AD7887 SPI ADC driver 44eb3ccf1SLars-Peter Clausen * 54eb3ccf1SLars-Peter Clausen * Copyright 2010-2011 Analog Devices Inc. 64eb3ccf1SLars-Peter Clausen */ 74eb3ccf1SLars-Peter Clausen 84eb3ccf1SLars-Peter Clausen #include <linux/device.h> 94eb3ccf1SLars-Peter Clausen #include <linux/kernel.h> 104eb3ccf1SLars-Peter Clausen #include <linux/slab.h> 114eb3ccf1SLars-Peter Clausen #include <linux/sysfs.h> 124eb3ccf1SLars-Peter Clausen #include <linux/spi/spi.h> 134eb3ccf1SLars-Peter Clausen #include <linux/regulator/consumer.h> 144eb3ccf1SLars-Peter Clausen #include <linux/err.h> 154eb3ccf1SLars-Peter Clausen #include <linux/module.h> 164eb3ccf1SLars-Peter Clausen #include <linux/interrupt.h> 1709a1737eSPeter Meerwald #include <linux/bitops.h> 184eb3ccf1SLars-Peter Clausen 194eb3ccf1SLars-Peter Clausen #include <linux/iio/iio.h> 204eb3ccf1SLars-Peter Clausen #include <linux/iio/sysfs.h> 214eb3ccf1SLars-Peter Clausen #include <linux/iio/buffer.h> 224eb3ccf1SLars-Peter Clausen 234eb3ccf1SLars-Peter Clausen #include <linux/iio/trigger_consumer.h> 244eb3ccf1SLars-Peter Clausen #include <linux/iio/triggered_buffer.h> 254eb3ccf1SLars-Peter Clausen 264eb3ccf1SLars-Peter Clausen #include <linux/platform_data/ad7887.h> 274eb3ccf1SLars-Peter Clausen 2809a1737eSPeter Meerwald #define AD7887_REF_DIS BIT(5) /* on-chip reference disable */ 2909a1737eSPeter Meerwald #define AD7887_DUAL BIT(4) /* dual-channel mode */ 3009a1737eSPeter Meerwald #define AD7887_CH_AIN1 BIT(3) /* convert on channel 1, DUAL=1 */ 3109a1737eSPeter Meerwald #define AD7887_CH_AIN0 0 /* convert on channel 0, DUAL=0,1 */ 3209a1737eSPeter Meerwald #define AD7887_PM_MODE1 0 /* CS based shutdown */ 3309a1737eSPeter Meerwald #define AD7887_PM_MODE2 1 /* full on */ 3409a1737eSPeter Meerwald #define AD7887_PM_MODE3 2 /* auto shutdown after conversion */ 3509a1737eSPeter Meerwald #define AD7887_PM_MODE4 3 /* standby mode */ 364eb3ccf1SLars-Peter Clausen 374eb3ccf1SLars-Peter Clausen enum ad7887_channels { 384eb3ccf1SLars-Peter Clausen AD7887_CH0, 394eb3ccf1SLars-Peter Clausen AD7887_CH0_CH1, 404eb3ccf1SLars-Peter Clausen AD7887_CH1, 414eb3ccf1SLars-Peter Clausen }; 424eb3ccf1SLars-Peter Clausen 434eb3ccf1SLars-Peter Clausen /** 444eb3ccf1SLars-Peter Clausen * struct ad7887_chip_info - chip specifc information 454eb3ccf1SLars-Peter Clausen * @int_vref_mv: the internal reference voltage 46*b0ec7a44SBeniamin Bia * @channels: channels specification 47*b0ec7a44SBeniamin Bia * @num_channels: number of channels 48*b0ec7a44SBeniamin Bia * @dual_channels: channels specification in dual mode 49*b0ec7a44SBeniamin Bia * @num_dual_channels: number of channels in dual mode 504eb3ccf1SLars-Peter Clausen */ 514eb3ccf1SLars-Peter Clausen struct ad7887_chip_info { 524eb3ccf1SLars-Peter Clausen u16 int_vref_mv; 53*b0ec7a44SBeniamin Bia const struct iio_chan_spec *channels; 54*b0ec7a44SBeniamin Bia unsigned int num_channels; 55*b0ec7a44SBeniamin Bia const struct iio_chan_spec *dual_channels; 56*b0ec7a44SBeniamin Bia unsigned int num_dual_channels; 574eb3ccf1SLars-Peter Clausen }; 584eb3ccf1SLars-Peter Clausen 594eb3ccf1SLars-Peter Clausen struct ad7887_state { 604eb3ccf1SLars-Peter Clausen struct spi_device *spi; 614eb3ccf1SLars-Peter Clausen const struct ad7887_chip_info *chip_info; 624eb3ccf1SLars-Peter Clausen struct regulator *reg; 634eb3ccf1SLars-Peter Clausen struct spi_transfer xfer[4]; 644eb3ccf1SLars-Peter Clausen struct spi_message msg[3]; 654eb3ccf1SLars-Peter Clausen struct spi_message *ring_msg; 664eb3ccf1SLars-Peter Clausen unsigned char tx_cmd_buf[4]; 674eb3ccf1SLars-Peter Clausen 684eb3ccf1SLars-Peter Clausen /* 694eb3ccf1SLars-Peter Clausen * DMA (thus cache coherency maintenance) requires the 704eb3ccf1SLars-Peter Clausen * transfer buffers to live in their own cache lines. 714eb3ccf1SLars-Peter Clausen * Buffer needs to be large enough to hold two 16 bit samples and a 724eb3ccf1SLars-Peter Clausen * 64 bit aligned 64 bit timestamp. 734eb3ccf1SLars-Peter Clausen */ 744eb3ccf1SLars-Peter Clausen unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)] 754eb3ccf1SLars-Peter Clausen ____cacheline_aligned; 764eb3ccf1SLars-Peter Clausen }; 774eb3ccf1SLars-Peter Clausen 784eb3ccf1SLars-Peter Clausen enum ad7887_supported_device_ids { 794eb3ccf1SLars-Peter Clausen ID_AD7887 804eb3ccf1SLars-Peter Clausen }; 814eb3ccf1SLars-Peter Clausen 824eb3ccf1SLars-Peter Clausen static int ad7887_ring_preenable(struct iio_dev *indio_dev) 834eb3ccf1SLars-Peter Clausen { 844eb3ccf1SLars-Peter Clausen struct ad7887_state *st = iio_priv(indio_dev); 854eb3ccf1SLars-Peter Clausen 864eb3ccf1SLars-Peter Clausen /* We know this is a single long so can 'cheat' */ 874eb3ccf1SLars-Peter Clausen switch (*indio_dev->active_scan_mask) { 884eb3ccf1SLars-Peter Clausen case (1 << 0): 894eb3ccf1SLars-Peter Clausen st->ring_msg = &st->msg[AD7887_CH0]; 904eb3ccf1SLars-Peter Clausen break; 914eb3ccf1SLars-Peter Clausen case (1 << 1): 924eb3ccf1SLars-Peter Clausen st->ring_msg = &st->msg[AD7887_CH1]; 934eb3ccf1SLars-Peter Clausen /* Dummy read: push CH1 setting down to hardware */ 944eb3ccf1SLars-Peter Clausen spi_sync(st->spi, st->ring_msg); 954eb3ccf1SLars-Peter Clausen break; 964eb3ccf1SLars-Peter Clausen case ((1 << 1) | (1 << 0)): 974eb3ccf1SLars-Peter Clausen st->ring_msg = &st->msg[AD7887_CH0_CH1]; 984eb3ccf1SLars-Peter Clausen break; 994eb3ccf1SLars-Peter Clausen } 1004eb3ccf1SLars-Peter Clausen 1014eb3ccf1SLars-Peter Clausen return 0; 1024eb3ccf1SLars-Peter Clausen } 1034eb3ccf1SLars-Peter Clausen 1044eb3ccf1SLars-Peter Clausen static int ad7887_ring_postdisable(struct iio_dev *indio_dev) 1054eb3ccf1SLars-Peter Clausen { 1064eb3ccf1SLars-Peter Clausen struct ad7887_state *st = iio_priv(indio_dev); 1074eb3ccf1SLars-Peter Clausen 1084eb3ccf1SLars-Peter Clausen /* dummy read: restore default CH0 settin */ 1094eb3ccf1SLars-Peter Clausen return spi_sync(st->spi, &st->msg[AD7887_CH0]); 1104eb3ccf1SLars-Peter Clausen } 1114eb3ccf1SLars-Peter Clausen 1124eb3ccf1SLars-Peter Clausen /** 1134eb3ccf1SLars-Peter Clausen * ad7887_trigger_handler() bh of trigger launched polling to ring buffer 1144eb3ccf1SLars-Peter Clausen * 1154eb3ccf1SLars-Peter Clausen * Currently there is no option in this driver to disable the saving of 1164eb3ccf1SLars-Peter Clausen * timestamps within the ring. 1174eb3ccf1SLars-Peter Clausen **/ 1184eb3ccf1SLars-Peter Clausen static irqreturn_t ad7887_trigger_handler(int irq, void *p) 1194eb3ccf1SLars-Peter Clausen { 1204eb3ccf1SLars-Peter Clausen struct iio_poll_func *pf = p; 1214eb3ccf1SLars-Peter Clausen struct iio_dev *indio_dev = pf->indio_dev; 1224eb3ccf1SLars-Peter Clausen struct ad7887_state *st = iio_priv(indio_dev); 1234eb3ccf1SLars-Peter Clausen int b_sent; 1244eb3ccf1SLars-Peter Clausen 1254eb3ccf1SLars-Peter Clausen b_sent = spi_sync(st->spi, st->ring_msg); 1264eb3ccf1SLars-Peter Clausen if (b_sent) 1274eb3ccf1SLars-Peter Clausen goto done; 1284eb3ccf1SLars-Peter Clausen 1295afd602bSLars-Peter Clausen iio_push_to_buffers_with_timestamp(indio_dev, st->data, 130bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev)); 1314eb3ccf1SLars-Peter Clausen done: 1324eb3ccf1SLars-Peter Clausen iio_trigger_notify_done(indio_dev->trig); 1334eb3ccf1SLars-Peter Clausen 1344eb3ccf1SLars-Peter Clausen return IRQ_HANDLED; 1354eb3ccf1SLars-Peter Clausen } 1364eb3ccf1SLars-Peter Clausen 1374eb3ccf1SLars-Peter Clausen static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { 1384eb3ccf1SLars-Peter Clausen .preenable = &ad7887_ring_preenable, 1394eb3ccf1SLars-Peter Clausen .postenable = &iio_triggered_buffer_postenable, 1404eb3ccf1SLars-Peter Clausen .predisable = &iio_triggered_buffer_predisable, 1414eb3ccf1SLars-Peter Clausen .postdisable = &ad7887_ring_postdisable, 1424eb3ccf1SLars-Peter Clausen }; 1434eb3ccf1SLars-Peter Clausen 1444eb3ccf1SLars-Peter Clausen static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch) 1454eb3ccf1SLars-Peter Clausen { 1464eb3ccf1SLars-Peter Clausen int ret = spi_sync(st->spi, &st->msg[ch]); 1474eb3ccf1SLars-Peter Clausen if (ret) 1484eb3ccf1SLars-Peter Clausen return ret; 1494eb3ccf1SLars-Peter Clausen 1504eb3ccf1SLars-Peter Clausen return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1]; 1514eb3ccf1SLars-Peter Clausen } 1524eb3ccf1SLars-Peter Clausen 1534eb3ccf1SLars-Peter Clausen static int ad7887_read_raw(struct iio_dev *indio_dev, 1544eb3ccf1SLars-Peter Clausen struct iio_chan_spec const *chan, 1554eb3ccf1SLars-Peter Clausen int *val, 1564eb3ccf1SLars-Peter Clausen int *val2, 1574eb3ccf1SLars-Peter Clausen long m) 1584eb3ccf1SLars-Peter Clausen { 1594eb3ccf1SLars-Peter Clausen int ret; 1604eb3ccf1SLars-Peter Clausen struct ad7887_state *st = iio_priv(indio_dev); 1614eb3ccf1SLars-Peter Clausen 1624eb3ccf1SLars-Peter Clausen switch (m) { 1634eb3ccf1SLars-Peter Clausen case IIO_CHAN_INFO_RAW: 1646fea8a42SAlison Schofield ret = iio_device_claim_direct_mode(indio_dev); 1656fea8a42SAlison Schofield if (ret) 1666fea8a42SAlison Schofield return ret; 1674eb3ccf1SLars-Peter Clausen ret = ad7887_scan_direct(st, chan->address); 1686fea8a42SAlison Schofield iio_device_release_direct_mode(indio_dev); 1694eb3ccf1SLars-Peter Clausen 1704eb3ccf1SLars-Peter Clausen if (ret < 0) 1714eb3ccf1SLars-Peter Clausen return ret; 1724eb3ccf1SLars-Peter Clausen *val = ret >> chan->scan_type.shift; 17309a1737eSPeter Meerwald *val &= GENMASK(chan->scan_type.realbits - 1, 0); 1744eb3ccf1SLars-Peter Clausen return IIO_VAL_INT; 1754eb3ccf1SLars-Peter Clausen case IIO_CHAN_INFO_SCALE: 1764eb3ccf1SLars-Peter Clausen if (st->reg) { 1774eb3ccf1SLars-Peter Clausen *val = regulator_get_voltage(st->reg); 1784eb3ccf1SLars-Peter Clausen if (*val < 0) 1794eb3ccf1SLars-Peter Clausen return *val; 1804eb3ccf1SLars-Peter Clausen *val /= 1000; 1814eb3ccf1SLars-Peter Clausen } else { 1824eb3ccf1SLars-Peter Clausen *val = st->chip_info->int_vref_mv; 1834eb3ccf1SLars-Peter Clausen } 1844eb3ccf1SLars-Peter Clausen 1854eb3ccf1SLars-Peter Clausen *val2 = chan->scan_type.realbits; 1864eb3ccf1SLars-Peter Clausen 1874eb3ccf1SLars-Peter Clausen return IIO_VAL_FRACTIONAL_LOG2; 1884eb3ccf1SLars-Peter Clausen } 1894eb3ccf1SLars-Peter Clausen return -EINVAL; 1904eb3ccf1SLars-Peter Clausen } 1914eb3ccf1SLars-Peter Clausen 192*b0ec7a44SBeniamin Bia #define AD7887_CHANNEL(x) { \ 193*b0ec7a44SBeniamin Bia .type = IIO_VOLTAGE, \ 194*b0ec7a44SBeniamin Bia .indexed = 1, \ 195*b0ec7a44SBeniamin Bia .channel = (x), \ 196*b0ec7a44SBeniamin Bia .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 197*b0ec7a44SBeniamin Bia .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 198*b0ec7a44SBeniamin Bia .address = (x), \ 199*b0ec7a44SBeniamin Bia .scan_index = (x), \ 200*b0ec7a44SBeniamin Bia .scan_type = { \ 201*b0ec7a44SBeniamin Bia .sign = 'u', \ 202*b0ec7a44SBeniamin Bia .realbits = 12, \ 203*b0ec7a44SBeniamin Bia .storagebits = 16, \ 204*b0ec7a44SBeniamin Bia .shift = 0, \ 205*b0ec7a44SBeniamin Bia .endianness = IIO_BE, \ 206*b0ec7a44SBeniamin Bia }, \ 207*b0ec7a44SBeniamin Bia } 208*b0ec7a44SBeniamin Bia 209*b0ec7a44SBeniamin Bia static const struct iio_chan_spec ad7887_channels[] = { 210*b0ec7a44SBeniamin Bia AD7887_CHANNEL(0), 211*b0ec7a44SBeniamin Bia IIO_CHAN_SOFT_TIMESTAMP(1), 212*b0ec7a44SBeniamin Bia }; 213*b0ec7a44SBeniamin Bia 214*b0ec7a44SBeniamin Bia static const struct iio_chan_spec ad7887_dual_channels[] = { 215*b0ec7a44SBeniamin Bia AD7887_CHANNEL(0), 216*b0ec7a44SBeniamin Bia AD7887_CHANNEL(1), 217*b0ec7a44SBeniamin Bia IIO_CHAN_SOFT_TIMESTAMP(2), 218*b0ec7a44SBeniamin Bia }; 2194eb3ccf1SLars-Peter Clausen 2204eb3ccf1SLars-Peter Clausen static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { 2214eb3ccf1SLars-Peter Clausen /* 2224eb3ccf1SLars-Peter Clausen * More devices added in future 2234eb3ccf1SLars-Peter Clausen */ 2244eb3ccf1SLars-Peter Clausen [ID_AD7887] = { 225*b0ec7a44SBeniamin Bia .channels = ad7887_channels, 226*b0ec7a44SBeniamin Bia .num_channels = ARRAY_SIZE(ad7887_channels), 227*b0ec7a44SBeniamin Bia .dual_channels = ad7887_dual_channels, 228*b0ec7a44SBeniamin Bia .num_dual_channels = ARRAY_SIZE(ad7887_dual_channels), 2294eb3ccf1SLars-Peter Clausen .int_vref_mv = 2500, 2304eb3ccf1SLars-Peter Clausen }, 2314eb3ccf1SLars-Peter Clausen }; 2324eb3ccf1SLars-Peter Clausen 2334eb3ccf1SLars-Peter Clausen static const struct iio_info ad7887_info = { 2344eb3ccf1SLars-Peter Clausen .read_raw = &ad7887_read_raw, 2354eb3ccf1SLars-Peter Clausen }; 2364eb3ccf1SLars-Peter Clausen 237fc52692cSGreg Kroah-Hartman static int ad7887_probe(struct spi_device *spi) 2384eb3ccf1SLars-Peter Clausen { 2394eb3ccf1SLars-Peter Clausen struct ad7887_platform_data *pdata = spi->dev.platform_data; 2404eb3ccf1SLars-Peter Clausen struct ad7887_state *st; 24182429e0dSSachin Kamat struct iio_dev *indio_dev; 2424eb3ccf1SLars-Peter Clausen uint8_t mode; 2434eb3ccf1SLars-Peter Clausen int ret; 2444eb3ccf1SLars-Peter Clausen 24582429e0dSSachin Kamat indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 2464eb3ccf1SLars-Peter Clausen if (indio_dev == NULL) 2474eb3ccf1SLars-Peter Clausen return -ENOMEM; 2484eb3ccf1SLars-Peter Clausen 2494eb3ccf1SLars-Peter Clausen st = iio_priv(indio_dev); 2504eb3ccf1SLars-Peter Clausen 2514eb3ccf1SLars-Peter Clausen if (!pdata || !pdata->use_onchip_ref) { 25282429e0dSSachin Kamat st->reg = devm_regulator_get(&spi->dev, "vref"); 25382429e0dSSachin Kamat if (IS_ERR(st->reg)) 25482429e0dSSachin Kamat return PTR_ERR(st->reg); 2554eb3ccf1SLars-Peter Clausen 2564eb3ccf1SLars-Peter Clausen ret = regulator_enable(st->reg); 2574eb3ccf1SLars-Peter Clausen if (ret) 25882429e0dSSachin Kamat return ret; 2594eb3ccf1SLars-Peter Clausen } 2604eb3ccf1SLars-Peter Clausen 2614eb3ccf1SLars-Peter Clausen st->chip_info = 2624eb3ccf1SLars-Peter Clausen &ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data]; 2634eb3ccf1SLars-Peter Clausen 2644eb3ccf1SLars-Peter Clausen spi_set_drvdata(spi, indio_dev); 2654eb3ccf1SLars-Peter Clausen st->spi = spi; 2664eb3ccf1SLars-Peter Clausen 2674eb3ccf1SLars-Peter Clausen /* Estabilish that the iio_dev is a child of the spi device */ 2684eb3ccf1SLars-Peter Clausen indio_dev->dev.parent = &spi->dev; 269b541eaffSMatt Ranostay indio_dev->dev.of_node = spi->dev.of_node; 2704eb3ccf1SLars-Peter Clausen indio_dev->name = spi_get_device_id(spi)->name; 2714eb3ccf1SLars-Peter Clausen indio_dev->info = &ad7887_info; 2724eb3ccf1SLars-Peter Clausen indio_dev->modes = INDIO_DIRECT_MODE; 2734eb3ccf1SLars-Peter Clausen 2744eb3ccf1SLars-Peter Clausen /* Setup default message */ 2754eb3ccf1SLars-Peter Clausen 2764eb3ccf1SLars-Peter Clausen mode = AD7887_PM_MODE4; 2774eb3ccf1SLars-Peter Clausen if (!pdata || !pdata->use_onchip_ref) 2784eb3ccf1SLars-Peter Clausen mode |= AD7887_REF_DIS; 2794eb3ccf1SLars-Peter Clausen if (pdata && pdata->en_dual) 2804eb3ccf1SLars-Peter Clausen mode |= AD7887_DUAL; 2814eb3ccf1SLars-Peter Clausen 2824eb3ccf1SLars-Peter Clausen st->tx_cmd_buf[0] = AD7887_CH_AIN0 | mode; 2834eb3ccf1SLars-Peter Clausen 2844eb3ccf1SLars-Peter Clausen st->xfer[0].rx_buf = &st->data[0]; 2854eb3ccf1SLars-Peter Clausen st->xfer[0].tx_buf = &st->tx_cmd_buf[0]; 2864eb3ccf1SLars-Peter Clausen st->xfer[0].len = 2; 2874eb3ccf1SLars-Peter Clausen 2884eb3ccf1SLars-Peter Clausen spi_message_init(&st->msg[AD7887_CH0]); 2894eb3ccf1SLars-Peter Clausen spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]); 2904eb3ccf1SLars-Peter Clausen 2914eb3ccf1SLars-Peter Clausen if (pdata && pdata->en_dual) { 2924eb3ccf1SLars-Peter Clausen st->tx_cmd_buf[2] = AD7887_CH_AIN1 | mode; 2934eb3ccf1SLars-Peter Clausen 2944eb3ccf1SLars-Peter Clausen st->xfer[1].rx_buf = &st->data[0]; 2954eb3ccf1SLars-Peter Clausen st->xfer[1].tx_buf = &st->tx_cmd_buf[2]; 2964eb3ccf1SLars-Peter Clausen st->xfer[1].len = 2; 2974eb3ccf1SLars-Peter Clausen 2984eb3ccf1SLars-Peter Clausen st->xfer[2].rx_buf = &st->data[2]; 2994eb3ccf1SLars-Peter Clausen st->xfer[2].tx_buf = &st->tx_cmd_buf[0]; 3004eb3ccf1SLars-Peter Clausen st->xfer[2].len = 2; 3014eb3ccf1SLars-Peter Clausen 3024eb3ccf1SLars-Peter Clausen spi_message_init(&st->msg[AD7887_CH0_CH1]); 3034eb3ccf1SLars-Peter Clausen spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]); 3044eb3ccf1SLars-Peter Clausen spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]); 3054eb3ccf1SLars-Peter Clausen 3064eb3ccf1SLars-Peter Clausen st->xfer[3].rx_buf = &st->data[2]; 3074eb3ccf1SLars-Peter Clausen st->xfer[3].tx_buf = &st->tx_cmd_buf[2]; 3084eb3ccf1SLars-Peter Clausen st->xfer[3].len = 2; 3094eb3ccf1SLars-Peter Clausen 3104eb3ccf1SLars-Peter Clausen spi_message_init(&st->msg[AD7887_CH1]); 3114eb3ccf1SLars-Peter Clausen spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); 3124eb3ccf1SLars-Peter Clausen 313*b0ec7a44SBeniamin Bia indio_dev->channels = st->chip_info->dual_channels; 314*b0ec7a44SBeniamin Bia indio_dev->num_channels = st->chip_info->num_dual_channels; 3154eb3ccf1SLars-Peter Clausen } else { 316*b0ec7a44SBeniamin Bia indio_dev->channels = st->chip_info->channels; 317*b0ec7a44SBeniamin Bia indio_dev->num_channels = st->chip_info->num_channels; 3184eb3ccf1SLars-Peter Clausen } 3194eb3ccf1SLars-Peter Clausen 3204eb3ccf1SLars-Peter Clausen ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, 3214eb3ccf1SLars-Peter Clausen &ad7887_trigger_handler, &ad7887_ring_setup_ops); 3224eb3ccf1SLars-Peter Clausen if (ret) 3234eb3ccf1SLars-Peter Clausen goto error_disable_reg; 3244eb3ccf1SLars-Peter Clausen 3254eb3ccf1SLars-Peter Clausen ret = iio_device_register(indio_dev); 3264eb3ccf1SLars-Peter Clausen if (ret) 3274eb3ccf1SLars-Peter Clausen goto error_unregister_ring; 3284eb3ccf1SLars-Peter Clausen 3294eb3ccf1SLars-Peter Clausen return 0; 3304eb3ccf1SLars-Peter Clausen error_unregister_ring: 3314eb3ccf1SLars-Peter Clausen iio_triggered_buffer_cleanup(indio_dev); 3324eb3ccf1SLars-Peter Clausen error_disable_reg: 3334eb3ccf1SLars-Peter Clausen if (st->reg) 3344eb3ccf1SLars-Peter Clausen regulator_disable(st->reg); 3354eb3ccf1SLars-Peter Clausen 3364eb3ccf1SLars-Peter Clausen return ret; 3374eb3ccf1SLars-Peter Clausen } 3384eb3ccf1SLars-Peter Clausen 339fc52692cSGreg Kroah-Hartman static int ad7887_remove(struct spi_device *spi) 3404eb3ccf1SLars-Peter Clausen { 3414eb3ccf1SLars-Peter Clausen struct iio_dev *indio_dev = spi_get_drvdata(spi); 3424eb3ccf1SLars-Peter Clausen struct ad7887_state *st = iio_priv(indio_dev); 3434eb3ccf1SLars-Peter Clausen 3444eb3ccf1SLars-Peter Clausen iio_device_unregister(indio_dev); 3454eb3ccf1SLars-Peter Clausen iio_triggered_buffer_cleanup(indio_dev); 34682429e0dSSachin Kamat if (st->reg) 3474eb3ccf1SLars-Peter Clausen regulator_disable(st->reg); 3484eb3ccf1SLars-Peter Clausen 3494eb3ccf1SLars-Peter Clausen return 0; 3504eb3ccf1SLars-Peter Clausen } 3514eb3ccf1SLars-Peter Clausen 3524eb3ccf1SLars-Peter Clausen static const struct spi_device_id ad7887_id[] = { 3534eb3ccf1SLars-Peter Clausen {"ad7887", ID_AD7887}, 3544eb3ccf1SLars-Peter Clausen {} 3554eb3ccf1SLars-Peter Clausen }; 3564eb3ccf1SLars-Peter Clausen MODULE_DEVICE_TABLE(spi, ad7887_id); 3574eb3ccf1SLars-Peter Clausen 3584eb3ccf1SLars-Peter Clausen static struct spi_driver ad7887_driver = { 3594eb3ccf1SLars-Peter Clausen .driver = { 3604eb3ccf1SLars-Peter Clausen .name = "ad7887", 3614eb3ccf1SLars-Peter Clausen }, 3624eb3ccf1SLars-Peter Clausen .probe = ad7887_probe, 363fc52692cSGreg Kroah-Hartman .remove = ad7887_remove, 3644eb3ccf1SLars-Peter Clausen .id_table = ad7887_id, 3654eb3ccf1SLars-Peter Clausen }; 3664eb3ccf1SLars-Peter Clausen module_spi_driver(ad7887_driver); 3674eb3ccf1SLars-Peter Clausen 3689920ed25SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 3694eb3ccf1SLars-Peter Clausen MODULE_DESCRIPTION("Analog Devices AD7887 ADC"); 3704eb3ccf1SLars-Peter Clausen MODULE_LICENSE("GPL v2"); 371