diff options
Diffstat (limited to 'drivers/iio/adc/ad7606.c')
-rw-r--r-- | drivers/iio/adc/ad7606.c | 375 |
1 files changed, 188 insertions, 187 deletions
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index 703556eb7257..185243dee86e 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -13,6 +13,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/property.h> #include <linux/pwm.h> #include <linux/regulator/consumer.h> @@ -94,121 +95,35 @@ static const unsigned int ad7616_oversampling_avail[8] = { 1, 2, 4, 8, 16, 32, 64, 128, }; -static const struct iio_chan_spec ad7605_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(4), - AD7605_CHANNEL(0), - AD7605_CHANNEL(1), - AD7605_CHANNEL(2), - AD7605_CHANNEL(3), -}; - -static const struct iio_chan_spec ad7606_channels_16bit[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 16), - AD7606_CHANNEL(1, 16), - AD7606_CHANNEL(2, 16), - AD7606_CHANNEL(3, 16), - AD7606_CHANNEL(4, 16), - AD7606_CHANNEL(5, 16), - AD7606_CHANNEL(6, 16), - AD7606_CHANNEL(7, 16), -}; - -static const struct iio_chan_spec ad7606_channels_18bit[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 18), - AD7606_CHANNEL(1, 18), - AD7606_CHANNEL(2, 18), - AD7606_CHANNEL(3, 18), - AD7606_CHANNEL(4, 18), - AD7606_CHANNEL(5, 18), - AD7606_CHANNEL(6, 18), - AD7606_CHANNEL(7, 18), -}; - -static const struct iio_chan_spec ad7607_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 14), - AD7606_CHANNEL(1, 14), - AD7606_CHANNEL(2, 14), - AD7606_CHANNEL(3, 14), - AD7606_CHANNEL(4, 14), - AD7606_CHANNEL(5, 14), - AD7606_CHANNEL(6, 14), - AD7606_CHANNEL(7, 14), -}; - -static const struct iio_chan_spec ad7608_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 18), - AD7606_CHANNEL(1, 18), - AD7606_CHANNEL(2, 18), - AD7606_CHANNEL(3, 18), - AD7606_CHANNEL(4, 18), - AD7606_CHANNEL(5, 18), - AD7606_CHANNEL(6, 18), - AD7606_CHANNEL(7, 18), -}; - -/* - * The current assumption that this driver makes for AD7616, is that it's - * working in Hardware Mode with Serial, Burst and Sequencer modes activated. - * To activate them, following pins must be pulled high: - * -SER/PAR - * -SEQEN - * And following pins must be pulled low: - * -WR/BURST - * -DB4/SER1W - */ -static const struct iio_chan_spec ad7616_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(16), - AD7606_CHANNEL(0, 16), - AD7606_CHANNEL(1, 16), - AD7606_CHANNEL(2, 16), - AD7606_CHANNEL(3, 16), - AD7606_CHANNEL(4, 16), - AD7606_CHANNEL(5, 16), - AD7606_CHANNEL(6, 16), - AD7606_CHANNEL(7, 16), - AD7606_CHANNEL(8, 16), - AD7606_CHANNEL(9, 16), - AD7606_CHANNEL(10, 16), - AD7606_CHANNEL(11, 16), - AD7606_CHANNEL(12, 16), - AD7606_CHANNEL(13, 16), - AD7606_CHANNEL(14, 16), - AD7606_CHANNEL(15, 16), -}; - static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7607_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7608_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7609_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7616_sw_mode_setup(struct iio_dev *indio_dev); static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev); const struct ad7606_chip_info ad7605_4_info = { - .channels = ad7605_channels, + .max_samplerate = 300 * KILO, .name = "ad7605-4", + .bits = 16, .num_adc_channels = 4, - .num_channels = 5, .scale_setup_cb = ad7606_16bit_chan_scale_setup, }; EXPORT_SYMBOL_NS_GPL(ad7605_4_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606_8_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 200 * KILO, .name = "ad7606-8", + .bits = 16, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, @@ -216,108 +131,116 @@ const struct ad7606_chip_info ad7606_8_info = { EXPORT_SYMBOL_NS_GPL(ad7606_8_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606_6_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 200 * KILO, .name = "ad7606-6", + .bits = 16, .num_adc_channels = 6, - .num_channels = 7, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606_6_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606_4_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 200 * KILO, .name = "ad7606-4", + .bits = 16, .num_adc_channels = 4, - .num_channels = 5, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606_4_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606b_info = { - .channels = ad7606_channels_16bit, .max_samplerate = 800 * KILO, .name = "ad7606b", + .bits = 16, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, .sw_setup_cb = ad7606b_sw_mode_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606b_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606c_16_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 1 * MEGA, .name = "ad7606c16", + .bits = 16, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606c_16bit_chan_scale_setup, .sw_setup_cb = ad7606b_sw_mode_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, "IIO_AD7606"); const struct ad7606_chip_info ad7607_info = { - .channels = ad7607_channels, + .max_samplerate = 200 * KILO, .name = "ad7607", + .bits = 14, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7607_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7607_info, "IIO_AD7606"); const struct ad7606_chip_info ad7608_info = { - .channels = ad7608_channels, + .max_samplerate = 200 * KILO, .name = "ad7608", + .bits = 18, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7608_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7608_info, "IIO_AD7606"); const struct ad7606_chip_info ad7609_info = { - .channels = ad7608_channels, + .max_samplerate = 200 * KILO, .name = "ad7609", + .bits = 18, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7609_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7609_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606c_18_info = { - .channels = ad7606_channels_18bit, + .max_samplerate = 1 * MEGA, .name = "ad7606c18", + .bits = 18, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606c_18bit_chan_scale_setup, .sw_setup_cb = ad7606b_sw_mode_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, "IIO_AD7606"); const struct ad7606_chip_info ad7616_info = { - .channels = ad7616_channels, + .max_samplerate = 1 * MEGA, .init_delay_ms = 15, .name = "ad7616", + .bits = 16, .num_adc_channels = 16, - .num_channels = 17, .oversampling_avail = ad7616_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), .os_req_reset = true, .scale_setup_cb = ad7606_16bit_chan_scale_setup, .sw_setup_cb = ad7616_sw_mode_setup, + .offload_storagebits = 16, }; EXPORT_SYMBOL_NS_GPL(ad7616_info, "IIO_AD7606"); @@ -335,10 +258,10 @@ int ad7606_reset(struct ad7606_state *st) EXPORT_SYMBOL_NS_GPL(ad7606_reset, "IIO_AD7606"); static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; if (!st->sw_mode_en) { /* tied to logic low, analog input range is +/- 5V */ @@ -362,7 +285,6 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch, { struct ad7606_state *st = iio_priv(indio_dev); unsigned int num_channels = st->chip_info->num_adc_channels; - unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels; struct device *dev = st->dev; int ret; @@ -378,7 +300,7 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch, continue; /* channel number (here) is from 1 to num_channels */ - if (reg < offset || reg > num_channels) { + if (reg < 1 || reg > num_channels) { dev_warn(dev, "Invalid channel number (ignoring): %d\n", reg); continue; @@ -414,10 +336,10 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch, } static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; bool bipolar, differential; int ret; @@ -428,7 +350,8 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, return 0; } - ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential); + ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar, + &differential); if (ret) return ret; @@ -471,10 +394,10 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; bool bipolar, differential; int ret; @@ -485,7 +408,8 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, return 0; } - ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential); + ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar, + &differential); if (ret) return ret; @@ -529,10 +453,10 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7607_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; cs->range = 0; cs->scale_avail = ad7607_hw_scale_avail; @@ -541,10 +465,10 @@ static int ad7607_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7608_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; cs->range = 0; cs->scale_avail = ad7606_18bit_hw_scale_avail; @@ -553,10 +477,10 @@ static int ad7608_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7609_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; cs->range = 0; cs->scale_avail = ad7609_hw_scale_avail; @@ -599,7 +523,7 @@ static int ad7606_pwm_set_high(struct ad7606_state *st) return ret; } -static int ad7606_pwm_set_low(struct ad7606_state *st) +int ad7606_pwm_set_low(struct ad7606_state *st) { struct pwm_state cnvst_pwm_state; int ret; @@ -612,8 +536,9 @@ static int ad7606_pwm_set_low(struct ad7606_state *st) return ret; } +EXPORT_SYMBOL_NS_GPL(ad7606_pwm_set_low, "IIO_AD7606"); -static int ad7606_pwm_set_swing(struct ad7606_state *st) +int ad7606_pwm_set_swing(struct ad7606_state *st) { struct pwm_state cnvst_pwm_state; @@ -623,6 +548,7 @@ static int ad7606_pwm_set_swing(struct ad7606_state *st) return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state); } +EXPORT_SYMBOL_NS_GPL(ad7606_pwm_set_swing, "IIO_AD7606"); static bool ad7606_pwm_is_swinging(struct ad7606_state *st) { @@ -679,8 +605,8 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p) if (ret) goto error_ret; - iio_push_to_buffers_with_timestamp(indio_dev, &st->data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data), + iio_get_time_ns(indio_dev)); error_ret: iio_trigger_notify_done(indio_dev->trig); /* The rising edge of the CONVST signal starts a new conversion. */ @@ -693,8 +619,8 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch, int *val) { struct ad7606_state *st = iio_priv(indio_dev); - unsigned int realbits = st->chip_info->channels[1].scan_type.realbits; const struct iio_chan_spec *chan; + unsigned int realbits; int ret; if (st->gpio_convst) { @@ -711,7 +637,7 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch, * will not happen because IIO_CHAN_INFO_RAW is not supported for the backend. * TODO: Add support for reading a single value when the backend is used. */ - if (!st->back) { + if (st->trig) { ret = wait_for_completion_timeout(&st->completion, msecs_to_jiffies(1000)); if (!ret) { @@ -719,25 +645,30 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch, goto error_ret; } } else { - fsleep(1); + /* + * If the BUSY interrupt is not available, wait enough time for + * the longest possible conversion (max for the whole family is + * around 350us). + */ + fsleep(400); } ret = ad7606_read_samples(st); if (ret) goto error_ret; - chan = &indio_dev->channels[ch + 1]; - if (chan->scan_type.sign == 'u') { - if (realbits > 16) - *val = st->data.buf32[ch]; - else - *val = st->data.buf16[ch]; - } else { - if (realbits > 16) - *val = sign_extend32(st->data.buf32[ch], realbits - 1); - else - *val = sign_extend32(st->data.buf16[ch], realbits - 1); - } + chan = &indio_dev->channels[ch]; + realbits = chan->scan_type.realbits; + + if (realbits > 16) + *val = st->data.buf32[ch]; + else + *val = st->data.buf16[ch]; + + *val &= GENMASK(realbits - 1, 0); + + if (chan->scan_type.sign == 's') + *val = sign_extend32(*val, realbits - 1); error_ret: if (!st->gpio_convst) { @@ -765,14 +696,14 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: if (!iio_device_claim_direct(indio_dev)) return -EBUSY; - ret = ad7606_scan_direct(indio_dev, chan->address, val); + ret = ad7606_scan_direct(indio_dev, chan->scan_index, val); iio_device_release_direct(indio_dev); if (ret < 0) return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if (st->sw_mode_en) - ch = chan->address; + ch = chan->scan_index; cs = &st->chan_scales[ch]; *val = cs->scale_avail[cs->range][0]; *val2 = cs->scale_avail[cs->range][1]; @@ -781,10 +712,6 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, *val = st->oversampling; return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: - /* - * TODO: return the real frequency intead of the requested one once - * pwm_get_state_hw comes upstream. - */ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); *val = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, cnvst_pwm_state.period); return IIO_VAL_INT; @@ -854,7 +781,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_SCALE: if (st->sw_mode_en) - ch = chan->address; + ch = chan->scan_index; cs = &st->chan_scales[ch]; for (i = 0; i < cs->num_scales; i++) { scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO + @@ -1061,7 +988,7 @@ static int ad7606_read_avail(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: if (st->sw_mode_en) - ch = chan->address; + ch = chan->scan_index; cs = &st->chan_scales[ch]; *vals = (int *)cs->scale_avail; @@ -1276,29 +1203,91 @@ static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev) return st->bops->sw_mode_config(indio_dev); } -static int ad7606_chan_scales_setup(struct iio_dev *indio_dev) +static int ad7606_probe_channels(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels; - struct iio_chan_spec *chans; - size_t size; - int ch, ret; - - /* Clone IIO channels, since some may be differential */ - size = indio_dev->num_channels * sizeof(*indio_dev->channels); - chans = devm_kzalloc(st->dev, size, GFP_KERNEL); - if (!chans) + struct device *dev = indio_dev->dev.parent; + struct iio_chan_spec *channels; + bool slow_bus; + int ret, i; + + slow_bus = !(st->bops->iio_backend_config || st->offload_en); + indio_dev->num_channels = st->chip_info->num_adc_channels; + + /* Slow buses also get 1 more channel for soft timestamp */ + if (slow_bus) + indio_dev->num_channels++; + + channels = devm_kcalloc(dev, indio_dev->num_channels, sizeof(*channels), + GFP_KERNEL); + if (!channels) return -ENOMEM; - memcpy(chans, indio_dev->channels, size); - indio_dev->channels = chans; + for (i = 0; i < st->chip_info->num_adc_channels; i++) { + struct iio_chan_spec *chan = &channels[i]; - for (ch = 0; ch < st->chip_info->num_adc_channels; ch++) { - ret = st->chip_info->scale_setup_cb(indio_dev, &chans[ch + offset], ch); + chan->type = IIO_VOLTAGE; + chan->indexed = 1; + chan->channel = i; + chan->scan_index = i; + chan->scan_type.sign = 's'; + chan->scan_type.realbits = st->chip_info->bits; + /* + * If in SPI offload mode, storagebits are set based + * on the spi-engine hw implementation. + */ + chan->scan_type.storagebits = st->offload_en ? + st->chip_info->offload_storagebits : + (st->chip_info->bits > 16 ? 32 : 16); + + chan->scan_type.endianness = IIO_CPU; + + if (indio_dev->modes & INDIO_DIRECT_MODE) + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_RAW); + + if (st->sw_mode_en) { + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_SCALE); + chan->info_mask_separate_available |= + BIT(IIO_CHAN_INFO_SCALE); + + /* + * All chips with software mode support oversampling, + * so we skip the oversampling_available check. And the + * shared_by_type instead of shared_by_all on slow + * buses is for backward compatibility. + */ + if (slow_bus) + chan->info_mask_shared_by_type |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + else + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + + chan->info_mask_shared_by_all_available |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + } else { + chan->info_mask_shared_by_type |= + BIT(IIO_CHAN_INFO_SCALE); + + if (st->chip_info->oversampling_avail) + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + } + + if (!slow_bus) + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_SAMP_FREQ); + + ret = st->chip_info->scale_setup_cb(indio_dev, chan); if (ret) return ret; } + if (slow_bus) + channels[i] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(i); + + indio_dev->channels = channels; + return 0; } @@ -1322,11 +1311,19 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st = iio_priv(indio_dev); dev_set_drvdata(dev, indio_dev); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + st->dev = dev; - mutex_init(&st->lock); st->bops = bops; st->base_address = base_address; st->oversampling = 1; + st->sw_mode_en = device_property_read_bool(dev, "adi,sw-mode"); + + if (st->sw_mode_en && !chip_info->sw_setup_cb) + return dev_err_probe(dev, -EINVAL, + "Software mode is not supported for this chip\n"); ret = devm_regulator_get_enable(dev, "avcc"); if (ret) @@ -1355,10 +1352,21 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, else indio_dev->info = &ad7606_info_no_os_or_range; } - indio_dev->modes = INDIO_DIRECT_MODE; + + /* AXI ADC backend doesn't support single read. */ + indio_dev->modes = st->bops->iio_backend_config ? 0 : INDIO_DIRECT_MODE; indio_dev->name = chip_info->name; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; + + /* Using spi-engine with offload support ? */ + if (st->bops->offload_config) { + ret = st->bops->offload_config(dev, indio_dev); + if (ret) + return ret; + } + + ret = ad7606_probe_channels(indio_dev); + if (ret) + return ret; ret = ad7606_reset(st); if (ret) @@ -1371,7 +1379,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, } /* If convst pin is not defined, setup PWM. */ - if (!st->gpio_convst) { + if (!st->gpio_convst || st->offload_en) { st->cnvst_pwm = devm_pwm_get(dev, NULL); if (IS_ERR(st->cnvst_pwm)) return PTR_ERR(st->cnvst_pwm); @@ -1401,8 +1409,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, * If there is a backend, the PWM should not overpass the maximum sampling * frequency the chip supports. */ - ret = ad7606_set_sampling_freq(st, - chip_info->max_samplerate ? : 2 * KILO); + ret = ad7606_set_sampling_freq(st, chip_info->max_samplerate); if (ret) return ret; @@ -1411,8 +1418,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, return ret; indio_dev->setup_ops = &ad7606_backend_buffer_ops; - } else { - + } else if (!st->offload_en) { /* Reserve the PWM use only for backend (force gpio_convst definition) */ if (!st->gpio_convst) return dev_err_probe(dev, -EINVAL, @@ -1450,17 +1456,12 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; - st->sw_mode_en = st->chip_info->sw_setup_cb && - device_property_present(st->dev, "adi,sw-mode"); - if (st->sw_mode_en) { + /* Offload needs 1 DOUT line, applying this setting in sw_setup_cb. */ + if (st->sw_mode_en || st->offload_en) { indio_dev->info = &ad7606_info_sw_mode; st->chip_info->sw_setup_cb(indio_dev); } - ret = ad7606_chan_scales_setup(indio_dev); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } EXPORT_SYMBOL_NS_GPL(ad7606_probe, "IIO_AD7606"); |