Add support for the ad4695's oversampling feature when SPI offload is available. This allows the ad4695 to set oversampling ratios on a per-channel basis, raising the effective-number-of-bits from 16 (OSR == 1) to 17 (4), 18 (16), or 19 (64) for a given sample (i.e. one full cycle through the auto-sequencer). The logic for reading and writing sampling frequency for a given channel is also adjusted based on the current oversampling ratio. The non-offload case isn't supported as there isn't a good way to trigger the CNV pin in this mode. Support could be added in the future if a use-case arises. Signed-off-by: Trevor Gamblin <tgamblin@xxxxxxxxxxxx> --- drivers/iio/adc/ad4695.c | 378 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 348 insertions(+), 30 deletions(-) diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index c8cd73d19e86..320f2c1a0877 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -79,6 +79,7 @@ #define AD4695_REG_CONFIG_IN_MODE BIT(6) #define AD4695_REG_CONFIG_IN_PAIR GENMASK(5, 4) #define AD4695_REG_CONFIG_IN_AINHIGHZ_EN BIT(3) +#define AD4695_REG_CONFIG_IN_OSR_SET GENMASK(1, 0) #define AD4695_REG_UPPER_IN(n) (0x0040 | (2 * (n))) #define AD4695_REG_LOWER_IN(n) (0x0060 | (2 * (n))) #define AD4695_REG_HYST_IN(n) (0x0080 | (2 * (n))) @@ -127,6 +128,7 @@ struct ad4695_channel_config { bool bipolar; enum ad4695_in_pair pin_pairing; unsigned int common_mode_mv; + unsigned int oversampling_ratio; }; struct ad4695_state { @@ -306,6 +308,65 @@ static const struct regmap_bus ad4695_regmap_bus = { .val_format_endian_default = REGMAP_ENDIAN_BIG, }; +enum { + AD4695_SCAN_TYPE_OSR_1, + AD4695_SCAN_TYPE_OSR_4, + AD4695_SCAN_TYPE_OSR_16, + AD4695_SCAN_TYPE_OSR_64, +}; + +static const struct iio_scan_type ad4695_scan_type_offload_u[] = { + [AD4695_SCAN_TYPE_OSR_1] = { + .sign = 'u', + .realbits = 16, + .shift = 3, + .storagebits = 32, + }, + [AD4695_SCAN_TYPE_OSR_4] = { + .sign = 'u', + .realbits = 17, + .shift = 2, + .storagebits = 32, + }, + [AD4695_SCAN_TYPE_OSR_16] = { + .sign = 'u', + .realbits = 18, + .shift = 1, + .storagebits = 32, + }, + [AD4695_SCAN_TYPE_OSR_64] = { + .sign = 'u', + .realbits = 19, + .storagebits = 32, + }, +}; + +static const struct iio_scan_type ad4695_scan_type_offload_s[] = { + [AD4695_SCAN_TYPE_OSR_1] = { + .sign = 's', + .realbits = 16, + .shift = 3, + .storagebits = 32, + }, + [AD4695_SCAN_TYPE_OSR_4] = { + .sign = 's', + .realbits = 17, + .shift = 2, + .storagebits = 32, + }, + [AD4695_SCAN_TYPE_OSR_16] = { + .sign = 's', + .realbits = 18, + .shift = 1, + .storagebits = 32, + }, + [AD4695_SCAN_TYPE_OSR_64] = { + .sign = 's', + .realbits = 19, + .storagebits = 32, + }, +}; + static const struct iio_chan_spec ad4695_channel_template = { .type = IIO_VOLTAGE, .indexed = 1, @@ -343,6 +404,10 @@ static const char * const ad4695_power_supplies[] = { "avdd", "vio" }; +static const int ad4695_oversampling_ratios[] = { + 1, 4, 16, 64, +}; + static const struct ad4695_chip_info ad4695_chip_info = { .name = "ad4695", .max_sample_rate = 500 * KILO, @@ -519,6 +584,29 @@ static int ad4695_set_ref_voltage(struct ad4695_state *st, int vref_mv) FIELD_PREP(AD4695_REG_REF_CTRL_VREF_SET, val)); } +/** + * ad4695_osr_to_regval - convert ratio to OSR register value + * @ratio: ratio to check + * + * Check if ratio is present in the list of available ratios and return + * the corresponding value that needs to be written to the register to + * select that ratio. + * + * Returns: register value (0 to 3) or -EINVAL if there is not an exact + * match + */ +static int ad4695_osr_to_regval(int ratio) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ad4695_oversampling_ratios); i++) { + if (ratio == ad4695_oversampling_ratios[i]) + return i; + } + + return -EINVAL; +} + static int ad4695_write_chn_cfg(struct ad4695_state *st, struct ad4695_channel_config *cfg) { @@ -945,10 +1033,18 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct ad4695_state *st = iio_priv(indio_dev); + const struct iio_scan_type *scan_type; struct ad4695_channel_config *cfg = &st->channels_cfg[chan->scan_index]; - u8 realbits = chan->scan_type.realbits; + unsigned int osr = st->channels_cfg[chan->scan_index].oversampling_ratio; unsigned int reg_val; int ret, tmp; + u8 realbits; + + scan_type = iio_get_current_scan_type(indio_dev, chan); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + realbits = scan_type->realbits; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -957,7 +1053,7 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - if (chan->scan_type.sign == 's') + if (scan_type->sign == 's') *val = sign_extend32(st->raw_data, realbits - 1); else *val = st->raw_data; @@ -969,7 +1065,7 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_VOLTAGE: *val = st->vref_mv; - *val2 = chan->scan_type.realbits; + *val2 = realbits; return IIO_VAL_FRACTIONAL_LOG2; case IIO_TEMP: /* T_scale (°C) = raw * V_REF (mV) / (-1.8 mV/°C * 2^16) */ @@ -1030,8 +1126,26 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, tmp = sign_extend32(reg_val, 15); - *val = tmp / 4; - *val2 = abs(tmp) % 4 * MICRO / 4; + switch (cfg->oversampling_ratio) { + case 1: + *val = tmp / 4; + *val2 = abs(tmp) % 4 * MICRO / 4; + break; + case 4: + *val = tmp / 2; + *val2 = abs(tmp) % 2 * MICRO / 2; + break; + case 16: + *val = tmp; + *val2 = 0; + break; + case 64: + *val = tmp * 2; + *val2 = 0; + break; + default: + return -EINVAL; + } if (tmp < 0 && *val2) { *val *= -1; @@ -1044,6 +1158,14 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + switch (chan->type) { + case IIO_VOLTAGE: + *val = st->channels_cfg[chan->scan_index].oversampling_ratio; + return IIO_VAL_INT; + default: + return -EINVAL; + } case IIO_CHAN_INFO_SAMP_FREQ: { struct pwm_state state; @@ -1051,7 +1173,11 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - *val = DIV_ROUND_UP_ULL(NSEC_PER_SEC, state.period); + /* + * The effective sampling frequency for a channel is the input + * frequency divided by the channel's OSR value. + */ + *val = DIV_ROUND_UP_ULL(NSEC_PER_SEC, state.period * osr); return IIO_VAL_INT; } @@ -1072,12 +1198,114 @@ static int ad4695_write_raw_get_fmt(struct iio_dev *indio_dev, } } +static int ad4695_set_osr_val(struct ad4695_state *st, + struct iio_chan_spec const *chan, + int val) +{ + int osr = ad4695_osr_to_regval(val); + + if (osr < 0) + return osr; + + switch (chan->type) { + case IIO_VOLTAGE: + st->channels_cfg[chan->scan_index].oversampling_ratio = val; + return regmap_update_bits(st->regmap, + AD4695_REG_CONFIG_IN(chan->scan_index), + AD4695_REG_CONFIG_IN_OSR_SET, + FIELD_PREP(AD4695_REG_CONFIG_IN_OSR_SET, osr)); + default: + return -EINVAL; + } +} + +static unsigned int ad4695_get_calibbias(int val, int val2, int osr) +{ + unsigned int reg_val; + + switch (osr) { + case 4: + if (val2 >= 0 && val > S16_MAX / 2) + reg_val = S16_MAX; + else if ((val2 < 0 ? -val : val) < S16_MIN / 2) + reg_val = S16_MIN; + else if (val2 < 0) + reg_val = clamp_t(int, + -(val * 2 + -val2 * 2 / MICRO), + S16_MIN, S16_MAX); + else if (val < 0) + reg_val = clamp_t(int, + val * 2 - val2 * 2 / MICRO, + S16_MIN, S16_MAX); + else + reg_val = clamp_t(int, + val * 2 + val2 * 2 / MICRO, + S16_MIN, S16_MAX); + return reg_val; + case 16: + if (val2 >= 0 && val > S16_MAX) + reg_val = S16_MAX; + else if ((val2 < 0 ? -val : val) < S16_MIN) + reg_val = S16_MIN; + else if (val2 < 0) + reg_val = clamp_t(int, + -(val + -val2 / MICRO), + S16_MIN, S16_MAX); + else if (val < 0) + reg_val = clamp_t(int, + val - val2 / MICRO, + S16_MIN, S16_MAX); + else + reg_val = clamp_t(int, + val + val2 / MICRO, + S16_MIN, S16_MAX); + return reg_val; + case 64: + if (val2 >= 0 && val > S16_MAX * 2) + reg_val = S16_MAX; + else if ((val2 < 0 ? -val : val) < S16_MIN * 2) + reg_val = S16_MIN; + else if (val2 < 0) + reg_val = clamp_t(int, + -(val / 2 + -val2 / 2 / MICRO), + S16_MIN, S16_MAX); + else if (val < 0) + reg_val = clamp_t(int, + val / 2 - val2 / 2 / MICRO, + S16_MIN, S16_MAX); + else + reg_val = clamp_t(int, + val / 2 + val2 / 2 / MICRO, + S16_MIN, S16_MAX); + return reg_val; + default: + if (val2 >= 0 && val > S16_MAX / 4) + reg_val = S16_MAX; + else if ((val2 < 0 ? -val : val) < S16_MIN / 4) + reg_val = S16_MIN; + else if (val2 < 0) + reg_val = clamp_t(int, + -(val * 4 + -val2 * 4 / MICRO), + S16_MIN, S16_MAX); + else if (val < 0) + reg_val = clamp_t(int, + val * 4 - val2 * 4 / MICRO, + S16_MIN, S16_MAX); + else + reg_val = clamp_t(int, + val * 4 + val2 * 4 / MICRO, + S16_MIN, S16_MAX); + return reg_val; + } +} + static int ad4695_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct ad4695_state *st = iio_priv(indio_dev); unsigned int reg_val; + unsigned int osr = st->channels_cfg[chan->scan_index].oversampling_ratio; iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { switch (mask) { @@ -1102,23 +1330,7 @@ static int ad4695_write_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_VOLTAGE: - if (val2 >= 0 && val > S16_MAX / 4) - reg_val = S16_MAX; - else if ((val2 < 0 ? -val : val) < S16_MIN / 4) - reg_val = S16_MIN; - else if (val2 < 0) - reg_val = clamp_t(int, - -(val * 4 + -val2 * 4 / MICRO), - S16_MIN, S16_MAX); - else if (val < 0) - reg_val = clamp_t(int, - val * 4 - val2 * 4 / MICRO, - S16_MIN, S16_MAX); - else - reg_val = clamp_t(int, - val * 4 + val2 * 4 / MICRO, - S16_MIN, S16_MAX); - + reg_val = ad4695_get_calibbias(val, val2, osr); return regmap_write(st->regmap16, AD4695_REG_OFFSET_IN(chan->scan_index), reg_val); @@ -1127,15 +1339,27 @@ static int ad4695_write_raw(struct iio_dev *indio_dev, } case IIO_CHAN_INFO_SAMP_FREQ: { struct pwm_state state; - - if (val <= 0 || val > st->chip_info->max_sample_rate) + /* + * Limit the maximum acceptable sample rate according to + * the channel's oversampling ratio. + */ + u64 max_osr_rate = DIV_ROUND_UP_ULL(st->chip_info->max_sample_rate, + osr); + + if (val <= 0 || val > max_osr_rate) return -EINVAL; guard(mutex)(&st->cnv_pwm_lock); pwm_get_state(st->cnv_pwm, &state); - state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, val); + /* + * The required sample frequency for a given OSR is the + * input frequency multiplied by it. + */ + state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, val * osr); return pwm_apply_might_sleep(st->cnv_pwm, &state); } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + return ad4695_set_osr_val(st, chan, val); default: return -EINVAL; } @@ -1148,18 +1372,40 @@ static int ad4695_read_avail(struct iio_dev *indio_dev, const int **vals, int *type, int *length, long mask) { + int ret; static const int ad4695_calibscale_available[6] = { /* Range of 0 (inclusive) to 2 (exclusive) */ 0, 15, 1, 15, U16_MAX, 15 }; - static const int ad4695_calibbias_available[6] = { + static const int ad4695_calibbias_available[4][6] = { /* * Datasheet says FSR/8 which translates to signed/4. The step - * depends on oversampling ratio which is always 1 for now. + * depends on oversampling ratio, so we need four different + * ranges to select from. */ - S16_MIN / 4, 0, 0, MICRO / 4, S16_MAX / 4, S16_MAX % 4 * MICRO / 4 + { + S16_MIN / 4, 0, + 0, MICRO / 4, + S16_MAX / 4, S16_MAX % 4 * MICRO / 4 + }, + { + S16_MIN / 2, 0, + 0, MICRO / 2, + S16_MAX / 2, S16_MAX % 2 * MICRO / 2, + }, + { + S16_MIN, 0, + 1, 0, + S16_MAX, 0, + }, + { + S16_MIN * 2, 0, + 2, 0, + S16_MAX * 2, 0, + }, }; struct ad4695_state *st = iio_priv(indio_dev); + unsigned int osr = st->channels_cfg[chan->scan_index].oversampling_ratio; switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: @@ -1174,16 +1420,36 @@ static int ad4695_read_avail(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_VOLTAGE: - *vals = ad4695_calibbias_available; + ret = ad4695_osr_to_regval(osr); + if (ret < 0) + return ret; + /* + * Select the appropriate calibbias array based on the + * OSR value in the register. + */ + *vals = ad4695_calibbias_available[ret]; *type = IIO_VAL_INT_PLUS_MICRO; return IIO_AVAIL_RANGE; default: return -EINVAL; } case IIO_CHAN_INFO_SAMP_FREQ: + /* Max sample rate for the channel depends on OSR */ + st->sample_freq_range[2] = + DIV_ROUND_UP_ULL(st->chip_info->max_sample_rate, osr); *vals = st->sample_freq_range; *type = IIO_VAL_INT; return IIO_AVAIL_RANGE; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + switch (chan->type) { + case IIO_VOLTAGE: + *vals = ad4695_oversampling_ratios; + *length = ARRAY_SIZE(ad4695_oversampling_ratios); + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -1217,6 +1483,26 @@ static int ad4695_debugfs_reg_access(struct iio_dev *indio_dev, return -EINVAL; } +static int ad4695_get_current_scan_type(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad4695_state *st = iio_priv(indio_dev); + unsigned int osr = st->channels_cfg[chan->scan_index].oversampling_ratio; + + switch (osr) { + case 1: + return AD4695_SCAN_TYPE_OSR_1; + case 4: + return AD4695_SCAN_TYPE_OSR_4; + case 16: + return AD4695_SCAN_TYPE_OSR_16; + case 64: + return AD4695_SCAN_TYPE_OSR_64; + default: + return -EINVAL; + } +} + static const struct iio_info ad4695_info = { .read_raw = &ad4695_read_raw, .write_raw_get_fmt = &ad4695_write_raw_get_fmt, @@ -1225,6 +1511,15 @@ static const struct iio_info ad4695_info = { .debugfs_reg_access = &ad4695_debugfs_reg_access, }; +static const struct iio_info ad4695_offload_info = { + .read_raw = &ad4695_read_raw, + .write_raw_get_fmt = &ad4695_write_raw_get_fmt, + .write_raw = &ad4695_write_raw, + .get_current_scan_type = &ad4695_get_current_scan_type, + .read_avail = &ad4695_read_avail, + .debugfs_reg_access = &ad4695_debugfs_reg_access, +}; + static int ad4695_parse_channel_cfg(struct ad4695_state *st) { struct device *dev = &st->spi->dev; @@ -1240,6 +1535,9 @@ static int ad4695_parse_channel_cfg(struct ad4695_state *st) chan_cfg->highz_en = true; chan_cfg->channel = i; + /* This is the default OSR after reset */ + chan_cfg->oversampling_ratio = 1; + *iio_chan = ad4695_channel_template; iio_chan->channel = i; iio_chan->scan_index = i; @@ -1408,6 +1706,7 @@ static int ad4695_probe_spi_offload(struct iio_dev *indio_dev, struct dma_chan *rx_dma; int ret, i; + indio_dev->info = &ad4695_offload_info; indio_dev->num_channels = st->chip_info->num_voltage_inputs + 1; indio_dev->setup_ops = &ad4695_offload_buffer_setup_ops; @@ -1458,6 +1757,7 @@ static int ad4695_probe_spi_offload(struct iio_dev *indio_dev, for (i = 0; i < indio_dev->num_channels; i++) { struct iio_chan_spec *chan = &st->iio_chan[i]; + struct ad4695_channel_config *cfg = &st->channels_cfg[i]; /* * NB: When using offload support, all channels need to have the @@ -1473,6 +1773,24 @@ static int ad4695_probe_spi_offload(struct iio_dev *indio_dev, /* add sample frequency for PWM CNV trigger */ chan->info_mask_separate |= BIT(IIO_CHAN_INFO_SAMP_FREQ); chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_SAMP_FREQ); + + /* Add the oversampling properties only for voltage channels */ + if (chan->type != IIO_VOLTAGE) + continue; + + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + chan->info_mask_separate_available |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + chan->has_ext_scan_type = 1; + if (cfg->bipolar) { + chan->ext_scan_type = ad4695_scan_type_offload_s; + chan->num_ext_scan_type = + ARRAY_SIZE(ad4695_scan_type_offload_s); + } else { + chan->ext_scan_type = ad4695_scan_type_offload_u; + chan->num_ext_scan_type = + ARRAY_SIZE(ad4695_scan_type_offload_u); + } } return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, -- 2.39.5