Skip to content

Commit df1f2e1

Browse files
ukleinekjic23
authored andcommitted
iio: adc: ad7124: Implement system calibration
Allow triggering both zero-scale and full-scale calibration via sysfs in the same way as it's done for ad7173. Signed-off-by: Uwe Kleine-König <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 47036a0 commit df1f2e1

File tree

1 file changed

+135
-17
lines changed

1 file changed

+135
-17
lines changed

drivers/iio/adc/ad7124.c

Lines changed: 135 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ struct ad7124_channel {
181181
struct ad7124_channel_config cfg;
182182
unsigned int ain;
183183
unsigned int slot;
184+
u8 syscalib_mode;
184185
};
185186

186187
struct ad7124_state {
@@ -202,23 +203,6 @@ struct ad7124_state {
202203
DECLARE_KFIFO(live_cfgs_fifo, struct ad7124_channel_config *, AD7124_MAX_CONFIGS);
203204
};
204205

205-
static const struct iio_chan_spec ad7124_channel_template = {
206-
.type = IIO_VOLTAGE,
207-
.indexed = 1,
208-
.differential = 1,
209-
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
210-
BIT(IIO_CHAN_INFO_SCALE) |
211-
BIT(IIO_CHAN_INFO_OFFSET) |
212-
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
213-
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
214-
.scan_type = {
215-
.sign = 'u',
216-
.realbits = 24,
217-
.storagebits = 32,
218-
.endianness = IIO_BE,
219-
},
220-
};
221-
222206
static struct ad7124_chip_info ad7124_chip_info_tbl[] = {
223207
[ID_AD7124_4] = {
224208
.name = "ad7124-4",
@@ -903,6 +887,140 @@ static int ad7124_check_chip_id(struct ad7124_state *st)
903887
return 0;
904888
}
905889

890+
enum {
891+
AD7124_SYSCALIB_ZERO_SCALE,
892+
AD7124_SYSCALIB_FULL_SCALE,
893+
};
894+
895+
static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan_spec *chan)
896+
{
897+
struct device *dev = &st->sd.spi->dev;
898+
struct ad7124_channel *ch = &st->channels[chan->channel];
899+
int ret;
900+
901+
if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) {
902+
ch->cfg.calibration_offset = 0x800000;
903+
904+
ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_ZERO,
905+
chan->address);
906+
if (ret < 0)
907+
return ret;
908+
909+
ret = ad_sd_read_reg(&st->sd, AD7124_OFFSET(ch->cfg.cfg_slot), 3,
910+
&ch->cfg.calibration_offset);
911+
if (ret < 0)
912+
return ret;
913+
914+
dev_dbg(dev, "offset for channel %d after zero-scale calibration: 0x%x\n",
915+
chan->channel, ch->cfg.calibration_offset);
916+
} else {
917+
ch->cfg.calibration_gain = st->gain_default;
918+
919+
ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_FULL,
920+
chan->address);
921+
if (ret < 0)
922+
return ret;
923+
924+
ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(ch->cfg.cfg_slot), 3,
925+
&ch->cfg.calibration_gain);
926+
if (ret < 0)
927+
return ret;
928+
929+
dev_dbg(dev, "gain for channel %d after full-scale calibration: 0x%x\n",
930+
chan->channel, ch->cfg.calibration_gain);
931+
}
932+
933+
return 0;
934+
}
935+
936+
static ssize_t ad7124_write_syscalib(struct iio_dev *indio_dev,
937+
uintptr_t private,
938+
const struct iio_chan_spec *chan,
939+
const char *buf, size_t len)
940+
{
941+
struct ad7124_state *st = iio_priv(indio_dev);
942+
bool sys_calib;
943+
int ret;
944+
945+
ret = kstrtobool(buf, &sys_calib);
946+
if (ret)
947+
return ret;
948+
949+
if (!sys_calib)
950+
return len;
951+
952+
if (!iio_device_claim_direct(indio_dev))
953+
return -EBUSY;
954+
955+
ret = ad7124_syscalib_locked(st, chan);
956+
957+
iio_device_release_direct(indio_dev);
958+
959+
return ret ?: len;
960+
}
961+
962+
static const char * const ad7124_syscalib_modes[] = {
963+
[AD7124_SYSCALIB_ZERO_SCALE] = "zero_scale",
964+
[AD7124_SYSCALIB_FULL_SCALE] = "full_scale",
965+
};
966+
967+
static int ad7124_set_syscalib_mode(struct iio_dev *indio_dev,
968+
const struct iio_chan_spec *chan,
969+
unsigned int mode)
970+
{
971+
struct ad7124_state *st = iio_priv(indio_dev);
972+
973+
st->channels[chan->channel].syscalib_mode = mode;
974+
975+
return 0;
976+
}
977+
978+
static int ad7124_get_syscalib_mode(struct iio_dev *indio_dev,
979+
const struct iio_chan_spec *chan)
980+
{
981+
struct ad7124_state *st = iio_priv(indio_dev);
982+
983+
return st->channels[chan->channel].syscalib_mode;
984+
}
985+
986+
static const struct iio_enum ad7124_syscalib_mode_enum = {
987+
.items = ad7124_syscalib_modes,
988+
.num_items = ARRAY_SIZE(ad7124_syscalib_modes),
989+
.set = ad7124_set_syscalib_mode,
990+
.get = ad7124_get_syscalib_mode
991+
};
992+
993+
static const struct iio_chan_spec_ext_info ad7124_calibsys_ext_info[] = {
994+
{
995+
.name = "sys_calibration",
996+
.write = ad7124_write_syscalib,
997+
.shared = IIO_SEPARATE,
998+
},
999+
IIO_ENUM("sys_calibration_mode", IIO_SEPARATE,
1000+
&ad7124_syscalib_mode_enum),
1001+
IIO_ENUM_AVAILABLE("sys_calibration_mode", IIO_SHARED_BY_TYPE,
1002+
&ad7124_syscalib_mode_enum),
1003+
{ }
1004+
};
1005+
1006+
static const struct iio_chan_spec ad7124_channel_template = {
1007+
.type = IIO_VOLTAGE,
1008+
.indexed = 1,
1009+
.differential = 1,
1010+
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1011+
BIT(IIO_CHAN_INFO_SCALE) |
1012+
BIT(IIO_CHAN_INFO_OFFSET) |
1013+
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
1014+
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
1015+
.scan_type = {
1016+
.sign = 'u',
1017+
.realbits = 24,
1018+
.storagebits = 32,
1019+
.endianness = IIO_BE,
1020+
},
1021+
.ext_info = ad7124_calibsys_ext_info,
1022+
};
1023+
9061024
/*
9071025
* Input specifiers 8 - 15 are explicitly reserved for ad7124-4
9081026
* while they are fine for ad7124-8. Values above 31 don't fit

0 commit comments

Comments
 (0)