/* * AD4170 registers * Multibyte register addresses point to the most significant byte which is the * address to use to get the most significant byte first (address accessed is * decremented by one for each data byte) * * Each register address define follows the AD4170_<REG_NAME>_REG format. * Each mask follows the AD4170_<REG_NAME>_<FIELD_NAME> format. * E.g. AD4170_PIN_MUXING_DIG_AUX1_CTRL_MSK is for accessing DIG_AUX1_CTRL field * of PIN_MUXING_REG. * Each constant follows the AD4170_<REG_NAME>_<FIELD_NAME>_<FUNCTION> format. * E.g. AD4170_PIN_MUXING_DIG_AUX1_DISABLED is the value written to * DIG_AUX1_CTRL field of PIN_MUXING register to disable DIG_AUX1 pin. * Some register names and register field names are shortened versions of * their datasheet counterpart names to provide better code readability.
*/ #define AD4170_CONFIG_A_REG 0x00 #define AD4170_DATA_24B_REG 0x1E #define AD4170_PIN_MUXING_REG 0x69 #define AD4170_CLOCK_CTRL_REG 0x6B #define AD4170_ADC_CTRL_REG 0x71 #define AD4170_CHAN_EN_REG 0x79 #define AD4170_CHAN_SETUP_REG(x) (0x81 + 4 * (x)) #define AD4170_CHAN_MAP_REG(x) (0x83 + 4 * (x)) #define AD4170_MISC_REG(x) (0xC1 + 14 * (x)) #define AD4170_AFE_REG(x) (0xC3 + 14 * (x)) #define AD4170_FILTER_REG(x) (0xC5 + 14 * (x)) #define AD4170_FILTER_FS_REG(x) (0xC7 + 14 * (x)) #define AD4170_OFFSET_REG(x) (0xCA + 14 * (x)) #define AD4170_GAIN_REG(x) (0xCD + 14 * (x)) #define AD4170_V_BIAS_REG 0x135 #define AD4170_CURRENT_SRC_REG(x) (0x139 + 2 * (x)) #define AD4170_GPIO_MODE_REG 0x191 #define AD4170_GPIO_OUTPUT_REG 0x193 #define AD4170_GPIO_INPUT_REG 0x195 #define AD4170_ADC_CTRL_CONT_READ_EXIT_REG 0x200 /* virtual reg */
/* * There are 8 of each MISC, AFE, FILTER, FILTER_FS, OFFSET, and GAIN * configuration registers. That is, there are 8 miscellaneous registers, MISC0 * to MISC7. Each MISC register is associated with a setup; MISCN is associated * with setup number N. The other 5 above mentioned types of registers have * analogous structure. A setup is a set of those registers. For example, * setup 1 comprises of MISC1, AFE1, FILTER1, FILTER_FS1, OFFSET1, and GAIN1 * registers. Also, there are 16 CHANNEL_SETUP registers (CHANNEL_SETUP0 to * CHANNEL_SETUP15). Each channel setup is associated with one of the 8 possible * setups. Thus, AD4170 can support up to 16 channels but, since there are only * 8 available setups, channels must share settings if more than 8 channels are * configured. * * If this struct is modified, ad4170_setup_eq() will probably need to be * updated too.
*/ struct ad4170_setup {
u16 misc;
u16 afe;
u16 filter;
u16 filter_fs;
u32 offset; /* For calibration purposes */
u32 gain; /* For calibration purposes */
};
/* * The ODR can be calculated the same way for sinc5+avg, sinc5, and * sinc3 filter types with the exception that sinc5 filter has a * narrowed range of allowed FILTER_FS values.
*/ for (i = 0; i < ARRAY_SIZE(ad4170_sinc3_filt_fs_tbl); i++) {
tmp0 = div_u64_rem(st->mclk_hz, 32 * ad4170_sinc3_filt_fs_tbl[i],
&tmp1);
tmp1 = mult_frac(tmp1, MICRO, 32 * ad4170_sinc3_filt_fs_tbl[i]); /* Fill sinc5+avg filter SPS table */
st->sps_tbl[AD4170_SINC5_AVG][i][0] = tmp0; /* Integer part */
st->sps_tbl[AD4170_SINC5_AVG][i][1] = tmp1; /* Fractional part */
/* Fill sinc3 filter SPS table */
st->sps_tbl[AD4170_SINC3][i][0] = tmp0; /* Integer part */
st->sps_tbl[AD4170_SINC3][i][1] = tmp1; /* Fractional part */
} /* Sinc5 filter ODR doesn't use all FILTER_FS bits */ for (i = 0; i < ARRAY_SIZE(ad4170_sinc5_filt_fs_tbl); i++) {
tmp0 = div_u64_rem(st->mclk_hz, 32 * ad4170_sinc5_filt_fs_tbl[i],
&tmp1);
tmp1 = mult_frac(tmp1, MICRO, 32 * ad4170_sinc5_filt_fs_tbl[i]); /* Fill sinc5 filter SPS table */
st->sps_tbl[AD4170_SINC5][i][0] = tmp0; /* Integer part */
st->sps_tbl[AD4170_SINC5][i][1] = tmp1; /* Fractional part */
}
}
for (i = 0; i < AD4170_MAX_SETUPS; i++) { struct ad4170_setup_info *setup_info = &st->setup_infos[i];
/* Immediately accept a matching setup. */ if (ad4170_setup_eq(target_setup, &setup_info->setup)) {
*setup_num = i; return 0;
}
/* Ignore all setups which are used by enabled channels. */ if (setup_info->enabled_channels) continue;
/* Find the least used slot. */ if (*setup_num == AD4170_INVALID_SETUP ||
setup_info->channels < st->setup_infos[*setup_num].channels)
*setup_num = i;
}
if (*setup_num == AD4170_INVALID_SETUP) return -EINVAL;
/* * It is recommended to place the ADC in standby mode or idle mode to * write to OFFSET and GAIN registers.
*/
ret = regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_MODE_MSK,
FIELD_PREP(AD4170_ADC_CTRL_MODE_MSK,
AD4170_ADC_CTRL_MODE_IDLE)); if (ret) return ret;
ret = regmap_write(st->regmap, AD4170_MISC_REG(setup_num), setup->misc); if (ret) return ret;
ret = regmap_write(st->regmap, AD4170_AFE_REG(setup_num), setup->afe); if (ret) return ret;
ret = regmap_write(st->regmap, AD4170_FILTER_REG(setup_num),
setup->filter); if (ret) return ret;
ret = regmap_write(st->regmap, AD4170_FILTER_FS_REG(setup_num),
setup->filter_fs); if (ret) return ret;
ret = regmap_write(st->regmap, AD4170_OFFSET_REG(setup_num),
setup->offset); if (ret) return ret;
ret = regmap_write(st->regmap, AD4170_GAIN_REG(setup_num), setup->gain); if (ret) return ret;
staticint ad4170_write_channel_setup(struct ad4170_state *st, unsignedint chan_addr, bool on_enable)
{ struct ad4170_chan_info *chan_info = &st->chan_infos[chan_addr]; bool overwrite; int setup_num; int ret;
/* * Similar to AD4130 driver, the following cases need to be handled. * * 1. Enabled and linked channel with setup changes: * - Find a setup. If not possible, return error. * - Unlink channel from current setup. * - If the setup found has only disabled channels linked to it, * unlink all channels, and write the new setup to it. * - Link channel to new setup. * * 2. Soon to be enabled and unlinked channel: * - Find a setup. If not possible, return error. * - If the setup found has only disabled channels linked to it, * unlink all channels, and write the new setup to it. * - Link channel to the setup. * * 3. Disabled and linked channel with setup changes: * - Unlink channel from current setup. * * 4. Soon to be enabled and linked channel: * 5. Disabled and unlinked channel with setup changes: * - Do nothing.
*/
/* Cases 3, 4, and 5 */ if (chan_info->setup_num != AD4170_INVALID_SETUP) { /* Case 4 */ if (on_enable) return 0;
/* Case 3 */ if (!chan_info->enabled) {
ad4170_unlink_channel(st, chan_addr); return 0;
}
} elseif (!on_enable && !chan_info->enabled) { /* Case 5 */ return 0;
}
/* Cases 1 & 2 */
ret = ad4170_find_setup(st, &chan_info->setup, &setup_num, &overwrite); if (ret) return ret;
if (chan_info->setup_num != AD4170_INVALID_SETUP) /* Case 1 */
ad4170_unlink_channel(st, chan_addr);
if (overwrite) {
ret = ad4170_unlink_setup(st, setup_num); if (ret) return ret;
ret = ad4170_write_setup(st, setup_num, &chan_info->setup); if (ret) return ret;
}
switch (val) { case AD4170_SINC5_AVG:
filter_type_conf = AD4170_FILTER_FILTER_TYPE_SINC5_AVG; break; case AD4170_SINC5:
filter_type_conf = AD4170_FILTER_FILTER_TYPE_SINC5; break; case AD4170_SINC3:
filter_type_conf = AD4170_FILTER_FILTER_TYPE_SINC3; break; default: return -EINVAL;
}
/* * The filters provide the same ODR for a given filter_fs value but * there are different minimum and maximum filter_fs limits for each * filter. The filter_fs value will be adjusted if the current filter_fs * is out of the limits of the just requested filter. Since the * filter_fs value affects the ODR (sampling_frequency), changing the * filter may lead to a change in the sampling frequency.
*/
scoped_guard(mutex, &st->lock) { if (!iio_device_claim_direct(indio_dev)) return -EBUSY;
if (val == AD4170_SINC5_AVG || val == AD4170_SINC3)
setup->filter_fs = clamp(val, AD4170_SINC3_MIN_FS,
AD4170_SINC3_MAX_FS); else
setup->filter_fs = clamp(val, AD4170_SINC5_MIN_FS,
AD4170_SINC5_MAX_FS);
/* * Receives the number of a multiplexed AD4170 input (ain_n), and stores the * voltage (in µV) of the specified input into ain_voltage. If the input number * is a ordinary analog input (AIN0 to AIN8), stores zero into ain_voltage. * If a voltage regulator required by a special input is unavailable, return * error code. Return 0 on success.
*/ staticint ad4170_get_ain_voltage_uv(struct ad4170_state *st, int ain_n, int *ain_voltage)
{ struct device *dev = &st->spi->dev; int v_diff;
*ain_voltage = 0; /* * The voltage bias (vbias) sets the common-mode voltage of the channel * to (AVDD + AVSS)/2. If provided, AVSS supply provides the magnitude * (absolute value) of the negative voltage supplied to the AVSS pin. * So, we do AVDD - AVSS to compute the DC voltage generated by the bias * voltage generator.
*/ if (st->pins_fn[ain_n] & AD4170_PIN_VBIAS) { int v_diff = st->vrefs_uv[AD4170_AVDD_SUP] - st->vrefs_uv[AD4170_AVSS_SUP];
*ain_voltage = v_diff / 2; return 0;
}
if (ain_n <= AD4170_CHAN_MAP_TEMP_SENSOR) return 0;
switch (ain_n) { case AD4170_CHAN_MAP_AVDD_AVSS_N:
v_diff = st->vrefs_uv[AD4170_AVDD_SUP] - st->vrefs_uv[AD4170_AVSS_SUP];
*ain_voltage = v_diff / 5; return 0; case AD4170_CHAN_MAP_IOVDD_DGND_N:
*ain_voltage = st->vrefs_uv[AD4170_IOVDD_SUP] / 5; return 0; case AD4170_CHAN_MAP_AVSS:
*ain_voltage = st->vrefs_uv[AD4170_AVSS_SUP]; return 0; case AD4170_CHAN_MAP_DGND:
*ain_voltage = 0; return 0; case AD4170_CHAN_MAP_REFIN1_P: if (st->vrefs_uv[AD4170_REFIN1P_SUP] == -ENODEV) return dev_err_probe(dev, -ENODEV, "input set to REFIN+ but ref not provided\n");
*ain_voltage = st->vrefs_uv[AD4170_REFIN1P_SUP]; return 0; case AD4170_CHAN_MAP_REFIN1_N: if (st->vrefs_uv[AD4170_REFIN1N_SUP] == -ENODEV) return dev_err_probe(dev, -ENODEV, "input set to REFIN- but ref not provided\n");
*ain_voltage = st->vrefs_uv[AD4170_REFIN1N_SUP]; return 0; case AD4170_CHAN_MAP_REFIN2_P: if (st->vrefs_uv[AD4170_REFIN2P_SUP] == -ENODEV) return dev_err_probe(dev, -ENODEV, "input set to REFIN2+ but ref not provided\n");
*ain_voltage = st->vrefs_uv[AD4170_REFIN2P_SUP]; return 0; case AD4170_CHAN_MAP_REFIN2_N: if (st->vrefs_uv[AD4170_REFIN2N_SUP] == -ENODEV) return dev_err_probe(dev, -ENODEV, "input set to REFIN2- but ref not provided\n");
*ain_voltage = st->vrefs_uv[AD4170_REFIN2N_SUP]; return 0; case AD4170_CHAN_MAP_REFOUT: /* REFOUT is 2.5V relative to AVSS so take that into account */
*ain_voltage = st->vrefs_uv[AD4170_AVSS_SUP] + AD4170_INT_REF_2_5V; return 0; default: return -EINVAL;
}
}
staticint ad4170_validate_analog_input(struct ad4170_state *st, int pin)
{ if (pin <= AD4170_MAX_ANALOG_PINS) { if (st->pins_fn[pin] & AD4170_PIN_CURRENT_OUT) return dev_err_probe(&st->spi->dev, -EINVAL, "Pin %d already used with fn %u.\n",
pin, st->pins_fn[pin]);
staticint ad4170_validate_channel_input(struct ad4170_state *st, int pin, bool com)
{ /* Check common-mode input pin is mapped to a special input. */ if (com && (pin < AD4170_CHAN_MAP_AVDD_AVSS_P || pin > AD4170_CHAN_MAP_REFOUT)) return dev_err_probe(&st->spi->dev, -EINVAL, "Invalid common-mode input pin number. %d\n",
pin);
/* Check differential input pin is mapped to a analog input pin. */ if (!com && pin > AD4170_MAX_ANALOG_PINS) return dev_err_probe(&st->spi->dev, -EINVAL, "Invalid analog input pin number. %d\n",
pin);
return ad4170_validate_analog_input(st, pin);
}
/* * Verifies whether the channel input configuration is valid by checking the * input numbers. * Returns 0 on valid channel input configuration. -EINVAL otherwise.
*/ staticint ad4170_validate_channel(struct ad4170_state *st, struct iio_chan_spec const *chan)
{ int ret;
ret = ad4170_validate_channel_input(st, chan->channel, false); if (ret) return ret;
/* * Verifies whether the channel configuration is valid by checking the provided * input type, polarity, and voltage references result in a sane input range. * Returns negative error code on failure.
*/ staticint ad4170_get_input_range(struct ad4170_state *st, struct iio_chan_spec const *chan, unsignedint ch_reg, unsignedint ref_sel)
{ bool bipolar = chan->scan_type.sign == 's'; struct device *dev = &st->spi->dev; int refp, refn, ain_voltage, ret;
switch (ref_sel) { case AD4170_REF_REFIN1: if (st->vrefs_uv[AD4170_REFIN1P_SUP] == -ENODEV ||
st->vrefs_uv[AD4170_REFIN1N_SUP] == -ENODEV) return dev_err_probe(dev, -ENODEV, "REFIN± selected but not provided\n");
refp = st->vrefs_uv[AD4170_REFIN1P_SUP];
refn = st->vrefs_uv[AD4170_REFIN1N_SUP]; break; case AD4170_REF_REFIN2: if (st->vrefs_uv[AD4170_REFIN2P_SUP] == -ENODEV ||
st->vrefs_uv[AD4170_REFIN2N_SUP] == -ENODEV) return dev_err_probe(dev, -ENODEV, "REFIN2± selected but not provided\n");
refp = st->vrefs_uv[AD4170_REFIN2P_SUP];
refn = st->vrefs_uv[AD4170_REFIN2N_SUP]; break; case AD4170_REF_AVDD:
refp = st->vrefs_uv[AD4170_AVDD_SUP];
refn = st->vrefs_uv[AD4170_AVSS_SUP]; break; case AD4170_REF_REFOUT: /* REFOUT is 2.5 V relative to AVSS */
refp = st->vrefs_uv[AD4170_AVSS_SUP] + AD4170_INT_REF_2_5V;
refn = st->vrefs_uv[AD4170_AVSS_SUP]; break; default: return -EINVAL;
}
/* * Find out the analog input range from the channel type, polarity, and * voltage reference selection. * AD4170 channels are either differential or pseudo-differential. * Diff input voltage range: −VREF/gain to +VREF/gain (datasheet page 6) * Pseudo-diff input voltage range: 0 to VREF/gain (datasheet page 6)
*/ if (chan->differential) { if (!bipolar) return dev_err_probe(dev, -EINVAL, "Channel %u differential unipolar\n",
ch_reg);
/* * Differential bipolar channel. * avss-supply is never above 0V. * Assuming refin1n-supply not above 0V. * Assuming refin2n-supply not above 0V.
*/ return refp + abs(refn);
} /* * Some configurations can lead to invalid setups. * For example, if AVSS = -2.5V, REF_SELECT set to REFOUT (REFOUT/AVSS), * and pseudo-diff channel configuration set, then the input range * should go from 0V to +VREF (single-ended - datasheet pg 10), but * REFOUT/AVSS range would be -2.5V to 0V. * Check the positive reference is higher than 0V for pseudo-diff * channels. * Note that at this point in the code, refp can only be >= 0 since all * error codes from reading the regulator voltage have been checked * either at ad4170_regulator_setup() or above in this function.
*/ if (refp == 0) return dev_err_probe(dev, -EINVAL, "REF+ == GND for pseudo-diff chan %u\n",
ch_reg);
if (bipolar) return refp;
/* * Pseudo-differential unipolar channel. * Input expected to swing from IN- to +VREF.
*/
ret = ad4170_get_ain_voltage_uv(st, chan->channel2, &ain_voltage); if (ret) return ret;
if (refp - ain_voltage <= 0) return dev_err_probe(dev, -EINVAL, "Negative input >= REF+ for pseudo-diff chan %u\n",
ch_reg);
return refp - ain_voltage;
}
staticint __ad4170_read_sample(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val)
{ struct ad4170_state *st = iio_priv(indio_dev); unsignedlong settling_time_ms; int ret;
reinit_completion(&st->completion);
ret = regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_MODE_MSK,
FIELD_PREP(AD4170_ADC_CTRL_MODE_MSK,
AD4170_ADC_CTRL_MODE_SINGLE)); if (ret) return ret;
/* * When a channel is manually selected by the user, the ADC needs an * extra time to provide the first stable conversion. The ADC settling * time depends on the filter type, filter frequency, and ADC clock * frequency (see datasheet page 53). The maximum settling time among * all filter configurations is 6291164 / fCLK. Use that formula to wait * for sufficient time whatever the filter configuration may be.
*/
settling_time_ms = DIV_ROUND_UP(6291164 * MILLI, st->mclk_hz);
ret = wait_for_completion_timeout(&st->completion,
msecs_to_jiffies(settling_time_ms)); if (!ret)
dev_dbg(&st->spi->dev, "No Data Ready signal. Reading after delay.\n");
ret = regmap_read(st->regmap, AD4170_DATA_24B_REG, val); if (ret) return ret;
if (chan->scan_type.sign == 's')
*val = sign_extend32(*val, chan->scan_type.realbits - 1);
/* * The ADC sequences through all enabled channels. That can lead to * incorrect channel being sampled if a previous read would have left a * different channel enabled. Thus, always enable and disable the * channel on single-shot read.
*/
ret = ad4170_set_channel_enable(st, chan->address, true); if (ret) return ret;
ret = __ad4170_read_sample(indio_dev, chan, val); if (ret) {
dev_err(dev, "failed to read sample: %d\n", ret);
ret2 = ad4170_set_channel_enable(st, chan->address, false); if (ret2)
dev_err(dev, "failed to disable channel: %d\n", ret2);
return ret;
}
ret = ad4170_set_channel_enable(st, chan->address, false); if (ret) return ret;
return IIO_VAL_INT;
}
staticint ad4170_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info)
{ struct ad4170_state *st = iio_priv(indio_dev); struct ad4170_chan_info *chan_info = &st->chan_infos[chan->address]; struct ad4170_setup *setup = &chan_info->setup; enum ad4170_filter_type f_type; unsignedint pga, fs_idx; int ret;
guard(mutex)(&st->lock); switch (info) { case IIO_CHAN_INFO_RAW: if (!iio_device_claim_direct(indio_dev)) return -EBUSY;
ret = ad4170_read_sample(indio_dev, chan, val);
iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SCALE:
pga = FIELD_GET(AD4170_AFE_PGA_GAIN_MSK, setup->afe); switch (chan->type) { case IIO_VOLTAGE:
*val = chan_info->scale_tbl[pga][0];
*val2 = chan_info->scale_tbl[pga][1]; return IIO_VAL_INT_PLUS_NANO; case IIO_TEMP: /* * The scale_tbl converts output codes to mV units so * multiply by MILLI to make the factor convert to µV. * Then, apply the temperature sensor change sensitivity * of 477 μV/K. Finally, multiply the result by MILLI * again to comply with milli degrees Celsius IIO ABI.
*/
*val = 0;
*val2 = DIV_ROUND_CLOSEST(chan_info->scale_tbl[pga][1] * MILLI, 477) *
MILLI; return IIO_VAL_INT_PLUS_NANO; default: return -EINVAL;
} case IIO_CHAN_INFO_OFFSET:
pga = FIELD_GET(AD4170_AFE_PGA_GAIN_MSK, setup->afe);
*val = chan_info->offset_tbl[pga]; return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ:
f_type = __ad4170_get_filter_type(setup->filter); switch (f_type) { case AD4170_SINC5_AVG: case AD4170_SINC3:
fs_idx = find_closest(setup->filter_fs,
ad4170_sinc3_filt_fs_tbl,
ARRAY_SIZE(ad4170_sinc3_filt_fs_tbl));
*val = st->sps_tbl[f_type][fs_idx][0];
*val2 = st->sps_tbl[f_type][fs_idx][1]; return IIO_VAL_INT_PLUS_MICRO; case AD4170_SINC5:
fs_idx = find_closest(setup->filter_fs,
ad4170_sinc5_filt_fs_tbl,
ARRAY_SIZE(ad4170_sinc5_filt_fs_tbl));
*val = st->sps_tbl[f_type][fs_idx][0];
*val2 = st->sps_tbl[f_type][fs_idx][1]; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL;
} case IIO_CHAN_INFO_CALIBBIAS:
*val = setup->offset; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBSCALE:
*val = setup->gain; return IIO_VAL_INT; default: return -EINVAL;
}
}
ainm_voltage = 0;
ret = ad4170_get_ain_voltage_uv(st, chan->channel2, &ainm_voltage); if (ret < 0) return dev_err_probe(dev, ret, "Failed to fill scale table\n");
/* * The PGA options are numbered from 0 to 9, with option 0 being * a gain of 2^0 (no actual gain), and 7 meaning a gain of 2^7. * Option 8, though, sets a gain of 0.5, so the input signal can * be attenuated by 2 rather than amplified. Option 9, allows * the signal to bypass the PGA circuitry (no gain). * * The scale factor to get ADC output codes to values in mV * units is given by: * _scale = (input_range / gain) / 2^precision * AD4170 gain is a power of 2 so the above can be written as * _scale = input_range / 2^(precision + gain) * Keep the input range in µV to avoid truncating the less * significant bits when right shifting it so to preserve scale * precision.
*/
nv = (u64)chan_info->input_range_uv * NANO;
lshift = !!(pga & BIT(3)); /* handle PGA options 8 and 9 */
rshift = precision_bits - bipolar + (pga & GENMASK(2, 0)) - lshift;
chan_info->scale_tbl[pga][0] = 0;
chan_info->scale_tbl[pga][1] = div_u64(nv >> rshift, MILLI);
/* * If the negative input is not at GND, the conversion result * (which is relative to IN-) will be offset by the level at IN-. * Use the scale factor the other way around to go from a known * voltage to the corresponding ADC output code. * With that, we are able to get to what would be the output * code for the voltage at the negative input. * If the negative input is not fixed, there is no offset.
*/
offset = ((unsignedlonglong)abs(ainm_voltage)) * MICRO;
offset = DIV_ROUND_CLOSEST_ULL(offset, chan_info->scale_tbl[pga][1]);
/* * After divided by the scale, offset will always fit into 31 * bits. For _raw + _offset to be relative to GND, the value * provided as _offset is of opposite sign than the real offset.
*/ if (ainm_voltage > 0)
chan_info->offset_tbl[pga] = -(int)(offset); else
chan_info->offset_tbl[pga] = (int)(offset);
} return 0;
}
staticint ad4170_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, constint **vals, int *type, int *length, long info)
{ struct ad4170_state *st = iio_priv(indio_dev); struct ad4170_chan_info *chan_info = &st->chan_infos[chan->address]; enum ad4170_filter_type f_type;
switch (info) { case IIO_CHAN_INFO_SCALE:
*vals = (int *)chan_info->scale_tbl;
*length = ARRAY_SIZE(chan_info->scale_tbl) * 2;
*type = IIO_VAL_INT_PLUS_NANO; return IIO_AVAIL_LIST; case IIO_CHAN_INFO_SAMP_FREQ:
*type = IIO_VAL_INT_PLUS_MICRO;
f_type = ad4170_get_filter_type(indio_dev, chan); switch (f_type) { case AD4170_SINC5_AVG: case AD4170_SINC3: /* Read sps_tbl here to ensure in bounds array access */
*vals = (int *)st->sps_tbl[f_type];
*length = ARRAY_SIZE(ad4170_sinc3_filt_fs_tbl) * 2; return IIO_AVAIL_LIST; case AD4170_SINC5: /* Read sps_tbl here to ensure in bounds array access */
*vals = (int *)st->sps_tbl[f_type];
*length = ARRAY_SIZE(ad4170_sinc5_filt_fs_tbl) * 2; return IIO_AVAIL_LIST; default: return -EINVAL;
} default: return -EINVAL;
}
}
switch (f_type) { case AD4170_SINC5_AVG: case AD4170_SINC3:
filt_fs_tbl_size = ARRAY_SIZE(ad4170_sinc3_filt_fs_tbl); break; case AD4170_SINC5:
filt_fs_tbl_size = ARRAY_SIZE(ad4170_sinc5_filt_fs_tbl); break;
}
for (i = 0; i < filt_fs_tbl_size; i++) { if (st->sps_tbl[f_type][i][0] == val &&
st->sps_tbl[f_type][i][1] == val2) break;
} if (i == filt_fs_tbl_size) return -EINVAL;
if (!iio_device_claim_direct(indio_dev)) return -EBUSY;
ret = regmap_read(st->regmap, AD4170_GPIO_MODE_REG, &val); if (ret) goto err_release;
/* * If the GPIO is configured as an input, read the current value from * AD4170_GPIO_INPUT_REG. Otherwise, read the input value from * AD4170_GPIO_OUTPUT_REG.
*/ if (val & BIT(offset * 2))
ret = regmap_read(st->regmap, AD4170_GPIO_INPUT_REG, &val); else
ret = regmap_read(st->regmap, AD4170_GPIO_OUTPUT_REG, &val); if (ret) goto err_release;
ret = !!(val & BIT(offset));
err_release:
iio_device_release_direct(indio_dev);
/* Only expose GPIOs that were not assigned any other function. */ for (i = 0; i < ngpios; i++) { bool valid = st->gpio_fn[i] == AD4170_GPIO_UNASSIGNED;
/* Check the pin number is valid */ for (i = 0; i < ARRAY_SIZE(ad4170_iout_pin_tbl); i++) if (ad4170_iout_pin_tbl[i] == pin) break;
if (i == ARRAY_SIZE(ad4170_iout_pin_tbl)) return dev_err_probe(dev, -EINVAL, "Invalid excitation pin: %u\n",
pin);
/* Check the pin is available */ if (pin <= AD4170_MAX_ANALOG_PINS) { if (st->pins_fn[pin] != AD4170_PIN_UNASSIGNED) return dev_err_probe(dev, -EINVAL, "Pin %u already used with fn %u\n",
pin, st->pins_fn[pin]);
/* * Parses firmware data describing output current source setup. There are 4 * excitation currents (IOUT0 to IOUT3) that can be configured independently. * Excitation currents are added if they are output on the same pin.
*/ staticint ad4170_parse_exc_current(struct ad4170_state *st, struct fwnode_handle *child, unsignedint *exc_pins, unsignedint *exc_curs, unsignedint *num_exc_pins)
{ struct device *dev = &st->spi->dev; unsignedint num_pins, i, j;
u32 pin, val; int ret;
num_pins = 0; for (i = 0; i < AD4170_NUM_CURRENT_SRC; i++) { /* Parse excitation current output pin properties. */
pin = AD4170_CURRENT_SRC_I_OUT_PIN_AIN(0);
ret = fwnode_property_read_u32(child, ad4170_i_out_pin_dt_props[i],
&pin); if (ret) continue;
exc_pins[num_pins] = pin;
/* Parse excitation current value properties. */
val = ad4170_iout_current_ua_tbl[0];
fwnode_property_read_u32(child,
ad4170_i_out_val_dt_props[i], &val);
for (j = 0; j < ARRAY_SIZE(ad4170_iout_current_ua_tbl); j++) if (ad4170_iout_current_ua_tbl[j] == val) break;
if (num_exc_pins < 2) return dev_err_probe(&st->spi->dev, -EINVAL, "Current chopping requested but only one pin provided: %u\n",
exc_pins[0]);
/* * Two use cases to handle here: * - 2 pairs of excitation currents; * - 1 pair of excitation currents.
*/ if (num_exc_pins == 4) { for (i = 0; i < AD4170_NUM_CURRENT_SRC; i++) if (st->cur_src_pins[i] != exc_pins[i]) return dev_err_probe(&st->spi->dev, -EINVAL, "Unable to use 4 exc pins\n");
} else { /* * Excitation current chopping is configured in pairs. Current * sources IOUT0 and IOUT1 form pair 1, IOUT2 and IOUT3 make up * pair 2. So, if current chopping was requested, check if the * first end of the first pair of excitation currents is * available. Try the next pair if IOUT0 has already been * configured for another channel.
*/
i = st->cur_src_pins[0] == exc_pins[0] ? 0 : 2;
if (st->cur_src_pins[i] != exc_pins[0] ||
st->cur_src_pins[i + 1] != exc_pins[1]) return dev_err_probe(&st->spi->dev, -EINVAL, "Failed to setup current chopping\n");
if (i == 0)
exc_cur_pair = AD4170_MISC_CHOP_IEXC_PAIR1; else
exc_cur_pair = AD4170_MISC_CHOP_IEXC_PAIR2;
}
/* * Configure excitation current chopping. * Chop both pairs if using four excitation pins.
*/
setup->misc |= FIELD_PREP(AD4170_MISC_CHOP_IEXC_MSK,
num_exc_pins == 2 ?
exc_cur_pair :
AD4170_MISC_CHOP_IEXC_BOTH);
/* * If a specific current is provided through * adi,excitation-current-n-microamp, set excitation pins provided * through adi,excitation-pin-n to excite the bridge circuit.
*/ for (i = 0; i < num_exc_pins; i++) if (exc_curs[i] > 0) return ad4170_setup_current_src(st, child, setup, exc_pins,
exc_curs, num_exc_pins,
ac_excited);
/* * Else, use predefined ACX1, ACX1 negated, ACX2, ACX2 negated signals * to AC excite the bridge. Those signals are output on GPIO2, GPIO0, * GPIO3, and GPIO1, respectively. If only two pins are specified for AC * excitation, use ACX1 and ACX2 (GPIO2 and GPIO3). * * Also, to avoid any short-circuit condition when more than one channel * is enabled, set GPIO2 and GPIO0 high, and set GPIO1 and GPIO3 low to * DC excite the bridge whenever a channel without AC excitation is * selected. That is needed because GPIO pins are controlled by the next * highest priority GPIO function when a channel doesn't enable AC * excitation. See datasheet Figure 113 Weigh Scale (AC Excitation) for * the reference circuit diagram.
*/ if (num_exc_pins == 2) {
setup->misc |= FIELD_PREP(AD4170_MISC_CHOP_ADC_MSK, 0x3);
gpio_mask = AD4170_GPIO_MODE_GPIO3_MSK | AD4170_GPIO_MODE_GPIO2_MSK;
ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG, gpio_mask,
FIELD_PREP(AD4170_GPIO_MODE_GPIO3_MSK,
AD4170_GPIO_MODE_GPIO_OUTPUT) |
FIELD_PREP(AD4170_GPIO_MODE_GPIO2_MSK,
AD4170_GPIO_MODE_GPIO_OUTPUT)); if (ret) return ret;
/* * Set GPIO2 high and GPIO3 low to DC excite the bridge when * a different channel is selected.
*/
gpio_mask = AD4170_GPIO_OUTPUT_GPIO_MSK(3) |
AD4170_GPIO_OUTPUT_GPIO_MSK(2);
ret = regmap_update_bits(st->regmap, AD4170_GPIO_OUTPUT_REG, gpio_mask,
FIELD_PREP(AD4170_GPIO_OUTPUT_GPIO_MSK(3), 0) |
FIELD_PREP(AD4170_GPIO_OUTPUT_GPIO_MSK(2), 1)); if (ret) return ret;
/* * Set GPIO2 and GPIO0 high, and set GPIO1 and GPIO3 low to DC * excite the bridge when a different channel is selected.
*/
gpio_mask = AD4170_GPIO_OUTPUT_GPIO_MSK(3) |
AD4170_GPIO_OUTPUT_GPIO_MSK(2) |
AD4170_GPIO_OUTPUT_GPIO_MSK(1) |
AD4170_GPIO_OUTPUT_GPIO_MSK(0);
ret = regmap_update_bits(st->regmap, AD4170_GPIO_OUTPUT_REG, gpio_mask,
FIELD_PREP(AD4170_GPIO_OUTPUT_GPIO_MSK(3), 0) |
FIELD_PREP(AD4170_GPIO_OUTPUT_GPIO_MSK(2), 1) |
FIELD_PREP(AD4170_GPIO_OUTPUT_GPIO_MSK(1), 0) |
FIELD_PREP(AD4170_GPIO_OUTPUT_GPIO_MSK(0), 1)); if (ret) return ret;
propname = "single-channel";
propname2 = "diff-channels"; if (!fwnode_property_present(child, propname) &&
!fwnode_property_present(child, propname2)) return dev_err_probe(dev, -EINVAL, "Channel must define one of %s or %s.\n",
propname, propname2);
/* Parse differential channel configuration */
ret = fwnode_property_read_u32_array(child, propname2, pins,
ARRAY_SIZE(pins)); if (!ret) {
chan->differential = true;
chan->channel = pins[0];
chan->channel2 = pins[1]; return 0;
} /* Failed to parse diff chan so try pseudo-diff chan props */
propname2 = "common-mode-channel"; if (fwnode_property_present(child, propname) &&
!fwnode_property_present(child, propname2)) return dev_err_probe(dev, -EINVAL, "When %s is defined, %s must be defined too\n",
propname, propname2);
setup = &chan_info->setup;
ret = ad4170_parse_reference(st, child, setup); if (ret) return ret;
ret = fwnode_property_match_property_string(child, "adi,sensor-type",
ad4170_sensor_type,
ARRAY_SIZE(ad4170_sensor_type));
/* Default to conventional ADC channel if sensor type not present */
s_type = ret < 0 ? AD4170_ADC_SENSOR : ret; switch (s_type) { case AD4170_ADC_SENSOR:
ret = ad4170_parse_adc_channel_type(dev, child, chan); if (ret) return ret;
break; case AD4170_WEIGH_SCALE_SENSOR: case AD4170_THERMOCOUPLE_SENSOR: case AD4170_RTD_SENSOR:
ret = ad4170_parse_external_sensor(st, child, setup, chan, s_type); if (ret) return ret;
if (num_channels > AD4170_MAX_ADC_CHANNELS) return dev_err_probe(dev, -EINVAL, "Too many channels\n");
/* Add one for temperature */
num_channels = min(num_channels + 1, AD4170_MAX_ADC_CHANNELS);
chan_num = 0;
device_for_each_child_node_scoped(dev, child) {
ret = ad4170_parse_channel_node(indio_dev, child, chan_num++); if (ret) return ret;
}
/* * Add internal temperature sensor channel if the maximum number of * channels has not been reached.
*/ if (num_channels < AD4170_MAX_ADC_CHANNELS) { struct ad4170_setup *setup = &st->chan_infos[chan_num].setup;
ext_clk = devm_clk_get_optional_enabled(dev, NULL); if (IS_ERR(ext_clk)) return dev_err_probe(dev, PTR_ERR(ext_clk), "Failed to get external clock\n");
if (!ext_clk) { /* Use internal clock reference */
st->mclk_hz = AD4170_INT_CLOCK_16MHZ;
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK,
AD4170_CLOCK_CTRL_CLOCKSEL_INT_OUT);
if (!device_property_present(&st->spi->dev, "#clock-cells")) return 0;
return ad4170_register_clk_provider(indio_dev);
}
/* Read optional clock-names prop to specify the external clock type */
ret = device_property_match_property_string(dev, "clock-names",
ad4170_clk_sel,
ARRAY_SIZE(ad4170_clk_sel));
ret = ret < 0 ? 0 : ret; /* Default to external clock if no clock-names */
st->clock_ctrl |= FIELD_PREP(AD4170_CLOCK_CTRL_CLOCKSEL_MSK,
AD4170_CLOCK_CTRL_CLOCKSEL_EXT + ret);
ret = ad4170_clock_select(indio_dev); if (ret) return dev_err_probe(dev, ret, "Failed to setup device clock\n");
ret = regmap_write(st->regmap, AD4170_CLOCK_CTRL_REG, st->clock_ctrl); if (ret) return ret;
for (i = 0; i < AD4170_NUM_CURRENT_SRC; i++)
st->cur_src_pins[i] = AD4170_CURRENT_SRC_DISABLED;
/* On power on, device defaults to using SDO pin for data ready signal */
int_pin_sel = AD4170_INT_PIN_SDO;
ret = device_property_match_property_string(dev, "interrupt-names",
ad4170_int_pin_names,
ARRAY_SIZE(ad4170_int_pin_names)); if (ret >= 0)
int_pin_sel = ret;
ret = regmap_update_bits(st->regmap, AD4170_PIN_MUXING_REG,
AD4170_PIN_MUXING_DIG_AUX1_CTRL_MSK, reg_data); if (ret) return ret;
ret = device_property_count_u32(dev, "adi,vbias-pins"); if (ret > 0) { if (ret > AD4170_MAX_ANALOG_PINS) return dev_err_probe(dev, -EINVAL, "Too many vbias pins %u\n", ret);
num_vbias_pins = ret;
ret = device_property_read_u32_array(dev, "adi,vbias-pins",
vbias_pins,
num_vbias_pins); if (ret) return dev_err_probe(dev, ret, "Failed to read vbias pins\n");
for (i = 0; i < num_vbias_pins; i++)
st->pins_fn[vbias_pins[i]] |= AD4170_PIN_VBIAS;
}
ret = ad4170_parse_channels(indio_dev); if (ret) return ret;
/* Only create a GPIO chip if flagged for it */ if (device_property_read_bool(dev, "gpio-controller")) {
ret = ad4170_gpio_init(indio_dev); if (ret) return ret;
}
ret = regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_MODE_MSK,
FIELD_PREP(AD4170_ADC_CTRL_MODE_MSK,
AD4170_ADC_CTRL_MODE_IDLE)); if (ret) return dev_err_probe(dev, ret, "Failed to set ADC mode to idle\n");
for (i = 0; i < indio_dev->num_channels; i++) { struct ad4170_chan_info *chan_info; struct iio_chan_spec const *chan; struct ad4170_setup *setup; unsignedint val;
chan = &indio_dev->channels[i]; if (chan->type == IIO_TIMESTAMP) continue;
chan_info = &st->chan_infos[chan->address];
setup = &chan_info->setup;
setup->gain = AD4170_GAIN_REG_DEFAULT;
ret = ad4170_write_channel_setup(st, chan->address, false); if (ret) return dev_err_probe(dev, ret, "Failed to write channel setup\n");
val = FIELD_PREP(AD4170_CHAN_MAP_AINP_MSK, chan->channel) |
FIELD_PREP(AD4170_CHAN_MAP_AINM_MSK, chan->channel2);
ret = regmap_write(st->regmap, AD4170_CHAN_MAP_REG(i), val); if (ret) return dev_err_probe(dev, ret, "Failed to write CHAN_MAP_REG\n");
ret = ad4170_set_channel_freq(st, chan,
AD4170_DEFAULT_SAMP_RATE, 0); if (ret) return dev_err_probe(dev, ret, "Failed to set channel freq\n");
ret = ad4170_fill_scale_tbl(indio_dev, chan); if (ret) return dev_err_probe(dev, ret, "Failed to fill scale tbl\n");
}
/* Disable all channels to avoid reading from unexpected channel */
ret = regmap_write(st->regmap, AD4170_CHAN_EN_REG, 0); if (ret) return dev_err_probe(dev, ret, "Failed to disable channels\n");
/* * Configure channels to share the same data output register, i.e. data * can be read from the same register address regardless of channel * number.
*/ return regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_MULTI_DATA_REG_SEL_MSK,
AD4170_ADC_CTRL_MULTI_DATA_REG_SEL_MSK);
}
staticint ad4170_prepare_spi_message(struct ad4170_state *st)
{ /* * Continuous data register read is enabled on buffer postenable so * no instruction phase is needed meaning we don't need to send the * register address to read data. Transfer only needs the read buffer.
*/
st->xfer.rx_buf = &st->rx_buf;
st->xfer.len = BITS_TO_BYTES(ad4170_channel_template.scan_type.realbits);
ret = regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_MODE_MSK,
FIELD_PREP(AD4170_ADC_CTRL_MODE_MSK,
AD4170_ADC_CTRL_MODE_CONT)); if (ret) return ret;
/* * This enables continuous read of the ADC data register. The ADC must * be in continuous conversion mode.
*/ return regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_CONT_READ_MSK,
FIELD_PREP(AD4170_ADC_CTRL_CONT_READ_MSK,
AD4170_ADC_CTRL_CONT_READ_ENABLE));
}
/* * Use a high register address (virtual register) to request a write of * 0xA5 to the ADC during the first 8 SCLKs of the ADC data read cycle, * thus exiting continuous read.
*/
ret = regmap_write(st->regmap, AD4170_ADC_CTRL_CONT_READ_EXIT_REG, 0); if (ret) return ret;
ret = regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_CONT_READ_MSK,
FIELD_PREP(AD4170_ADC_CTRL_CONT_READ_MSK,
AD4170_ADC_CTRL_CONT_READ_DISABLE)); if (ret) return ret;
ret = regmap_update_bits(st->regmap, AD4170_ADC_CTRL_REG,
AD4170_ADC_CTRL_MODE_MSK,
FIELD_PREP(AD4170_ADC_CTRL_MODE_MSK,
AD4170_ADC_CTRL_MODE_IDLE)); if (ret) return ret;
/* * The ADC sequences through all the enabled channels (see datasheet * page 95). That can lead to incorrect channel being read if a * single-shot read (or buffered read with different active_scan_mask) * is done after buffer disable. Disable all channels so only requested * channels will be read.
*/ for (i = 0; i < indio_dev->num_channels; i++) { if (indio_dev->channels[i].type == IIO_TIMESTAMP) continue;
ret = ad4170_set_channel_enable(st, i, false); if (ret) return ret;
}
/* * The channel sequencer cycles through the enabled channels in * sequential order, from channel 0 to channel 15, bypassing disabled * channels. When more than one channel is enabled, channel 0 must * always be enabled. See datasheet channel_en register description at * page 95.
*/
enabled = bitmap_weight(scan_mask, masklength); if (enabled > 1) return test_bit(0, scan_mask);
st->trig = devm_iio_trigger_alloc(dev, "%s-trig%d",
indio_dev->name,
iio_device_id(indio_dev)); if (!st->trig) return -ENOMEM;
st->trig->ops = &ad4170_trigger_ops;
iio_trigger_set_drvdata(st->trig, indio_dev);
ret = devm_iio_trigger_register(dev, st->trig); if (ret) return dev_err_probe(dev, ret, "Failed to register trigger\n");
/* Required regulators */
ret = devm_regulator_get_enable_read_voltage(dev, "avdd"); if (ret < 0) return dev_err_probe(dev, ret, "Failed to get AVDD voltage.\n");
st->vrefs_uv[AD4170_AVDD_SUP] = ret;
ret = devm_regulator_get_enable_read_voltage(dev, "iovdd"); if (ret < 0) return dev_err_probe(dev, ret, "Failed to get IOVDD voltage.\n");
st->vrefs_uv[AD4170_IOVDD_SUP] = ret;
/* Optional regulators */
ret = devm_regulator_get_enable_read_voltage(dev, "avss"); if (ret < 0 && ret != -ENODEV) return dev_err_probe(dev, ret, "Failed to get AVSS voltage.\n");
/* * Assume AVSS at GND (0V) if not provided. * REVISIT: AVSS is never above system ground level (i.e. AVSS is either * GND or a negative voltage). But we currently don't have support for * reading negative voltages with the regulator framework. So, the * current AD4170 support reads a positive value from the regulator, * then inverts sign to make that negative.
*/
st->vrefs_uv[AD4170_AVSS_SUP] = ret == -ENODEV ? 0 : -ret;
ret = devm_regulator_get_enable_read_voltage(dev, "refin1p"); if (ret < 0 && ret != -ENODEV) return dev_err_probe(dev, ret, "Failed to get REFIN+ voltage.\n");
st->vrefs_uv[AD4170_REFIN1P_SUP] = ret;
ret = devm_regulator_get_enable_read_voltage(dev, "refin1n"); if (ret < 0 && ret != -ENODEV) return dev_err_probe(dev, ret, "Failed to get REFIN- voltage.\n");
/* * Negative supplies are assumed to provide negative voltage. * REVISIT when support for negative regulator voltage read be available * in the regulator framework.
*/
st->vrefs_uv[AD4170_REFIN1N_SUP] = ret == -ENODEV ? -ENODEV : -ret;
ret = devm_regulator_get_enable_read_voltage(dev, "refin2p"); if (ret < 0 && ret != -ENODEV) return dev_err_probe(dev, ret, "Failed to get REFIN2+ voltage.\n");
st->vrefs_uv[AD4170_REFIN2P_SUP] = ret;
ret = devm_regulator_get_enable_read_voltage(dev, "refin2n"); if (ret < 0 && ret != -ENODEV) return dev_err_probe(dev, ret, "Failed to get REFIN2- voltage.\n");
/* * Negative supplies are assumed to provide negative voltage. * REVISIT when support for negative regulator voltage read be available * in the regulator framework.
*/
st->vrefs_uv[AD4170_REFIN2N_SUP] = ret == -ENODEV ? -ENODEV : -ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.