/* * AD7792/AD7793 SPI ADC driver * * Copyright 2011 Analog Devices Inc. * * Licensed under the GPL-2. */ #include #include #include #include #include #include #include #include #include #include #include "../iio.h" #include "../sysfs.h" #include "../ring_generic.h" #include "../ring_sw.h" #include "../trigger.h" #include "adc.h" #include "ad7793.h" /* NOTE: * The AD7792/AD7793 features a dual use data out ready DOUT/RDY output. * In order to avoid contentions on the SPI bus, it's therefore necessary * to use spi bus locking. * * The DOUT/RDY output must also be wired to an interrupt capable GPIO. */ struct ad7793_chip_info { struct iio_chan_spec channel[7]; }; struct ad7793_state { struct spi_device *spi; struct iio_trigger *trig; const struct ad7793_chip_info *chip_info; struct regulator *reg; struct ad7793_platform_data *pdata; wait_queue_head_t wq_data_avail; bool done; bool irq_dis; u16 int_vref_mv; u16 mode; u16 conf; u32 scale_avail[8][2]; u32 available_scan_masks[7]; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. */ u8 data[4] ____cacheline_aligned; }; enum ad7793_supported_device_ids { ID_AD7792, ID_AD7793, }; static int __ad7793_write_reg(struct ad7793_state *st, bool locked, bool cs_change, unsigned char reg, unsigned size, unsigned val) { u8 *data = st->data; struct spi_transfer t = { .tx_buf = data, .len = size + 1, .cs_change = cs_change, }; struct spi_message m; data[0] = AD7793_COMM_WRITE | AD7793_COMM_ADDR(reg); switch (size) { case 3: data[1] = val >> 16; data[2] = val >> 8; data[3] = val; break; case 2: data[1] = val >> 8; data[2] = val; break; case 1: data[1] = val; break; default: return -EINVAL; } spi_message_init(&m); spi_message_add_tail(&t, &m); if (locked) return spi_sync_locked(st->spi, &m); else return spi_sync(st->spi, &m); } static int ad7793_write_reg(struct ad7793_state *st, unsigned reg, unsigned size, unsigned val) { return __ad7793_write_reg(st, false, false, reg, size, val); } static int __ad7793_read_reg(struct ad7793_state *st, bool locked, bool cs_change, unsigned char reg, int *val, unsigned size) { u8 *data = st->data; int ret; struct spi_transfer t[] = { { .tx_buf = data, .len = 1, }, { .rx_buf = data, .len = size, .cs_change = cs_change, }, }; struct spi_message m; data[0] = AD7793_COMM_READ | AD7793_COMM_ADDR(reg); spi_message_init(&m); spi_message_add_tail(&t[0], &m); spi_message_add_tail(&t[1], &m); if (locked) ret = spi_sync_locked(st->spi, &m); else ret = spi_sync(st->spi, &m); if (ret < 0) return ret; switch (size) { case 3: *val = data[0] << 16 | data[1] << 8 | data[2]; break; case 2: *val = data[0] << 8 | data[1]; break; case 1: *val = data[0]; break; default: return -EINVAL; } return 0; } static int ad7793_read_reg(struct ad7793_state *st, unsigned reg, int *val, unsigned size) { return __ad7793_read_reg(st, 0, 0, reg, val, size); } static int ad7793_read(struct ad7793_state *st, unsigned ch, unsigned len, int *val) { int ret; st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(AD7793_MODE_SINGLE); ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); spi_bus_lock(st->spi->master); st->done = false; ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, sizeof(st->mode), st->mode); if (ret < 0) goto out; st->irq_dis = false; enable_irq(st->spi->irq); wait_event_interruptible(st->wq_data_avail, st->done); ret = __ad7793_read_reg(st, 1, 0, AD7793_REG_DATA, val, len); out: spi_bus_unlock(st->spi->master); return ret; } static int ad7793_calibrate(struct ad7793_state *st, unsigned mode, unsigned ch) { int ret; st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(mode); ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); spi_bus_lock(st->spi->master); st->done = false; ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, sizeof(st->mode), st->mode); if (ret < 0) goto out; st->irq_dis = false; enable_irq(st->spi->irq); wait_event_interruptible(st->wq_data_avail, st->done); st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(AD7793_MODE_IDLE); ret = __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, sizeof(st->mode), st->mode); out: spi_bus_unlock(st->spi->master); return ret; } static const u8 ad7793_calib_arr[6][2] = { {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M}, {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M}, {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M}, {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN2P_AIN2M}, {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN3P_AIN3M}, {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN3P_AIN3M} }; static int ad7793_calibrate_all(struct ad7793_state *st) { int i, ret; for (i = 0; i < ARRAY_SIZE(ad7793_calib_arr); i++) { ret = ad7793_calibrate(st, ad7793_calib_arr[i][0], ad7793_calib_arr[i][1]); if (ret) goto out; } return 0; out: dev_err(&st->spi->dev, "Calibration failed\n"); return ret; } static int ad7793_setup(struct ad7793_state *st) { int i, ret = -1; unsigned long long scale_uv; u32 id; /* reset the serial interface */ ret = spi_write(st->spi, (u8 *)&ret, sizeof(ret)); if (ret < 0) goto out; msleep(1); /* Wait for at least 500us */ /* write/read test for device presence */ ret = ad7793_read_reg(st, AD7793_REG_ID, &id, 1); if (ret) goto out; id &= AD7793_ID_MASK; if (!((id == AD7792_ID) || (id == AD7793_ID))) { dev_err(&st->spi->dev, "device ID query failed\n"); goto out; } st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(AD7793_MODE_IDLE); st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1); ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode); if (ret) goto out; ret = ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); if (ret) goto out; ret = ad7793_write_reg(st, AD7793_REG_IO, sizeof(st->pdata->io), st->pdata->io); if (ret) goto out; ret = ad7793_calibrate_all(st); if (ret) goto out; /* Populate available ADC input ranges */ for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { scale_uv = ((u64)st->int_vref_mv * 100000000) >> (st->chip_info->channel[0].scan_type.realbits - (!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1)); scale_uv >>= i; st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10; st->scale_avail[i][0] = scale_uv; } return 0; out: dev_err(&st->spi->dev, "setup failed\n"); return ret; } static int ad7793_scan_from_ring(struct ad7793_state *st, unsigned ch, int *val) { struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; int ret; s64 dat64[2]; u32 *dat32 = (u32 *)dat64; if (!(ring->scan_mask & (1 << ch))) return -EBUSY; ret = ring->access->read_last(ring, (u8 *) &dat64); if (ret) return ret; *val = *dat32; return 0; } static int ad7793_ring_preenable(struct iio_dev *indio_dev) { struct ad7793_state *st = iio_priv(indio_dev); struct iio_ring_buffer *ring = indio_dev->ring; size_t d_size; unsigned channel; if (!ring->scan_count) return -EINVAL; channel = __ffs(ring->scan_mask); d_size = ring->scan_count * indio_dev->channels[0].scan_type.storagebits / 8; if (ring->scan_timestamp) { d_size += sizeof(s64); if (d_size % sizeof(s64)) d_size += sizeof(s64) - (d_size % sizeof(s64)); } if (indio_dev->ring->access->set_bytes_per_datum) indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, d_size); st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(AD7793_MODE_CONT); st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(indio_dev->channels[channel].address); ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); spi_bus_lock(st->spi->master); __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, sizeof(st->mode), st->mode); st->irq_dis = false; enable_irq(st->spi->irq); return 0; } static int ad7793_ring_postdisable(struct iio_dev *indio_dev) { struct ad7793_state *st = iio_priv(indio_dev); st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(AD7793_MODE_IDLE); st->done = false; wait_event_interruptible(st->wq_data_avail, st->done); if (!st->irq_dis) disable_irq_nosync(st->spi->irq); __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, sizeof(st->mode), st->mode); return spi_bus_unlock(st->spi->master); } /** * ad7793_trigger_handler() bh of trigger launched polling to ring buffer **/ static irqreturn_t ad7793_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->private_data; struct iio_ring_buffer *ring = indio_dev->ring; struct ad7793_state *st = iio_priv(indio_dev); s64 dat64[2]; s32 *dat32 = (s32 *)dat64; if (ring->scan_count) __ad7793_read_reg(st, 1, 1, AD7793_REG_DATA, dat32, indio_dev->channels[0].scan_type.realbits/8); /* Guaranteed to be aligned with 8 byte boundary */ if (ring->scan_timestamp) dat64[1] = pf->timestamp; ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); iio_trigger_notify_done(indio_dev->trig); st->irq_dis = false; enable_irq(st->spi->irq); return IRQ_HANDLED; } static const struct iio_ring_setup_ops ad7793_ring_setup_ops = { .preenable = &ad7793_ring_preenable, .postenable = &iio_triggered_ring_postenable, .predisable = &iio_triggered_ring_predisable, .postdisable = &ad7793_ring_postdisable, }; static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) { int ret; indio_dev->ring = iio_sw_rb_allocate(indio_dev); if (!indio_dev->ring) { ret = -ENOMEM; goto error_ret; } /* Effectively select the ring buffer implementation */ indio_dev->ring->access = &ring_sw_access_funcs; indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &ad7793_trigger_handler, IRQF_ONESHOT, indio_dev, "ad7793_consumer%d", indio_dev->id); if (indio_dev->pollfunc == NULL) { ret = -ENOMEM; goto error_deallocate_sw_rb; } /* Ring buffer functions - here trigger setup related */ indio_dev->ring->setup_ops = &ad7793_ring_setup_ops; /* Flag that polled ring buffering is possible */ indio_dev->modes |= INDIO_RING_TRIGGERED; return 0; error_deallocate_sw_rb: iio_sw_rb_free(indio_dev->ring); error_ret: return ret; } static void ad7793_ring_cleanup(struct iio_dev *indio_dev) { /* ensure that the trigger has been detached */ if (indio_dev->trig) { iio_put_trigger(indio_dev->trig); iio_trigger_dettach_poll_func(indio_dev->trig, indio_dev->pollfunc); } iio_dealloc_pollfunc(indio_dev->pollfunc); iio_sw_rb_free(indio_dev->ring); } /** * ad7793_data_rdy_trig_poll() the event handler for the data rdy trig **/ static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private) { struct ad7793_state *st = iio_priv(private); st->done = true; wake_up_interruptible(&st->wq_data_avail); disable_irq_nosync(irq); st->irq_dis = true; iio_trigger_poll(st->trig, iio_get_time_ns()); return IRQ_HANDLED; } static int ad7793_probe_trigger(struct iio_dev *indio_dev) { struct ad7793_state *st = iio_priv(indio_dev); int ret; st->trig = iio_allocate_trigger("%s-dev%d", spi_get_device_id(st->spi)->name, indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; } ret = request_irq(st->spi->irq, ad7793_data_rdy_trig_poll, IRQF_TRIGGER_LOW, spi_get_device_id(st->spi)->name, indio_dev); if (ret) goto error_free_trig; disable_irq_nosync(st->spi->irq); st->irq_dis = true; st->trig->dev.parent = &st->spi->dev; st->trig->owner = THIS_MODULE; st->trig->private_data = indio_dev; ret = iio_trigger_register(st->trig); /* select default trigger */ indio_dev->trig = st->trig; if (ret) goto error_free_irq; return 0; error_free_irq: free_irq(st->spi->irq, indio_dev); error_free_trig: iio_free_trigger(st->trig); error_ret: return ret; } static void ad7793_remove_trigger(struct iio_dev *indio_dev) { struct ad7793_state *st = iio_priv(indio_dev); iio_trigger_unregister(st->trig); free_irq(st->spi->irq, indio_dev); iio_free_trigger(st->trig); } static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19, 17, 16, 12, 10, 8, 6, 4}; static ssize_t ad7793_read_frequency(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7793_state *st = iio_priv(indio_dev); return sprintf(buf, "%d\n", sample_freq_avail[AD7793_MODE_RATE(st->mode)]); } static ssize_t ad7793_write_frequency(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7793_state *st = iio_priv(indio_dev); long lval; int i, ret; mutex_lock(&indio_dev->mlock); if (iio_ring_enabled(indio_dev)) { mutex_unlock(&indio_dev->mlock); return -EBUSY; } mutex_unlock(&indio_dev->mlock); ret = strict_strtol(buf, 10, &lval); if (ret) return ret; ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(sample_freq_avail); i++) if (lval == sample_freq_avail[i]) { mutex_lock(&indio_dev->mlock); st->mode &= ~AD7793_MODE_RATE(-1); st->mode |= AD7793_MODE_RATE(i); ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode); mutex_unlock(&indio_dev->mlock); ret = 0; } return ret ? ret : len; } static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, ad7793_read_frequency, ad7793_write_frequency); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( "470 242 123 62 50 39 33 19 17 16 12 10 8 6 4"); static ssize_t ad7793_show_scale_available(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad7793_state *st = iio_priv(indio_dev); int i, len = 0; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0], st->scale_avail[i][1]); len += sprintf(buf + len, "\n"); return len; } static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available, S_IRUGO, ad7793_show_scale_available, NULL, 0); static struct attribute *ad7793_attributes[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_in_m_in_scale_available.dev_attr.attr, NULL }; static const struct attribute_group ad7793_attribute_group = { .attrs = ad7793_attributes, }; static int ad7793_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m) { struct ad7793_state *st = iio_priv(indio_dev); int ret, smpl = 0; unsigned long long scale_uv; bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR); switch (m) { case 0: mutex_lock(&indio_dev->mlock); if (iio_ring_enabled(indio_dev)) ret = ad7793_scan_from_ring(st, chan->scan_index, &smpl); else ret = ad7793_read(st, chan->address, chan->scan_type.realbits / 8, &smpl); mutex_unlock(&indio_dev->mlock); if (ret < 0) return ret; *val = (smpl >> chan->scan_type.shift) & ((1 << (chan->scan_type.realbits)) - 1); if (!unipolar) *val -= (1 << (chan->scan_type.realbits - 1)); return IIO_VAL_INT; case (1 << IIO_CHAN_INFO_SCALE_SHARED): *val = st->scale_avail[(st->conf >> 8) & 0x7][0]; *val2 = st->scale_avail[(st->conf >> 8) & 0x7][1]; return IIO_VAL_INT_PLUS_NANO; case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): switch (chan->type) { case IIO_IN: /* 1170mV / 2^23 * 6 */ scale_uv = (1170ULL * 100000000ULL * 6ULL) >> (chan->scan_type.realbits - (unipolar ? 0 : 1)); break; case IIO_TEMP: /* Always uses unity gain and internal ref */ scale_uv = (2500ULL * 100000000ULL) >> (chan->scan_type.realbits - (unipolar ? 0 : 1)); break; default: return -EINVAL; } *val2 = do_div(scale_uv, 100000000) * 10; *val = scale_uv; return IIO_VAL_INT_PLUS_NANO; } return -EINVAL; } static int ad7793_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct ad7793_state *st = iio_priv(indio_dev); int ret, i; unsigned int tmp; mutex_lock(&indio_dev->mlock); if (iio_ring_enabled(indio_dev)) { mutex_unlock(&indio_dev->mlock); return -EBUSY; } switch (mask) { case (1 << IIO_CHAN_INFO_SCALE_SHARED): ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { tmp = st->conf; st->conf &= ~AD7793_CONF_GAIN(-1); st->conf |= AD7793_CONF_GAIN(i); if (tmp != st->conf) { ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); ad7793_calibrate_all(st); } ret = 0; } default: ret = -EINVAL; } mutex_unlock(&indio_dev->mlock); return ret; } static int ad7793_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig) { if (indio_dev->trig != trig) return -EINVAL; return 0; } static int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, long mask) { return IIO_VAL_INT_PLUS_NANO; } static const struct iio_info ad7793_info = { .read_raw = &ad7793_read_raw, .write_raw = &ad7793_write_raw, .write_raw_get_fmt = &ad7793_write_raw_get_fmt, .attrs = &ad7793_attribute_group, .validate_trigger = ad7793_validate_trigger, .driver_module = THIS_MODULE, }; static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { [ID_AD7793] = { .channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN1P_AIN1M, 0, IIO_ST('s', 24, 32, 0), 0), .channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN2P_AIN2M, 1, IIO_ST('s', 24, 32, 0), 0), .channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN3P_AIN3M, 2, IIO_ST('s', 24, 32, 0), 0), .channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN1M_AIN1M, 3, IIO_ST('s', 24, 32, 0), 0), .channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), AD7793_CH_TEMP, 4, IIO_ST('s', 24, 32, 0), 0), .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), AD7793_CH_AVDD_MONITOR, 5, IIO_ST('s', 24, 32, 0), 0), .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, [ID_AD7792] = { .channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN1P_AIN1M, 0, IIO_ST('s', 16, 32, 0), 0), .channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN2P_AIN2M, 1, IIO_ST('s', 16, 32, 0), 0), .channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN3P_AIN3M, 2, IIO_ST('s', 16, 32, 0), 0), .channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0, (1 << IIO_CHAN_INFO_SCALE_SHARED), AD7793_CH_AIN1M_AIN1M, 3, IIO_ST('s', 16, 32, 0), 0), .channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), AD7793_CH_TEMP, 4, IIO_ST('s', 16, 32, 0), 0), .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0, (1 << IIO_CHAN_INFO_SCALE_SEPARATE), AD7793_CH_AVDD_MONITOR, 5, IIO_ST('s', 16, 32, 0), 0), .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), }, }; static int __devinit ad7793_probe(struct spi_device *spi) { struct ad7793_platform_data *pdata = spi->dev.platform_data; struct ad7793_state *st; struct iio_dev *indio_dev; int ret, i, voltage_uv = 0, regdone = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); return -ENODEV; } if (!spi->irq) { dev_err(&spi->dev, "no IRQ?\n"); return -ENODEV; } indio_dev = iio_allocate_device(sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); st->reg = regulator_get(&spi->dev, "vcc"); if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) goto error_put_reg; voltage_uv = regulator_get_voltage(st->reg); } st->chip_info = &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; st->pdata = pdata; if (pdata && pdata->vref_mv) st->int_vref_mv = pdata->vref_mv; else if (voltage_uv) st->int_vref_mv = voltage_uv / 1000; else st->int_vref_mv = 2500; /* Build-in ref */ spi_set_drvdata(spi, indio_dev); st->spi = spi; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channel; indio_dev->available_scan_masks = st->available_scan_masks; indio_dev->num_channels = 7; indio_dev->info = &ad7793_info; for (i = 0; i < indio_dev->num_channels; i++) st->available_scan_masks[i] = (1 << i) | (1 << indio_dev->channels[indio_dev->num_channels - 1]. scan_index); init_waitqueue_head(&st->wq_data_avail); ret = ad7793_register_ring_funcs_and_init(indio_dev); if (ret) goto error_disable_reg; ret = iio_device_register(indio_dev); if (ret) goto error_unreg_ring; regdone = 1; ret = ad7793_probe_trigger(indio_dev); if (ret) goto error_unreg_ring; ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, indio_dev->channels, indio_dev->num_channels); if (ret) goto error_remove_trigger; ret = ad7793_setup(st); if (ret) goto error_uninitialize_ring; return 0; error_uninitialize_ring: iio_ring_buffer_unregister(indio_dev->ring); error_remove_trigger: ad7793_remove_trigger(indio_dev); error_unreg_ring: ad7793_ring_cleanup(indio_dev); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); if (regdone) iio_device_unregister(indio_dev); else iio_free_device(indio_dev); return ret; } static int ad7793_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); struct ad7793_state *st = iio_priv(indio_dev); iio_ring_buffer_unregister(indio_dev->ring); ad7793_remove_trigger(indio_dev); ad7793_ring_cleanup(indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); regulator_put(st->reg); } iio_device_unregister(indio_dev); return 0; } static const struct spi_device_id ad7793_id[] = { {"ad7792", ID_AD7792}, {"ad7793", ID_AD7793}, {} }; static struct spi_driver ad7793_driver = { .driver = { .name = "ad7793", .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = ad7793_probe, .remove = __devexit_p(ad7793_remove), .id_table = ad7793_id, }; static int __init ad7793_init(void) { return spi_register_driver(&ad7793_driver); } module_init(ad7793_init); static void __exit ad7793_exit(void) { spi_unregister_driver(&ad7793_driver); } module_exit(ad7793_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7792/3 ADC"); MODULE_LICENSE("GPL v2");