17d7209f0SDavid Lechner // SPDX-License-Identifier: GPL-2.0 2902c4b24SDavid Lechner /* 3902c4b24SDavid Lechner * Texas Instruments ADS7950 SPI ADC driver 4902c4b24SDavid Lechner * 5902c4b24SDavid Lechner * Copyright 2016 David Lechner <david@lechnology.com> 6902c4b24SDavid Lechner * 7902c4b24SDavid Lechner * Based on iio/ad7923.c: 8902c4b24SDavid Lechner * Copyright 2011 Analog Devices Inc 9902c4b24SDavid Lechner * Copyright 2012 CS Systemes d'Information 10902c4b24SDavid Lechner * 11902c4b24SDavid Lechner * And also on hwmon/ads79xx.c 12902c4b24SDavid Lechner * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ 13902c4b24SDavid Lechner * Nishanth Menon 14902c4b24SDavid Lechner */ 15902c4b24SDavid Lechner 168cfa26a7SAndy Shevchenko #include <linux/acpi.h> 17902c4b24SDavid Lechner #include <linux/bitops.h> 18902c4b24SDavid Lechner #include <linux/device.h> 19902c4b24SDavid Lechner #include <linux/err.h> 20902c4b24SDavid Lechner #include <linux/interrupt.h> 21902c4b24SDavid Lechner #include <linux/kernel.h> 22902c4b24SDavid Lechner #include <linux/module.h> 23902c4b24SDavid Lechner #include <linux/regulator/consumer.h> 24902c4b24SDavid Lechner #include <linux/slab.h> 25902c4b24SDavid Lechner #include <linux/spi/spi.h> 26902c4b24SDavid Lechner 27902c4b24SDavid Lechner #include <linux/iio/buffer.h> 28902c4b24SDavid Lechner #include <linux/iio/iio.h> 29902c4b24SDavid Lechner #include <linux/iio/sysfs.h> 30902c4b24SDavid Lechner #include <linux/iio/trigger_consumer.h> 31902c4b24SDavid Lechner #include <linux/iio/triggered_buffer.h> 32902c4b24SDavid Lechner 338cfa26a7SAndy Shevchenko /* 348cfa26a7SAndy Shevchenko * In case of ACPI, we use the 5000 mV as default for the reference pin. 358cfa26a7SAndy Shevchenko * Device tree users encode that via the vref-supply regulator. 368cfa26a7SAndy Shevchenko */ 378cfa26a7SAndy Shevchenko #define TI_ADS7950_VA_MV_ACPI_DEFAULT 5000 388cfa26a7SAndy Shevchenko 39902c4b24SDavid Lechner #define TI_ADS7950_CR_MANUAL BIT(12) 40902c4b24SDavid Lechner #define TI_ADS7950_CR_WRITE BIT(11) 41902c4b24SDavid Lechner #define TI_ADS7950_CR_CHAN(ch) ((ch) << 7) 42902c4b24SDavid Lechner #define TI_ADS7950_CR_RANGE_5V BIT(6) 43902c4b24SDavid Lechner 44902c4b24SDavid Lechner #define TI_ADS7950_MAX_CHAN 16 45902c4b24SDavid Lechner 46902c4b24SDavid Lechner #define TI_ADS7950_TIMESTAMP_SIZE (sizeof(int64_t) / sizeof(__be16)) 47902c4b24SDavid Lechner 48902c4b24SDavid Lechner /* val = value, dec = left shift, bits = number of bits of the mask */ 49902c4b24SDavid Lechner #define TI_ADS7950_EXTRACT(val, dec, bits) \ 50902c4b24SDavid Lechner (((val) >> (dec)) & ((1 << (bits)) - 1)) 51902c4b24SDavid Lechner 52902c4b24SDavid Lechner struct ti_ads7950_state { 53902c4b24SDavid Lechner struct spi_device *spi; 54902c4b24SDavid Lechner struct spi_transfer ring_xfer[TI_ADS7950_MAX_CHAN + 2]; 55902c4b24SDavid Lechner struct spi_transfer scan_single_xfer[3]; 56902c4b24SDavid Lechner struct spi_message ring_msg; 57902c4b24SDavid Lechner struct spi_message scan_single_msg; 58902c4b24SDavid Lechner 59902c4b24SDavid Lechner struct regulator *reg; 608cfa26a7SAndy Shevchenko unsigned int vref_mv; 61902c4b24SDavid Lechner 62902c4b24SDavid Lechner unsigned int settings; 63902c4b24SDavid Lechner 64902c4b24SDavid Lechner /* 65902c4b24SDavid Lechner * DMA (thus cache coherency maintenance) requires the 66902c4b24SDavid Lechner * transfer buffers to live in their own cache lines. 67902c4b24SDavid Lechner */ 68902c4b24SDavid Lechner __be16 rx_buf[TI_ADS7950_MAX_CHAN + TI_ADS7950_TIMESTAMP_SIZE] 69902c4b24SDavid Lechner ____cacheline_aligned; 70902c4b24SDavid Lechner __be16 tx_buf[TI_ADS7950_MAX_CHAN]; 71902c4b24SDavid Lechner }; 72902c4b24SDavid Lechner 73902c4b24SDavid Lechner struct ti_ads7950_chip_info { 74902c4b24SDavid Lechner const struct iio_chan_spec *channels; 75902c4b24SDavid Lechner unsigned int num_channels; 76902c4b24SDavid Lechner }; 77902c4b24SDavid Lechner 78902c4b24SDavid Lechner enum ti_ads7950_id { 79902c4b24SDavid Lechner TI_ADS7950, 80902c4b24SDavid Lechner TI_ADS7951, 81902c4b24SDavid Lechner TI_ADS7952, 82902c4b24SDavid Lechner TI_ADS7953, 83902c4b24SDavid Lechner TI_ADS7954, 84902c4b24SDavid Lechner TI_ADS7955, 85902c4b24SDavid Lechner TI_ADS7956, 86902c4b24SDavid Lechner TI_ADS7957, 87902c4b24SDavid Lechner TI_ADS7958, 88902c4b24SDavid Lechner TI_ADS7959, 89902c4b24SDavid Lechner TI_ADS7960, 90902c4b24SDavid Lechner TI_ADS7961, 91902c4b24SDavid Lechner }; 92902c4b24SDavid Lechner 93902c4b24SDavid Lechner #define TI_ADS7950_V_CHAN(index, bits) \ 94902c4b24SDavid Lechner { \ 95902c4b24SDavid Lechner .type = IIO_VOLTAGE, \ 96902c4b24SDavid Lechner .indexed = 1, \ 97902c4b24SDavid Lechner .channel = index, \ 98902c4b24SDavid Lechner .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 99902c4b24SDavid Lechner .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 100902c4b24SDavid Lechner .address = index, \ 101902c4b24SDavid Lechner .datasheet_name = "CH##index", \ 102902c4b24SDavid Lechner .scan_index = index, \ 103902c4b24SDavid Lechner .scan_type = { \ 104902c4b24SDavid Lechner .sign = 'u', \ 105902c4b24SDavid Lechner .realbits = bits, \ 106902c4b24SDavid Lechner .storagebits = 16, \ 107902c4b24SDavid Lechner .shift = 12 - (bits), \ 108902c4b24SDavid Lechner .endianness = IIO_BE, \ 109902c4b24SDavid Lechner }, \ 110902c4b24SDavid Lechner } 111902c4b24SDavid Lechner 112902c4b24SDavid Lechner #define DECLARE_TI_ADS7950_4_CHANNELS(name, bits) \ 113902c4b24SDavid Lechner const struct iio_chan_spec name ## _channels[] = { \ 114902c4b24SDavid Lechner TI_ADS7950_V_CHAN(0, bits), \ 115902c4b24SDavid Lechner TI_ADS7950_V_CHAN(1, bits), \ 116902c4b24SDavid Lechner TI_ADS7950_V_CHAN(2, bits), \ 117902c4b24SDavid Lechner TI_ADS7950_V_CHAN(3, bits), \ 118902c4b24SDavid Lechner IIO_CHAN_SOFT_TIMESTAMP(4), \ 119902c4b24SDavid Lechner } 120902c4b24SDavid Lechner 121902c4b24SDavid Lechner #define DECLARE_TI_ADS7950_8_CHANNELS(name, bits) \ 122902c4b24SDavid Lechner const struct iio_chan_spec name ## _channels[] = { \ 123902c4b24SDavid Lechner TI_ADS7950_V_CHAN(0, bits), \ 124902c4b24SDavid Lechner TI_ADS7950_V_CHAN(1, bits), \ 125902c4b24SDavid Lechner TI_ADS7950_V_CHAN(2, bits), \ 126902c4b24SDavid Lechner TI_ADS7950_V_CHAN(3, bits), \ 127902c4b24SDavid Lechner TI_ADS7950_V_CHAN(4, bits), \ 128902c4b24SDavid Lechner TI_ADS7950_V_CHAN(5, bits), \ 129902c4b24SDavid Lechner TI_ADS7950_V_CHAN(6, bits), \ 130902c4b24SDavid Lechner TI_ADS7950_V_CHAN(7, bits), \ 131902c4b24SDavid Lechner IIO_CHAN_SOFT_TIMESTAMP(8), \ 132902c4b24SDavid Lechner } 133902c4b24SDavid Lechner 134902c4b24SDavid Lechner #define DECLARE_TI_ADS7950_12_CHANNELS(name, bits) \ 135902c4b24SDavid Lechner const struct iio_chan_spec name ## _channels[] = { \ 136902c4b24SDavid Lechner TI_ADS7950_V_CHAN(0, bits), \ 137902c4b24SDavid Lechner TI_ADS7950_V_CHAN(1, bits), \ 138902c4b24SDavid Lechner TI_ADS7950_V_CHAN(2, bits), \ 139902c4b24SDavid Lechner TI_ADS7950_V_CHAN(3, bits), \ 140902c4b24SDavid Lechner TI_ADS7950_V_CHAN(4, bits), \ 141902c4b24SDavid Lechner TI_ADS7950_V_CHAN(5, bits), \ 142902c4b24SDavid Lechner TI_ADS7950_V_CHAN(6, bits), \ 143902c4b24SDavid Lechner TI_ADS7950_V_CHAN(7, bits), \ 144902c4b24SDavid Lechner TI_ADS7950_V_CHAN(8, bits), \ 145902c4b24SDavid Lechner TI_ADS7950_V_CHAN(9, bits), \ 146902c4b24SDavid Lechner TI_ADS7950_V_CHAN(10, bits), \ 147902c4b24SDavid Lechner TI_ADS7950_V_CHAN(11, bits), \ 148902c4b24SDavid Lechner IIO_CHAN_SOFT_TIMESTAMP(12), \ 149902c4b24SDavid Lechner } 150902c4b24SDavid Lechner 151902c4b24SDavid Lechner #define DECLARE_TI_ADS7950_16_CHANNELS(name, bits) \ 152902c4b24SDavid Lechner const struct iio_chan_spec name ## _channels[] = { \ 153902c4b24SDavid Lechner TI_ADS7950_V_CHAN(0, bits), \ 154902c4b24SDavid Lechner TI_ADS7950_V_CHAN(1, bits), \ 155902c4b24SDavid Lechner TI_ADS7950_V_CHAN(2, bits), \ 156902c4b24SDavid Lechner TI_ADS7950_V_CHAN(3, bits), \ 157902c4b24SDavid Lechner TI_ADS7950_V_CHAN(4, bits), \ 158902c4b24SDavid Lechner TI_ADS7950_V_CHAN(5, bits), \ 159902c4b24SDavid Lechner TI_ADS7950_V_CHAN(6, bits), \ 160902c4b24SDavid Lechner TI_ADS7950_V_CHAN(7, bits), \ 161902c4b24SDavid Lechner TI_ADS7950_V_CHAN(8, bits), \ 162902c4b24SDavid Lechner TI_ADS7950_V_CHAN(9, bits), \ 163902c4b24SDavid Lechner TI_ADS7950_V_CHAN(10, bits), \ 164902c4b24SDavid Lechner TI_ADS7950_V_CHAN(11, bits), \ 165902c4b24SDavid Lechner TI_ADS7950_V_CHAN(12, bits), \ 166902c4b24SDavid Lechner TI_ADS7950_V_CHAN(13, bits), \ 167902c4b24SDavid Lechner TI_ADS7950_V_CHAN(14, bits), \ 168902c4b24SDavid Lechner TI_ADS7950_V_CHAN(15, bits), \ 169902c4b24SDavid Lechner IIO_CHAN_SOFT_TIMESTAMP(16), \ 170902c4b24SDavid Lechner } 171902c4b24SDavid Lechner 172902c4b24SDavid Lechner static DECLARE_TI_ADS7950_4_CHANNELS(ti_ads7950, 12); 173902c4b24SDavid Lechner static DECLARE_TI_ADS7950_8_CHANNELS(ti_ads7951, 12); 174902c4b24SDavid Lechner static DECLARE_TI_ADS7950_12_CHANNELS(ti_ads7952, 12); 175902c4b24SDavid Lechner static DECLARE_TI_ADS7950_16_CHANNELS(ti_ads7953, 12); 176902c4b24SDavid Lechner static DECLARE_TI_ADS7950_4_CHANNELS(ti_ads7954, 10); 177902c4b24SDavid Lechner static DECLARE_TI_ADS7950_8_CHANNELS(ti_ads7955, 10); 178902c4b24SDavid Lechner static DECLARE_TI_ADS7950_12_CHANNELS(ti_ads7956, 10); 179902c4b24SDavid Lechner static DECLARE_TI_ADS7950_16_CHANNELS(ti_ads7957, 10); 180902c4b24SDavid Lechner static DECLARE_TI_ADS7950_4_CHANNELS(ti_ads7958, 8); 181902c4b24SDavid Lechner static DECLARE_TI_ADS7950_8_CHANNELS(ti_ads7959, 8); 182902c4b24SDavid Lechner static DECLARE_TI_ADS7950_12_CHANNELS(ti_ads7960, 8); 183902c4b24SDavid Lechner static DECLARE_TI_ADS7950_16_CHANNELS(ti_ads7961, 8); 184902c4b24SDavid Lechner 185902c4b24SDavid Lechner static const struct ti_ads7950_chip_info ti_ads7950_chip_info[] = { 186902c4b24SDavid Lechner [TI_ADS7950] = { 187902c4b24SDavid Lechner .channels = ti_ads7950_channels, 188902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7950_channels), 189902c4b24SDavid Lechner }, 190902c4b24SDavid Lechner [TI_ADS7951] = { 191902c4b24SDavid Lechner .channels = ti_ads7951_channels, 192902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7951_channels), 193902c4b24SDavid Lechner }, 194902c4b24SDavid Lechner [TI_ADS7952] = { 195902c4b24SDavid Lechner .channels = ti_ads7952_channels, 196902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7952_channels), 197902c4b24SDavid Lechner }, 198902c4b24SDavid Lechner [TI_ADS7953] = { 199902c4b24SDavid Lechner .channels = ti_ads7953_channels, 200902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7953_channels), 201902c4b24SDavid Lechner }, 202902c4b24SDavid Lechner [TI_ADS7954] = { 203902c4b24SDavid Lechner .channels = ti_ads7954_channels, 204902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7954_channels), 205902c4b24SDavid Lechner }, 206902c4b24SDavid Lechner [TI_ADS7955] = { 207902c4b24SDavid Lechner .channels = ti_ads7955_channels, 208902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7955_channels), 209902c4b24SDavid Lechner }, 210902c4b24SDavid Lechner [TI_ADS7956] = { 211902c4b24SDavid Lechner .channels = ti_ads7956_channels, 212902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7956_channels), 213902c4b24SDavid Lechner }, 214902c4b24SDavid Lechner [TI_ADS7957] = { 215902c4b24SDavid Lechner .channels = ti_ads7957_channels, 216902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7957_channels), 217902c4b24SDavid Lechner }, 218902c4b24SDavid Lechner [TI_ADS7958] = { 219902c4b24SDavid Lechner .channels = ti_ads7958_channels, 220902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7958_channels), 221902c4b24SDavid Lechner }, 222902c4b24SDavid Lechner [TI_ADS7959] = { 223902c4b24SDavid Lechner .channels = ti_ads7959_channels, 224902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7959_channels), 225902c4b24SDavid Lechner }, 226902c4b24SDavid Lechner [TI_ADS7960] = { 227902c4b24SDavid Lechner .channels = ti_ads7960_channels, 228902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7960_channels), 229902c4b24SDavid Lechner }, 230902c4b24SDavid Lechner [TI_ADS7961] = { 231902c4b24SDavid Lechner .channels = ti_ads7961_channels, 232902c4b24SDavid Lechner .num_channels = ARRAY_SIZE(ti_ads7961_channels), 233902c4b24SDavid Lechner }, 234902c4b24SDavid Lechner }; 235902c4b24SDavid Lechner 236902c4b24SDavid Lechner /* 237902c4b24SDavid Lechner * ti_ads7950_update_scan_mode() setup the spi transfer buffer for the new 238902c4b24SDavid Lechner * scan mask 239902c4b24SDavid Lechner */ 240902c4b24SDavid Lechner static int ti_ads7950_update_scan_mode(struct iio_dev *indio_dev, 241902c4b24SDavid Lechner const unsigned long *active_scan_mask) 242902c4b24SDavid Lechner { 243902c4b24SDavid Lechner struct ti_ads7950_state *st = iio_priv(indio_dev); 244902c4b24SDavid Lechner int i, cmd, len; 245902c4b24SDavid Lechner 246902c4b24SDavid Lechner len = 0; 247902c4b24SDavid Lechner for_each_set_bit(i, active_scan_mask, indio_dev->num_channels) { 248902c4b24SDavid Lechner cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(i) | st->settings; 249902c4b24SDavid Lechner st->tx_buf[len++] = cpu_to_be16(cmd); 250902c4b24SDavid Lechner } 251902c4b24SDavid Lechner 252902c4b24SDavid Lechner /* Data for the 1st channel is not returned until the 3rd transfer */ 253902c4b24SDavid Lechner len += 2; 254902c4b24SDavid Lechner for (i = 0; i < len; i++) { 255902c4b24SDavid Lechner if ((i + 2) < len) 256902c4b24SDavid Lechner st->ring_xfer[i].tx_buf = &st->tx_buf[i]; 257902c4b24SDavid Lechner if (i >= 2) 258902c4b24SDavid Lechner st->ring_xfer[i].rx_buf = &st->rx_buf[i - 2]; 259902c4b24SDavid Lechner st->ring_xfer[i].len = 2; 260902c4b24SDavid Lechner st->ring_xfer[i].cs_change = 1; 261902c4b24SDavid Lechner } 262902c4b24SDavid Lechner /* make sure last transfer's cs_change is not set */ 263902c4b24SDavid Lechner st->ring_xfer[len - 1].cs_change = 0; 264902c4b24SDavid Lechner 265902c4b24SDavid Lechner spi_message_init_with_transfers(&st->ring_msg, st->ring_xfer, len); 266902c4b24SDavid Lechner 267902c4b24SDavid Lechner return 0; 268902c4b24SDavid Lechner } 269902c4b24SDavid Lechner 270902c4b24SDavid Lechner static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p) 271902c4b24SDavid Lechner { 272902c4b24SDavid Lechner struct iio_poll_func *pf = p; 273902c4b24SDavid Lechner struct iio_dev *indio_dev = pf->indio_dev; 274902c4b24SDavid Lechner struct ti_ads7950_state *st = iio_priv(indio_dev); 275902c4b24SDavid Lechner int ret; 276902c4b24SDavid Lechner 277902c4b24SDavid Lechner ret = spi_sync(st->spi, &st->ring_msg); 278902c4b24SDavid Lechner if (ret < 0) 279902c4b24SDavid Lechner goto out; 280902c4b24SDavid Lechner 281902c4b24SDavid Lechner iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, 282902c4b24SDavid Lechner iio_get_time_ns(indio_dev)); 283902c4b24SDavid Lechner 284902c4b24SDavid Lechner out: 285902c4b24SDavid Lechner iio_trigger_notify_done(indio_dev->trig); 286902c4b24SDavid Lechner 287902c4b24SDavid Lechner return IRQ_HANDLED; 288902c4b24SDavid Lechner } 289902c4b24SDavid Lechner 290902c4b24SDavid Lechner static int ti_ads7950_scan_direct(struct ti_ads7950_state *st, unsigned int ch) 291902c4b24SDavid Lechner { 292902c4b24SDavid Lechner int ret, cmd; 293902c4b24SDavid Lechner 294902c4b24SDavid Lechner cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(ch) | st->settings; 295902c4b24SDavid Lechner st->tx_buf[0] = cpu_to_be16(cmd); 296902c4b24SDavid Lechner 297902c4b24SDavid Lechner ret = spi_sync(st->spi, &st->scan_single_msg); 298902c4b24SDavid Lechner if (ret) 299902c4b24SDavid Lechner return ret; 300902c4b24SDavid Lechner 301902c4b24SDavid Lechner return be16_to_cpu(st->rx_buf[0]); 302902c4b24SDavid Lechner } 303902c4b24SDavid Lechner 304902c4b24SDavid Lechner static int ti_ads7950_get_range(struct ti_ads7950_state *st) 305902c4b24SDavid Lechner { 306902c4b24SDavid Lechner int vref; 307902c4b24SDavid Lechner 3088cfa26a7SAndy Shevchenko if (st->vref_mv) { 3098cfa26a7SAndy Shevchenko vref = st->vref_mv; 3108cfa26a7SAndy Shevchenko } else { 311902c4b24SDavid Lechner vref = regulator_get_voltage(st->reg); 312902c4b24SDavid Lechner if (vref < 0) 313902c4b24SDavid Lechner return vref; 314902c4b24SDavid Lechner 315902c4b24SDavid Lechner vref /= 1000; 3168cfa26a7SAndy Shevchenko } 317902c4b24SDavid Lechner 318902c4b24SDavid Lechner if (st->settings & TI_ADS7950_CR_RANGE_5V) 319902c4b24SDavid Lechner vref *= 2; 320902c4b24SDavid Lechner 321902c4b24SDavid Lechner return vref; 322902c4b24SDavid Lechner } 323902c4b24SDavid Lechner 324902c4b24SDavid Lechner static int ti_ads7950_read_raw(struct iio_dev *indio_dev, 325902c4b24SDavid Lechner struct iio_chan_spec const *chan, 326902c4b24SDavid Lechner int *val, int *val2, long m) 327902c4b24SDavid Lechner { 328902c4b24SDavid Lechner struct ti_ads7950_state *st = iio_priv(indio_dev); 329902c4b24SDavid Lechner int ret; 330902c4b24SDavid Lechner 331902c4b24SDavid Lechner switch (m) { 332902c4b24SDavid Lechner case IIO_CHAN_INFO_RAW: 333902c4b24SDavid Lechner 334902c4b24SDavid Lechner ret = iio_device_claim_direct_mode(indio_dev); 335902c4b24SDavid Lechner if (ret < 0) 336902c4b24SDavid Lechner return ret; 337902c4b24SDavid Lechner 338902c4b24SDavid Lechner ret = ti_ads7950_scan_direct(st, chan->address); 339902c4b24SDavid Lechner iio_device_release_direct_mode(indio_dev); 340902c4b24SDavid Lechner if (ret < 0) 341902c4b24SDavid Lechner return ret; 342902c4b24SDavid Lechner 343902c4b24SDavid Lechner if (chan->address != TI_ADS7950_EXTRACT(ret, 12, 4)) 344902c4b24SDavid Lechner return -EIO; 345902c4b24SDavid Lechner 346902c4b24SDavid Lechner *val = TI_ADS7950_EXTRACT(ret, chan->scan_type.shift, 347902c4b24SDavid Lechner chan->scan_type.realbits); 348902c4b24SDavid Lechner 349902c4b24SDavid Lechner return IIO_VAL_INT; 350902c4b24SDavid Lechner case IIO_CHAN_INFO_SCALE: 351902c4b24SDavid Lechner ret = ti_ads7950_get_range(st); 352902c4b24SDavid Lechner if (ret < 0) 353902c4b24SDavid Lechner return ret; 354902c4b24SDavid Lechner 355902c4b24SDavid Lechner *val = ret; 356902c4b24SDavid Lechner *val2 = (1 << chan->scan_type.realbits) - 1; 357902c4b24SDavid Lechner 358902c4b24SDavid Lechner return IIO_VAL_FRACTIONAL; 359902c4b24SDavid Lechner } 360902c4b24SDavid Lechner 361902c4b24SDavid Lechner return -EINVAL; 362902c4b24SDavid Lechner } 363902c4b24SDavid Lechner 364902c4b24SDavid Lechner static const struct iio_info ti_ads7950_info = { 365902c4b24SDavid Lechner .read_raw = &ti_ads7950_read_raw, 366902c4b24SDavid Lechner .update_scan_mode = ti_ads7950_update_scan_mode, 367902c4b24SDavid Lechner }; 368902c4b24SDavid Lechner 369902c4b24SDavid Lechner static int ti_ads7950_probe(struct spi_device *spi) 370902c4b24SDavid Lechner { 371902c4b24SDavid Lechner struct ti_ads7950_state *st; 372902c4b24SDavid Lechner struct iio_dev *indio_dev; 373902c4b24SDavid Lechner const struct ti_ads7950_chip_info *info; 374902c4b24SDavid Lechner int ret; 375902c4b24SDavid Lechner 376902c4b24SDavid Lechner indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 377902c4b24SDavid Lechner if (!indio_dev) 378902c4b24SDavid Lechner return -ENOMEM; 379902c4b24SDavid Lechner 380902c4b24SDavid Lechner st = iio_priv(indio_dev); 381902c4b24SDavid Lechner 382902c4b24SDavid Lechner spi_set_drvdata(spi, indio_dev); 383902c4b24SDavid Lechner 384902c4b24SDavid Lechner st->spi = spi; 385902c4b24SDavid Lechner st->settings = TI_ADS7950_CR_MANUAL | TI_ADS7950_CR_RANGE_5V; 386902c4b24SDavid Lechner 387902c4b24SDavid Lechner info = &ti_ads7950_chip_info[spi_get_device_id(spi)->driver_data]; 388902c4b24SDavid Lechner 389902c4b24SDavid Lechner indio_dev->name = spi_get_device_id(spi)->name; 390902c4b24SDavid Lechner indio_dev->dev.parent = &spi->dev; 391902c4b24SDavid Lechner indio_dev->modes = INDIO_DIRECT_MODE; 392902c4b24SDavid Lechner indio_dev->channels = info->channels; 393902c4b24SDavid Lechner indio_dev->num_channels = info->num_channels; 394902c4b24SDavid Lechner indio_dev->info = &ti_ads7950_info; 395902c4b24SDavid Lechner 396902c4b24SDavid Lechner /* 397902c4b24SDavid Lechner * Setup default message. The sample is read at the end of the first 398902c4b24SDavid Lechner * transfer, then it takes one full cycle to convert the sample and one 399902c4b24SDavid Lechner * more cycle to send the value. The conversion process is driven by 400902c4b24SDavid Lechner * the SPI clock, which is why we have 3 transfers. The middle one is 401902c4b24SDavid Lechner * just dummy data sent while the chip is converting the sample that 402902c4b24SDavid Lechner * was read at the end of the first transfer. 403902c4b24SDavid Lechner */ 404902c4b24SDavid Lechner 405902c4b24SDavid Lechner st->scan_single_xfer[0].tx_buf = &st->tx_buf[0]; 406902c4b24SDavid Lechner st->scan_single_xfer[0].len = 2; 407902c4b24SDavid Lechner st->scan_single_xfer[0].cs_change = 1; 408902c4b24SDavid Lechner st->scan_single_xfer[1].tx_buf = &st->tx_buf[0]; 409902c4b24SDavid Lechner st->scan_single_xfer[1].len = 2; 410902c4b24SDavid Lechner st->scan_single_xfer[1].cs_change = 1; 411902c4b24SDavid Lechner st->scan_single_xfer[2].rx_buf = &st->rx_buf[0]; 412902c4b24SDavid Lechner st->scan_single_xfer[2].len = 2; 413902c4b24SDavid Lechner 414902c4b24SDavid Lechner spi_message_init_with_transfers(&st->scan_single_msg, 415902c4b24SDavid Lechner st->scan_single_xfer, 3); 416902c4b24SDavid Lechner 4178cfa26a7SAndy Shevchenko /* Use hard coded value for reference voltage in ACPI case */ 4188cfa26a7SAndy Shevchenko if (ACPI_COMPANION(&spi->dev)) 4198cfa26a7SAndy Shevchenko st->vref_mv = TI_ADS7950_VA_MV_ACPI_DEFAULT; 4208cfa26a7SAndy Shevchenko 4210bf1a2aaSDavid Lechner st->reg = devm_regulator_get(&spi->dev, "vref"); 422902c4b24SDavid Lechner if (IS_ERR(st->reg)) { 4230bf1a2aaSDavid Lechner dev_err(&spi->dev, "Failed get get regulator \"vref\"\n"); 424902c4b24SDavid Lechner return PTR_ERR(st->reg); 425902c4b24SDavid Lechner } 426902c4b24SDavid Lechner 427902c4b24SDavid Lechner ret = regulator_enable(st->reg); 428902c4b24SDavid Lechner if (ret) { 4290bf1a2aaSDavid Lechner dev_err(&spi->dev, "Failed to enable regulator \"vref\"\n"); 430902c4b24SDavid Lechner return ret; 431902c4b24SDavid Lechner } 432902c4b24SDavid Lechner 433902c4b24SDavid Lechner ret = iio_triggered_buffer_setup(indio_dev, NULL, 434902c4b24SDavid Lechner &ti_ads7950_trigger_handler, NULL); 435902c4b24SDavid Lechner if (ret) { 436902c4b24SDavid Lechner dev_err(&spi->dev, "Failed to setup triggered buffer\n"); 437902c4b24SDavid Lechner goto error_disable_reg; 438902c4b24SDavid Lechner } 439902c4b24SDavid Lechner 440902c4b24SDavid Lechner ret = iio_device_register(indio_dev); 441902c4b24SDavid Lechner if (ret) { 442902c4b24SDavid Lechner dev_err(&spi->dev, "Failed to register iio device\n"); 443902c4b24SDavid Lechner goto error_cleanup_ring; 444902c4b24SDavid Lechner } 445902c4b24SDavid Lechner 446902c4b24SDavid Lechner return 0; 447902c4b24SDavid Lechner 448902c4b24SDavid Lechner error_cleanup_ring: 449902c4b24SDavid Lechner iio_triggered_buffer_cleanup(indio_dev); 450902c4b24SDavid Lechner error_disable_reg: 451902c4b24SDavid Lechner regulator_disable(st->reg); 452902c4b24SDavid Lechner 453902c4b24SDavid Lechner return ret; 454902c4b24SDavid Lechner } 455902c4b24SDavid Lechner 456902c4b24SDavid Lechner static int ti_ads7950_remove(struct spi_device *spi) 457902c4b24SDavid Lechner { 458902c4b24SDavid Lechner struct iio_dev *indio_dev = spi_get_drvdata(spi); 459902c4b24SDavid Lechner struct ti_ads7950_state *st = iio_priv(indio_dev); 460902c4b24SDavid Lechner 461902c4b24SDavid Lechner iio_device_unregister(indio_dev); 462902c4b24SDavid Lechner iio_triggered_buffer_cleanup(indio_dev); 463902c4b24SDavid Lechner regulator_disable(st->reg); 464902c4b24SDavid Lechner 465902c4b24SDavid Lechner return 0; 466902c4b24SDavid Lechner } 467902c4b24SDavid Lechner 468902c4b24SDavid Lechner static const struct spi_device_id ti_ads7950_id[] = { 4692b84f4deSDavid Lechner { "ads7950", TI_ADS7950 }, 4702b84f4deSDavid Lechner { "ads7951", TI_ADS7951 }, 4712b84f4deSDavid Lechner { "ads7952", TI_ADS7952 }, 4722b84f4deSDavid Lechner { "ads7953", TI_ADS7953 }, 4732b84f4deSDavid Lechner { "ads7954", TI_ADS7954 }, 4742b84f4deSDavid Lechner { "ads7955", TI_ADS7955 }, 4752b84f4deSDavid Lechner { "ads7956", TI_ADS7956 }, 4762b84f4deSDavid Lechner { "ads7957", TI_ADS7957 }, 4772b84f4deSDavid Lechner { "ads7958", TI_ADS7958 }, 4782b84f4deSDavid Lechner { "ads7959", TI_ADS7959 }, 4792b84f4deSDavid Lechner { "ads7960", TI_ADS7960 }, 4802b84f4deSDavid Lechner { "ads7961", TI_ADS7961 }, 481902c4b24SDavid Lechner { } 482902c4b24SDavid Lechner }; 483902c4b24SDavid Lechner MODULE_DEVICE_TABLE(spi, ti_ads7950_id); 484902c4b24SDavid Lechner 485fb4b6f92SAndy Shevchenko static const struct of_device_id ads7950_of_table[] = { 486fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7950", .data = &ti_ads7950_chip_info[TI_ADS7950] }, 487fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7951", .data = &ti_ads7950_chip_info[TI_ADS7951] }, 488fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7952", .data = &ti_ads7950_chip_info[TI_ADS7952] }, 489fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7953", .data = &ti_ads7950_chip_info[TI_ADS7953] }, 490fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7954", .data = &ti_ads7950_chip_info[TI_ADS7954] }, 491fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7955", .data = &ti_ads7950_chip_info[TI_ADS7955] }, 492fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7956", .data = &ti_ads7950_chip_info[TI_ADS7956] }, 493fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7957", .data = &ti_ads7950_chip_info[TI_ADS7957] }, 494fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7958", .data = &ti_ads7950_chip_info[TI_ADS7958] }, 495fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7959", .data = &ti_ads7950_chip_info[TI_ADS7959] }, 496fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7960", .data = &ti_ads7950_chip_info[TI_ADS7960] }, 497fb4b6f92SAndy Shevchenko { .compatible = "ti,ads7961", .data = &ti_ads7950_chip_info[TI_ADS7961] }, 498fb4b6f92SAndy Shevchenko { }, 499fb4b6f92SAndy Shevchenko }; 500fb4b6f92SAndy Shevchenko MODULE_DEVICE_TABLE(of, ads7950_of_table); 501fb4b6f92SAndy Shevchenko 502902c4b24SDavid Lechner static struct spi_driver ti_ads7950_driver = { 503902c4b24SDavid Lechner .driver = { 5042b84f4deSDavid Lechner .name = "ads7950", 505fb4b6f92SAndy Shevchenko .of_match_table = ads7950_of_table, 506902c4b24SDavid Lechner }, 507902c4b24SDavid Lechner .probe = ti_ads7950_probe, 508902c4b24SDavid Lechner .remove = ti_ads7950_remove, 509902c4b24SDavid Lechner .id_table = ti_ads7950_id, 510902c4b24SDavid Lechner }; 511902c4b24SDavid Lechner module_spi_driver(ti_ads7950_driver); 512902c4b24SDavid Lechner 513902c4b24SDavid Lechner MODULE_AUTHOR("David Lechner <david@lechnology.com>"); 514902c4b24SDavid Lechner MODULE_DESCRIPTION("TI TI_ADS7950 ADC"); 515902c4b24SDavid Lechner MODULE_LICENSE("GPL v2"); 516