162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AD7785/AD7792/AD7793/AD7794/AD7795 SPI ADC driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011-2012 Analog Devices Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/interrupt.h> 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include <linux/sysfs.h> 1362306a36Sopenharmony_ci#include <linux/spi/spi.h> 1462306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1562306a36Sopenharmony_ci#include <linux/err.h> 1662306a36Sopenharmony_ci#include <linux/sched.h> 1762306a36Sopenharmony_ci#include <linux/delay.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/iio/iio.h> 2162306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2262306a36Sopenharmony_ci#include <linux/iio/buffer.h> 2362306a36Sopenharmony_ci#include <linux/iio/trigger.h> 2462306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 2562306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 2662306a36Sopenharmony_ci#include <linux/iio/adc/ad_sigma_delta.h> 2762306a36Sopenharmony_ci#include <linux/platform_data/ad7793.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* Registers */ 3062306a36Sopenharmony_ci#define AD7793_REG_COMM 0 /* Communications Register (WO, 8-bit) */ 3162306a36Sopenharmony_ci#define AD7793_REG_STAT 0 /* Status Register (RO, 8-bit) */ 3262306a36Sopenharmony_ci#define AD7793_REG_MODE 1 /* Mode Register (RW, 16-bit */ 3362306a36Sopenharmony_ci#define AD7793_REG_CONF 2 /* Configuration Register (RW, 16-bit) */ 3462306a36Sopenharmony_ci#define AD7793_REG_DATA 3 /* Data Register (RO, 16-/24-bit) */ 3562306a36Sopenharmony_ci#define AD7793_REG_ID 4 /* ID Register (RO, 8-bit) */ 3662306a36Sopenharmony_ci#define AD7793_REG_IO 5 /* IO Register (RO, 8-bit) */ 3762306a36Sopenharmony_ci#define AD7793_REG_OFFSET 6 /* Offset Register (RW, 16-bit 3862306a36Sopenharmony_ci * (AD7792)/24-bit (AD7793)) */ 3962306a36Sopenharmony_ci#define AD7793_REG_FULLSALE 7 /* Full-Scale Register 4062306a36Sopenharmony_ci * (RW, 16-bit (AD7792)/24-bit (AD7793)) */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* Communications Register Bit Designations (AD7793_REG_COMM) */ 4362306a36Sopenharmony_ci#define AD7793_COMM_WEN (1 << 7) /* Write Enable */ 4462306a36Sopenharmony_ci#define AD7793_COMM_WRITE (0 << 6) /* Write Operation */ 4562306a36Sopenharmony_ci#define AD7793_COMM_READ (1 << 6) /* Read Operation */ 4662306a36Sopenharmony_ci#define AD7793_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */ 4762306a36Sopenharmony_ci#define AD7793_COMM_CREAD (1 << 2) /* Continuous Read of Data Register */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* Status Register Bit Designations (AD7793_REG_STAT) */ 5062306a36Sopenharmony_ci#define AD7793_STAT_RDY (1 << 7) /* Ready */ 5162306a36Sopenharmony_ci#define AD7793_STAT_ERR (1 << 6) /* Error (Overrange, Underrange) */ 5262306a36Sopenharmony_ci#define AD7793_STAT_CH3 (1 << 2) /* Channel 3 */ 5362306a36Sopenharmony_ci#define AD7793_STAT_CH2 (1 << 1) /* Channel 2 */ 5462306a36Sopenharmony_ci#define AD7793_STAT_CH1 (1 << 0) /* Channel 1 */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* Mode Register Bit Designations (AD7793_REG_MODE) */ 5762306a36Sopenharmony_ci#define AD7793_MODE_SEL(x) (((x) & 0x7) << 13) /* Operation Mode Select */ 5862306a36Sopenharmony_ci#define AD7793_MODE_SEL_MASK (0x7 << 13) /* Operation Mode Select mask */ 5962306a36Sopenharmony_ci#define AD7793_MODE_CLKSRC(x) (((x) & 0x3) << 6) /* ADC Clock Source Select */ 6062306a36Sopenharmony_ci#define AD7793_MODE_RATE(x) ((x) & 0xF) /* Filter Update Rate Select */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define AD7793_MODE_CONT 0 /* Continuous Conversion Mode */ 6362306a36Sopenharmony_ci#define AD7793_MODE_SINGLE 1 /* Single Conversion Mode */ 6462306a36Sopenharmony_ci#define AD7793_MODE_IDLE 2 /* Idle Mode */ 6562306a36Sopenharmony_ci#define AD7793_MODE_PWRDN 3 /* Power-Down Mode */ 6662306a36Sopenharmony_ci#define AD7793_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */ 6762306a36Sopenharmony_ci#define AD7793_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */ 6862306a36Sopenharmony_ci#define AD7793_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */ 6962306a36Sopenharmony_ci#define AD7793_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */ 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define AD7793_CLK_INT 0 /* Internal 64 kHz Clock not 7262306a36Sopenharmony_ci * available at the CLK pin */ 7362306a36Sopenharmony_ci#define AD7793_CLK_INT_CO 1 /* Internal 64 kHz Clock available 7462306a36Sopenharmony_ci * at the CLK pin */ 7562306a36Sopenharmony_ci#define AD7793_CLK_EXT 2 /* External 64 kHz Clock */ 7662306a36Sopenharmony_ci#define AD7793_CLK_EXT_DIV2 3 /* External Clock divided by 2 */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* Configuration Register Bit Designations (AD7793_REG_CONF) */ 7962306a36Sopenharmony_ci#define AD7793_CONF_VBIAS(x) (((x) & 0x3) << 14) /* Bias Voltage 8062306a36Sopenharmony_ci * Generator Enable */ 8162306a36Sopenharmony_ci#define AD7793_CONF_BO_EN (1 << 13) /* Burnout Current Enable */ 8262306a36Sopenharmony_ci#define AD7793_CONF_UNIPOLAR (1 << 12) /* Unipolar/Bipolar Enable */ 8362306a36Sopenharmony_ci#define AD7793_CONF_BOOST (1 << 11) /* Boost Enable */ 8462306a36Sopenharmony_ci#define AD7793_CONF_GAIN(x) (((x) & 0x7) << 8) /* Gain Select */ 8562306a36Sopenharmony_ci#define AD7793_CONF_REFSEL(x) ((x) << 6) /* INT/EXT Reference Select */ 8662306a36Sopenharmony_ci#define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */ 8762306a36Sopenharmony_ci#define AD7793_CONF_CHAN(x) ((x) & 0xf) /* Channel select */ 8862306a36Sopenharmony_ci#define AD7793_CONF_CHAN_MASK 0xf /* Channel select mask */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci#define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */ 9162306a36Sopenharmony_ci#define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */ 9262306a36Sopenharmony_ci#define AD7793_CH_AIN3P_AIN3M 2 /* AIN3(+) - AIN3(-) */ 9362306a36Sopenharmony_ci#define AD7793_CH_AIN1M_AIN1M 3 /* AIN1(-) - AIN1(-) */ 9462306a36Sopenharmony_ci#define AD7793_CH_TEMP 6 /* Temp Sensor */ 9562306a36Sopenharmony_ci#define AD7793_CH_AVDD_MONITOR 7 /* AVDD Monitor */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define AD7795_CH_AIN4P_AIN4M 4 /* AIN4(+) - AIN4(-) */ 9862306a36Sopenharmony_ci#define AD7795_CH_AIN5P_AIN5M 5 /* AIN5(+) - AIN5(-) */ 9962306a36Sopenharmony_ci#define AD7795_CH_AIN6P_AIN6M 6 /* AIN6(+) - AIN6(-) */ 10062306a36Sopenharmony_ci#define AD7795_CH_AIN1M_AIN1M 8 /* AIN1(-) - AIN1(-) */ 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* ID Register Bit Designations (AD7793_REG_ID) */ 10362306a36Sopenharmony_ci#define AD7785_ID 0x3 10462306a36Sopenharmony_ci#define AD7792_ID 0xA 10562306a36Sopenharmony_ci#define AD7793_ID 0xB 10662306a36Sopenharmony_ci#define AD7794_ID 0xF 10762306a36Sopenharmony_ci#define AD7795_ID 0xF 10862306a36Sopenharmony_ci#define AD7796_ID 0xA 10962306a36Sopenharmony_ci#define AD7797_ID 0xB 11062306a36Sopenharmony_ci#define AD7798_ID 0x8 11162306a36Sopenharmony_ci#define AD7799_ID 0x9 11262306a36Sopenharmony_ci#define AD7793_ID_MASK 0xF 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */ 11562306a36Sopenharmony_ci#define AD7793_IO_IEXC1_IOUT1_IEXC2_IOUT2 0 /* IEXC1 connect to IOUT1, 11662306a36Sopenharmony_ci * IEXC2 connect to IOUT2 */ 11762306a36Sopenharmony_ci#define AD7793_IO_IEXC1_IOUT2_IEXC2_IOUT1 1 /* IEXC1 connect to IOUT2, 11862306a36Sopenharmony_ci * IEXC2 connect to IOUT1 */ 11962306a36Sopenharmony_ci#define AD7793_IO_IEXC1_IEXC2_IOUT1 2 /* Both current sources 12062306a36Sopenharmony_ci * IEXC1,2 connect to IOUT1 */ 12162306a36Sopenharmony_ci#define AD7793_IO_IEXC1_IEXC2_IOUT2 3 /* Both current sources 12262306a36Sopenharmony_ci * IEXC1,2 connect to IOUT2 */ 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define AD7793_IO_IXCEN_10uA (1 << 0) /* Excitation Current 10uA */ 12562306a36Sopenharmony_ci#define AD7793_IO_IXCEN_210uA (2 << 0) /* Excitation Current 210uA */ 12662306a36Sopenharmony_ci#define AD7793_IO_IXCEN_1mA (3 << 0) /* Excitation Current 1mA */ 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* NOTE: 12962306a36Sopenharmony_ci * The AD7792/AD7793 features a dual use data out ready DOUT/RDY output. 13062306a36Sopenharmony_ci * In order to avoid contentions on the SPI bus, it's therefore necessary 13162306a36Sopenharmony_ci * to use spi bus locking. 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci * The DOUT/RDY output must also be wired to an interrupt capable GPIO. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#define AD7793_FLAG_HAS_CLKSEL BIT(0) 13762306a36Sopenharmony_ci#define AD7793_FLAG_HAS_REFSEL BIT(1) 13862306a36Sopenharmony_ci#define AD7793_FLAG_HAS_VBIAS BIT(2) 13962306a36Sopenharmony_ci#define AD7793_HAS_EXITATION_CURRENT BIT(3) 14062306a36Sopenharmony_ci#define AD7793_FLAG_HAS_GAIN BIT(4) 14162306a36Sopenharmony_ci#define AD7793_FLAG_HAS_BUFFER BIT(5) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistruct ad7793_chip_info { 14462306a36Sopenharmony_ci unsigned int id; 14562306a36Sopenharmony_ci const struct iio_chan_spec *channels; 14662306a36Sopenharmony_ci unsigned int num_channels; 14762306a36Sopenharmony_ci unsigned int flags; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci const struct iio_info *iio_info; 15062306a36Sopenharmony_ci const u16 *sample_freq_avail; 15162306a36Sopenharmony_ci}; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistruct ad7793_state { 15462306a36Sopenharmony_ci const struct ad7793_chip_info *chip_info; 15562306a36Sopenharmony_ci struct regulator *reg; 15662306a36Sopenharmony_ci u16 int_vref_mv; 15762306a36Sopenharmony_ci u16 mode; 15862306a36Sopenharmony_ci u16 conf; 15962306a36Sopenharmony_ci u32 scale_avail[8][2]; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci struct ad_sigma_delta sd; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cienum ad7793_supported_device_ids { 16662306a36Sopenharmony_ci ID_AD7785, 16762306a36Sopenharmony_ci ID_AD7792, 16862306a36Sopenharmony_ci ID_AD7793, 16962306a36Sopenharmony_ci ID_AD7794, 17062306a36Sopenharmony_ci ID_AD7795, 17162306a36Sopenharmony_ci ID_AD7796, 17262306a36Sopenharmony_ci ID_AD7797, 17362306a36Sopenharmony_ci ID_AD7798, 17462306a36Sopenharmony_ci ID_AD7799, 17562306a36Sopenharmony_ci}; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic struct ad7793_state *ad_sigma_delta_to_ad7793(struct ad_sigma_delta *sd) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci return container_of(sd, struct ad7793_state, sd); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int ad7793_set_channel(struct ad_sigma_delta *sd, unsigned int channel) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci st->conf &= ~AD7793_CONF_CHAN_MASK; 18762306a36Sopenharmony_ci st->conf |= AD7793_CONF_CHAN(channel); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return ad_sd_write_reg(&st->sd, AD7793_REG_CONF, 2, st->conf); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int ad7793_set_mode(struct ad_sigma_delta *sd, 19362306a36Sopenharmony_ci enum ad_sigma_delta_mode mode) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci st->mode &= ~AD7793_MODE_SEL_MASK; 19862306a36Sopenharmony_ci st->mode |= AD7793_MODE_SEL(mode); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci return ad_sd_write_reg(&st->sd, AD7793_REG_MODE, 2, st->mode); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic const struct ad_sigma_delta_info ad7793_sigma_delta_info = { 20462306a36Sopenharmony_ci .set_channel = ad7793_set_channel, 20562306a36Sopenharmony_ci .set_mode = ad7793_set_mode, 20662306a36Sopenharmony_ci .has_registers = true, 20762306a36Sopenharmony_ci .addr_shift = 3, 20862306a36Sopenharmony_ci .read_mask = BIT(6), 20962306a36Sopenharmony_ci .irq_flags = IRQF_TRIGGER_FALLING, 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const struct ad_sd_calib_data ad7793_calib_arr[6] = { 21362306a36Sopenharmony_ci {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M}, 21462306a36Sopenharmony_ci {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M}, 21562306a36Sopenharmony_ci {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M}, 21662306a36Sopenharmony_ci {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN2P_AIN2M}, 21762306a36Sopenharmony_ci {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN3P_AIN3M}, 21862306a36Sopenharmony_ci {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN3P_AIN3M} 21962306a36Sopenharmony_ci}; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic int ad7793_calibrate_all(struct ad7793_state *st) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci return ad_sd_calibrate_all(&st->sd, ad7793_calib_arr, 22462306a36Sopenharmony_ci ARRAY_SIZE(ad7793_calib_arr)); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic int ad7793_check_platform_data(struct ad7793_state *st, 22862306a36Sopenharmony_ci const struct ad7793_platform_data *pdata) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci if ((pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT1 || 23162306a36Sopenharmony_ci pdata->current_source_direction == AD7793_IEXEC1_IEXEC2_IOUT2) && 23262306a36Sopenharmony_ci ((pdata->exitation_current != AD7793_IX_10uA) && 23362306a36Sopenharmony_ci (pdata->exitation_current != AD7793_IX_210uA))) 23462306a36Sopenharmony_ci return -EINVAL; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (!(st->chip_info->flags & AD7793_FLAG_HAS_CLKSEL) && 23762306a36Sopenharmony_ci pdata->clock_src != AD7793_CLK_SRC_INT) 23862306a36Sopenharmony_ci return -EINVAL; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (!(st->chip_info->flags & AD7793_FLAG_HAS_REFSEL) && 24162306a36Sopenharmony_ci pdata->refsel != AD7793_REFSEL_REFIN1) 24262306a36Sopenharmony_ci return -EINVAL; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (!(st->chip_info->flags & AD7793_FLAG_HAS_VBIAS) && 24562306a36Sopenharmony_ci pdata->bias_voltage != AD7793_BIAS_VOLTAGE_DISABLED) 24662306a36Sopenharmony_ci return -EINVAL; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (!(st->chip_info->flags & AD7793_HAS_EXITATION_CURRENT) && 24962306a36Sopenharmony_ci pdata->exitation_current != AD7793_IX_DISABLED) 25062306a36Sopenharmony_ci return -EINVAL; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci return 0; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic int ad7793_setup(struct iio_dev *indio_dev, 25662306a36Sopenharmony_ci const struct ad7793_platform_data *pdata, 25762306a36Sopenharmony_ci unsigned int vref_mv) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct ad7793_state *st = iio_priv(indio_dev); 26062306a36Sopenharmony_ci int i, ret; 26162306a36Sopenharmony_ci unsigned long long scale_uv; 26262306a36Sopenharmony_ci u32 id; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci ret = ad7793_check_platform_data(st, pdata); 26562306a36Sopenharmony_ci if (ret) 26662306a36Sopenharmony_ci return ret; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* reset the serial interface */ 26962306a36Sopenharmony_ci ret = ad_sd_reset(&st->sd, 32); 27062306a36Sopenharmony_ci if (ret < 0) 27162306a36Sopenharmony_ci goto out; 27262306a36Sopenharmony_ci usleep_range(500, 2000); /* Wait for at least 500us */ 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* write/read test for device presence */ 27562306a36Sopenharmony_ci ret = ad_sd_read_reg(&st->sd, AD7793_REG_ID, 1, &id); 27662306a36Sopenharmony_ci if (ret) 27762306a36Sopenharmony_ci goto out; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci id &= AD7793_ID_MASK; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (id != st->chip_info->id) { 28262306a36Sopenharmony_ci ret = -ENODEV; 28362306a36Sopenharmony_ci dev_err(&st->sd.spi->dev, "device ID query failed\n"); 28462306a36Sopenharmony_ci goto out; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci st->mode = AD7793_MODE_RATE(1); 28862306a36Sopenharmony_ci st->conf = 0; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (st->chip_info->flags & AD7793_FLAG_HAS_CLKSEL) 29162306a36Sopenharmony_ci st->mode |= AD7793_MODE_CLKSRC(pdata->clock_src); 29262306a36Sopenharmony_ci if (st->chip_info->flags & AD7793_FLAG_HAS_REFSEL) 29362306a36Sopenharmony_ci st->conf |= AD7793_CONF_REFSEL(pdata->refsel); 29462306a36Sopenharmony_ci if (st->chip_info->flags & AD7793_FLAG_HAS_VBIAS) 29562306a36Sopenharmony_ci st->conf |= AD7793_CONF_VBIAS(pdata->bias_voltage); 29662306a36Sopenharmony_ci if (pdata->buffered || !(st->chip_info->flags & AD7793_FLAG_HAS_BUFFER)) 29762306a36Sopenharmony_ci st->conf |= AD7793_CONF_BUF; 29862306a36Sopenharmony_ci if (pdata->boost_enable && 29962306a36Sopenharmony_ci (st->chip_info->flags & AD7793_FLAG_HAS_VBIAS)) 30062306a36Sopenharmony_ci st->conf |= AD7793_CONF_BOOST; 30162306a36Sopenharmony_ci if (pdata->burnout_current) 30262306a36Sopenharmony_ci st->conf |= AD7793_CONF_BO_EN; 30362306a36Sopenharmony_ci if (pdata->unipolar) 30462306a36Sopenharmony_ci st->conf |= AD7793_CONF_UNIPOLAR; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if (!(st->chip_info->flags & AD7793_FLAG_HAS_GAIN)) 30762306a36Sopenharmony_ci st->conf |= AD7793_CONF_GAIN(7); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci ret = ad7793_set_mode(&st->sd, AD_SD_MODE_IDLE); 31062306a36Sopenharmony_ci if (ret) 31162306a36Sopenharmony_ci goto out; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci ret = ad7793_set_channel(&st->sd, 0); 31462306a36Sopenharmony_ci if (ret) 31562306a36Sopenharmony_ci goto out; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci if (st->chip_info->flags & AD7793_HAS_EXITATION_CURRENT) { 31862306a36Sopenharmony_ci ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO, 1, 31962306a36Sopenharmony_ci pdata->exitation_current | 32062306a36Sopenharmony_ci (pdata->current_source_direction << 2)); 32162306a36Sopenharmony_ci if (ret) 32262306a36Sopenharmony_ci goto out; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci ret = ad7793_calibrate_all(st); 32662306a36Sopenharmony_ci if (ret) 32762306a36Sopenharmony_ci goto out; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* Populate available ADC input ranges */ 33062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { 33162306a36Sopenharmony_ci scale_uv = ((u64)vref_mv * 100000000) 33262306a36Sopenharmony_ci >> (st->chip_info->channels[0].scan_type.realbits - 33362306a36Sopenharmony_ci (!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1)); 33462306a36Sopenharmony_ci scale_uv >>= i; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10; 33762306a36Sopenharmony_ci st->scale_avail[i][0] = scale_uv; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci return 0; 34162306a36Sopenharmony_ciout: 34262306a36Sopenharmony_ci dev_err(&st->sd.spi->dev, "setup failed\n"); 34362306a36Sopenharmony_ci return ret; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic const u16 ad7793_sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 34762306a36Sopenharmony_ci 33, 19, 17, 16, 12, 10, 8, 6, 4}; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic const u16 ad7797_sample_freq_avail[16] = {0, 0, 0, 123, 62, 50, 0, 35062306a36Sopenharmony_ci 33, 0, 17, 16, 12, 10, 8, 6, 4}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic IIO_CONST_ATTR_SAMP_FREQ_AVAIL( 35362306a36Sopenharmony_ci "470 242 123 62 50 39 33 19 17 16 12 10 8 6 4"); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic IIO_CONST_ATTR_NAMED(sampling_frequency_available_ad7797, 35662306a36Sopenharmony_ci sampling_frequency_available, "123 62 50 33 17 16 12 10 8 6 4"); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic int ad7793_read_avail(struct iio_dev *indio_dev, 35962306a36Sopenharmony_ci struct iio_chan_spec const *chan, 36062306a36Sopenharmony_ci const int **vals, int *type, int *length, 36162306a36Sopenharmony_ci long mask) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci struct ad7793_state *st = iio_priv(indio_dev); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci switch (mask) { 36662306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 36762306a36Sopenharmony_ci *vals = (int *)st->scale_avail; 36862306a36Sopenharmony_ci *type = IIO_VAL_INT_PLUS_NANO; 36962306a36Sopenharmony_ci /* Values are stored in a 2D matrix */ 37062306a36Sopenharmony_ci *length = ARRAY_SIZE(st->scale_avail) * 2; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci return IIO_AVAIL_LIST; 37362306a36Sopenharmony_ci default: 37462306a36Sopenharmony_ci return -EINVAL; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic struct attribute *ad7793_attributes[] = { 37962306a36Sopenharmony_ci &iio_const_attr_sampling_frequency_available.dev_attr.attr, 38062306a36Sopenharmony_ci NULL 38162306a36Sopenharmony_ci}; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic const struct attribute_group ad7793_attribute_group = { 38462306a36Sopenharmony_ci .attrs = ad7793_attributes, 38562306a36Sopenharmony_ci}; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic struct attribute *ad7797_attributes[] = { 38862306a36Sopenharmony_ci &iio_const_attr_sampling_frequency_available_ad7797.dev_attr.attr, 38962306a36Sopenharmony_ci NULL 39062306a36Sopenharmony_ci}; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic const struct attribute_group ad7797_attribute_group = { 39362306a36Sopenharmony_ci .attrs = ad7797_attributes, 39462306a36Sopenharmony_ci}; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic int ad7793_read_raw(struct iio_dev *indio_dev, 39762306a36Sopenharmony_ci struct iio_chan_spec const *chan, 39862306a36Sopenharmony_ci int *val, 39962306a36Sopenharmony_ci int *val2, 40062306a36Sopenharmony_ci long m) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct ad7793_state *st = iio_priv(indio_dev); 40362306a36Sopenharmony_ci int ret; 40462306a36Sopenharmony_ci unsigned long long scale_uv; 40562306a36Sopenharmony_ci bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci switch (m) { 40862306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 40962306a36Sopenharmony_ci ret = ad_sigma_delta_single_conversion(indio_dev, chan, val); 41062306a36Sopenharmony_ci if (ret < 0) 41162306a36Sopenharmony_ci return ret; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci return IIO_VAL_INT; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 41662306a36Sopenharmony_ci switch (chan->type) { 41762306a36Sopenharmony_ci case IIO_VOLTAGE: 41862306a36Sopenharmony_ci if (chan->differential) { 41962306a36Sopenharmony_ci *val = st-> 42062306a36Sopenharmony_ci scale_avail[(st->conf >> 8) & 0x7][0]; 42162306a36Sopenharmony_ci *val2 = st-> 42262306a36Sopenharmony_ci scale_avail[(st->conf >> 8) & 0x7][1]; 42362306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_NANO; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci /* 1170mV / 2^23 * 6 */ 42662306a36Sopenharmony_ci scale_uv = (1170ULL * 1000000000ULL * 6ULL); 42762306a36Sopenharmony_ci break; 42862306a36Sopenharmony_ci case IIO_TEMP: 42962306a36Sopenharmony_ci /* 1170mV / 0.81 mV/C / 2^23 */ 43062306a36Sopenharmony_ci scale_uv = 1444444444444444ULL; 43162306a36Sopenharmony_ci break; 43262306a36Sopenharmony_ci default: 43362306a36Sopenharmony_ci return -EINVAL; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci scale_uv >>= (chan->scan_type.realbits - (unipolar ? 0 : 1)); 43762306a36Sopenharmony_ci *val = 0; 43862306a36Sopenharmony_ci *val2 = scale_uv; 43962306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_NANO; 44062306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 44162306a36Sopenharmony_ci if (!unipolar) 44262306a36Sopenharmony_ci *val = -(1 << (chan->scan_type.realbits - 1)); 44362306a36Sopenharmony_ci else 44462306a36Sopenharmony_ci *val = 0; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci /* Kelvin to Celsius */ 44762306a36Sopenharmony_ci if (chan->type == IIO_TEMP) { 44862306a36Sopenharmony_ci unsigned long long offset; 44962306a36Sopenharmony_ci unsigned int shift; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci shift = chan->scan_type.realbits - (unipolar ? 0 : 1); 45262306a36Sopenharmony_ci offset = 273ULL << shift; 45362306a36Sopenharmony_ci do_div(offset, 1444); 45462306a36Sopenharmony_ci *val -= offset; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci return IIO_VAL_INT; 45762306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 45862306a36Sopenharmony_ci *val = st->chip_info 45962306a36Sopenharmony_ci ->sample_freq_avail[AD7793_MODE_RATE(st->mode)]; 46062306a36Sopenharmony_ci return IIO_VAL_INT; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci return -EINVAL; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic int ad7793_write_raw(struct iio_dev *indio_dev, 46662306a36Sopenharmony_ci struct iio_chan_spec const *chan, 46762306a36Sopenharmony_ci int val, 46862306a36Sopenharmony_ci int val2, 46962306a36Sopenharmony_ci long mask) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci struct ad7793_state *st = iio_priv(indio_dev); 47262306a36Sopenharmony_ci int ret, i; 47362306a36Sopenharmony_ci unsigned int tmp; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 47662306a36Sopenharmony_ci if (ret) 47762306a36Sopenharmony_ci return ret; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci switch (mask) { 48062306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 48162306a36Sopenharmony_ci ret = -EINVAL; 48262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) 48362306a36Sopenharmony_ci if (val2 == st->scale_avail[i][1]) { 48462306a36Sopenharmony_ci ret = 0; 48562306a36Sopenharmony_ci tmp = st->conf; 48662306a36Sopenharmony_ci st->conf &= ~AD7793_CONF_GAIN(-1); 48762306a36Sopenharmony_ci st->conf |= AD7793_CONF_GAIN(i); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci if (tmp == st->conf) 49062306a36Sopenharmony_ci break; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci ad_sd_write_reg(&st->sd, AD7793_REG_CONF, 49362306a36Sopenharmony_ci sizeof(st->conf), st->conf); 49462306a36Sopenharmony_ci ad7793_calibrate_all(st); 49562306a36Sopenharmony_ci break; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci break; 49862306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 49962306a36Sopenharmony_ci if (!val) { 50062306a36Sopenharmony_ci ret = -EINVAL; 50162306a36Sopenharmony_ci break; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci for (i = 0; i < 16; i++) 50562306a36Sopenharmony_ci if (val == st->chip_info->sample_freq_avail[i]) 50662306a36Sopenharmony_ci break; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (i == 16) { 50962306a36Sopenharmony_ci ret = -EINVAL; 51062306a36Sopenharmony_ci break; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci st->mode &= ~AD7793_MODE_RATE(-1); 51462306a36Sopenharmony_ci st->mode |= AD7793_MODE_RATE(i); 51562306a36Sopenharmony_ci ad_sd_write_reg(&st->sd, AD7793_REG_MODE, sizeof(st->mode), 51662306a36Sopenharmony_ci st->mode); 51762306a36Sopenharmony_ci break; 51862306a36Sopenharmony_ci default: 51962306a36Sopenharmony_ci ret = -EINVAL; 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 52362306a36Sopenharmony_ci return ret; 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_cistatic int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev, 52762306a36Sopenharmony_ci struct iio_chan_spec const *chan, 52862306a36Sopenharmony_ci long mask) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_NANO; 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_cistatic const struct iio_info ad7793_info = { 53462306a36Sopenharmony_ci .read_raw = &ad7793_read_raw, 53562306a36Sopenharmony_ci .write_raw = &ad7793_write_raw, 53662306a36Sopenharmony_ci .write_raw_get_fmt = &ad7793_write_raw_get_fmt, 53762306a36Sopenharmony_ci .read_avail = ad7793_read_avail, 53862306a36Sopenharmony_ci .attrs = &ad7793_attribute_group, 53962306a36Sopenharmony_ci .validate_trigger = ad_sd_validate_trigger, 54062306a36Sopenharmony_ci}; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic const struct iio_info ad7797_info = { 54362306a36Sopenharmony_ci .read_raw = &ad7793_read_raw, 54462306a36Sopenharmony_ci .write_raw = &ad7793_write_raw, 54562306a36Sopenharmony_ci .write_raw_get_fmt = &ad7793_write_raw_get_fmt, 54662306a36Sopenharmony_ci .attrs = &ad7797_attribute_group, 54762306a36Sopenharmony_ci .validate_trigger = ad_sd_validate_trigger, 54862306a36Sopenharmony_ci}; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci#define __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ 55162306a36Sopenharmony_ci _storagebits, _shift, _extend_name, _type, _mask_type_av, _mask_all) \ 55262306a36Sopenharmony_ci { \ 55362306a36Sopenharmony_ci .type = (_type), \ 55462306a36Sopenharmony_ci .differential = (_channel2 == -1 ? 0 : 1), \ 55562306a36Sopenharmony_ci .indexed = 1, \ 55662306a36Sopenharmony_ci .channel = (_channel1), \ 55762306a36Sopenharmony_ci .channel2 = (_channel2), \ 55862306a36Sopenharmony_ci .address = (_address), \ 55962306a36Sopenharmony_ci .extend_name = (_extend_name), \ 56062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 56162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET), \ 56262306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 56362306a36Sopenharmony_ci .info_mask_shared_by_type_available = (_mask_type_av), \ 56462306a36Sopenharmony_ci .info_mask_shared_by_all = _mask_all, \ 56562306a36Sopenharmony_ci .scan_index = (_si), \ 56662306a36Sopenharmony_ci .scan_type = { \ 56762306a36Sopenharmony_ci .sign = 'u', \ 56862306a36Sopenharmony_ci .realbits = (_bits), \ 56962306a36Sopenharmony_ci .storagebits = (_storagebits), \ 57062306a36Sopenharmony_ci .shift = (_shift), \ 57162306a36Sopenharmony_ci .endianness = IIO_BE, \ 57262306a36Sopenharmony_ci }, \ 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci#define AD7793_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ 57662306a36Sopenharmony_ci _storagebits, _shift) \ 57762306a36Sopenharmony_ci __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ 57862306a36Sopenharmony_ci _storagebits, _shift, NULL, IIO_VOLTAGE, \ 57962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 58062306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SAMP_FREQ)) 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci#define AD7793_SHORTED_CHANNEL(_si, _channel, _address, _bits, \ 58362306a36Sopenharmony_ci _storagebits, _shift) \ 58462306a36Sopenharmony_ci __AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \ 58562306a36Sopenharmony_ci _storagebits, _shift, "shorted", IIO_VOLTAGE, \ 58662306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 58762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SAMP_FREQ)) 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci#define AD7793_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \ 59062306a36Sopenharmony_ci __AD7793_CHANNEL(_si, 0, -1, _address, _bits, \ 59162306a36Sopenharmony_ci _storagebits, _shift, NULL, IIO_TEMP, \ 59262306a36Sopenharmony_ci 0, \ 59362306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SAMP_FREQ)) 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci#define AD7793_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \ 59662306a36Sopenharmony_ci _shift) \ 59762306a36Sopenharmony_ci __AD7793_CHANNEL(_si, _channel, -1, _address, _bits, \ 59862306a36Sopenharmony_ci _storagebits, _shift, "supply", IIO_VOLTAGE, \ 59962306a36Sopenharmony_ci 0, \ 60062306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SAMP_FREQ)) 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci#define AD7797_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ 60362306a36Sopenharmony_ci _storagebits, _shift) \ 60462306a36Sopenharmony_ci __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \ 60562306a36Sopenharmony_ci _storagebits, _shift, NULL, IIO_VOLTAGE, \ 60662306a36Sopenharmony_ci 0, \ 60762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SAMP_FREQ)) 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci#define AD7797_SHORTED_CHANNEL(_si, _channel, _address, _bits, \ 61062306a36Sopenharmony_ci _storagebits, _shift) \ 61162306a36Sopenharmony_ci __AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \ 61262306a36Sopenharmony_ci _storagebits, _shift, "shorted", IIO_VOLTAGE, \ 61362306a36Sopenharmony_ci 0, \ 61462306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SAMP_FREQ)) 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci#define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \ 61762306a36Sopenharmony_ciconst struct iio_chan_spec _name##_channels[] = { \ 61862306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \ 61962306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \ 62062306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \ 62162306a36Sopenharmony_ci AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \ 62262306a36Sopenharmony_ci AD7793_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \ 62362306a36Sopenharmony_ci AD7793_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \ 62462306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(6), \ 62562306a36Sopenharmony_ci} 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci#define DECLARE_AD7795_CHANNELS(_name, _b, _sb) \ 62862306a36Sopenharmony_ciconst struct iio_chan_spec _name##_channels[] = { \ 62962306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \ 63062306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \ 63162306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \ 63262306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \ 63362306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \ 63462306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \ 63562306a36Sopenharmony_ci AD7793_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \ 63662306a36Sopenharmony_ci AD7793_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \ 63762306a36Sopenharmony_ci AD7793_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \ 63862306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(9), \ 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci#define DECLARE_AD7797_CHANNELS(_name, _b, _sb) \ 64262306a36Sopenharmony_ciconst struct iio_chan_spec _name##_channels[] = { \ 64362306a36Sopenharmony_ci AD7797_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \ 64462306a36Sopenharmony_ci AD7797_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \ 64562306a36Sopenharmony_ci AD7793_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \ 64662306a36Sopenharmony_ci AD7793_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \ 64762306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(4), \ 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci#define DECLARE_AD7799_CHANNELS(_name, _b, _sb) \ 65162306a36Sopenharmony_ciconst struct iio_chan_spec _name##_channels[] = { \ 65262306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \ 65362306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \ 65462306a36Sopenharmony_ci AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \ 65562306a36Sopenharmony_ci AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \ 65662306a36Sopenharmony_ci AD7793_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \ 65762306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(5), \ 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_cistatic DECLARE_AD7793_CHANNELS(ad7785, 20, 32, 4); 66162306a36Sopenharmony_cistatic DECLARE_AD7793_CHANNELS(ad7792, 16, 32, 0); 66262306a36Sopenharmony_cistatic DECLARE_AD7793_CHANNELS(ad7793, 24, 32, 0); 66362306a36Sopenharmony_cistatic DECLARE_AD7795_CHANNELS(ad7794, 16, 32); 66462306a36Sopenharmony_cistatic DECLARE_AD7795_CHANNELS(ad7795, 24, 32); 66562306a36Sopenharmony_cistatic DECLARE_AD7797_CHANNELS(ad7796, 16, 16); 66662306a36Sopenharmony_cistatic DECLARE_AD7797_CHANNELS(ad7797, 24, 32); 66762306a36Sopenharmony_cistatic DECLARE_AD7799_CHANNELS(ad7798, 16, 16); 66862306a36Sopenharmony_cistatic DECLARE_AD7799_CHANNELS(ad7799, 24, 32); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic const struct ad7793_chip_info ad7793_chip_info_tbl[] = { 67162306a36Sopenharmony_ci [ID_AD7785] = { 67262306a36Sopenharmony_ci .id = AD7785_ID, 67362306a36Sopenharmony_ci .channels = ad7785_channels, 67462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7785_channels), 67562306a36Sopenharmony_ci .iio_info = &ad7793_info, 67662306a36Sopenharmony_ci .sample_freq_avail = ad7793_sample_freq_avail, 67762306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_CLKSEL | 67862306a36Sopenharmony_ci AD7793_FLAG_HAS_REFSEL | 67962306a36Sopenharmony_ci AD7793_FLAG_HAS_VBIAS | 68062306a36Sopenharmony_ci AD7793_HAS_EXITATION_CURRENT | 68162306a36Sopenharmony_ci AD7793_FLAG_HAS_GAIN | 68262306a36Sopenharmony_ci AD7793_FLAG_HAS_BUFFER, 68362306a36Sopenharmony_ci }, 68462306a36Sopenharmony_ci [ID_AD7792] = { 68562306a36Sopenharmony_ci .id = AD7792_ID, 68662306a36Sopenharmony_ci .channels = ad7792_channels, 68762306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7792_channels), 68862306a36Sopenharmony_ci .iio_info = &ad7793_info, 68962306a36Sopenharmony_ci .sample_freq_avail = ad7793_sample_freq_avail, 69062306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_CLKSEL | 69162306a36Sopenharmony_ci AD7793_FLAG_HAS_REFSEL | 69262306a36Sopenharmony_ci AD7793_FLAG_HAS_VBIAS | 69362306a36Sopenharmony_ci AD7793_HAS_EXITATION_CURRENT | 69462306a36Sopenharmony_ci AD7793_FLAG_HAS_GAIN | 69562306a36Sopenharmony_ci AD7793_FLAG_HAS_BUFFER, 69662306a36Sopenharmony_ci }, 69762306a36Sopenharmony_ci [ID_AD7793] = { 69862306a36Sopenharmony_ci .id = AD7793_ID, 69962306a36Sopenharmony_ci .channels = ad7793_channels, 70062306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7793_channels), 70162306a36Sopenharmony_ci .iio_info = &ad7793_info, 70262306a36Sopenharmony_ci .sample_freq_avail = ad7793_sample_freq_avail, 70362306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_CLKSEL | 70462306a36Sopenharmony_ci AD7793_FLAG_HAS_REFSEL | 70562306a36Sopenharmony_ci AD7793_FLAG_HAS_VBIAS | 70662306a36Sopenharmony_ci AD7793_HAS_EXITATION_CURRENT | 70762306a36Sopenharmony_ci AD7793_FLAG_HAS_GAIN | 70862306a36Sopenharmony_ci AD7793_FLAG_HAS_BUFFER, 70962306a36Sopenharmony_ci }, 71062306a36Sopenharmony_ci [ID_AD7794] = { 71162306a36Sopenharmony_ci .id = AD7794_ID, 71262306a36Sopenharmony_ci .channels = ad7794_channels, 71362306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7794_channels), 71462306a36Sopenharmony_ci .iio_info = &ad7793_info, 71562306a36Sopenharmony_ci .sample_freq_avail = ad7793_sample_freq_avail, 71662306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_CLKSEL | 71762306a36Sopenharmony_ci AD7793_FLAG_HAS_REFSEL | 71862306a36Sopenharmony_ci AD7793_FLAG_HAS_VBIAS | 71962306a36Sopenharmony_ci AD7793_HAS_EXITATION_CURRENT | 72062306a36Sopenharmony_ci AD7793_FLAG_HAS_GAIN | 72162306a36Sopenharmony_ci AD7793_FLAG_HAS_BUFFER, 72262306a36Sopenharmony_ci }, 72362306a36Sopenharmony_ci [ID_AD7795] = { 72462306a36Sopenharmony_ci .id = AD7795_ID, 72562306a36Sopenharmony_ci .channels = ad7795_channels, 72662306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7795_channels), 72762306a36Sopenharmony_ci .iio_info = &ad7793_info, 72862306a36Sopenharmony_ci .sample_freq_avail = ad7793_sample_freq_avail, 72962306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_CLKSEL | 73062306a36Sopenharmony_ci AD7793_FLAG_HAS_REFSEL | 73162306a36Sopenharmony_ci AD7793_FLAG_HAS_VBIAS | 73262306a36Sopenharmony_ci AD7793_HAS_EXITATION_CURRENT | 73362306a36Sopenharmony_ci AD7793_FLAG_HAS_GAIN | 73462306a36Sopenharmony_ci AD7793_FLAG_HAS_BUFFER, 73562306a36Sopenharmony_ci }, 73662306a36Sopenharmony_ci [ID_AD7796] = { 73762306a36Sopenharmony_ci .id = AD7796_ID, 73862306a36Sopenharmony_ci .channels = ad7796_channels, 73962306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7796_channels), 74062306a36Sopenharmony_ci .iio_info = &ad7797_info, 74162306a36Sopenharmony_ci .sample_freq_avail = ad7797_sample_freq_avail, 74262306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_CLKSEL, 74362306a36Sopenharmony_ci }, 74462306a36Sopenharmony_ci [ID_AD7797] = { 74562306a36Sopenharmony_ci .id = AD7797_ID, 74662306a36Sopenharmony_ci .channels = ad7797_channels, 74762306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7797_channels), 74862306a36Sopenharmony_ci .iio_info = &ad7797_info, 74962306a36Sopenharmony_ci .sample_freq_avail = ad7797_sample_freq_avail, 75062306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_CLKSEL, 75162306a36Sopenharmony_ci }, 75262306a36Sopenharmony_ci [ID_AD7798] = { 75362306a36Sopenharmony_ci .id = AD7798_ID, 75462306a36Sopenharmony_ci .channels = ad7798_channels, 75562306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7798_channels), 75662306a36Sopenharmony_ci .iio_info = &ad7793_info, 75762306a36Sopenharmony_ci .sample_freq_avail = ad7793_sample_freq_avail, 75862306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_GAIN | 75962306a36Sopenharmony_ci AD7793_FLAG_HAS_BUFFER, 76062306a36Sopenharmony_ci }, 76162306a36Sopenharmony_ci [ID_AD7799] = { 76262306a36Sopenharmony_ci .id = AD7799_ID, 76362306a36Sopenharmony_ci .channels = ad7799_channels, 76462306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(ad7799_channels), 76562306a36Sopenharmony_ci .iio_info = &ad7793_info, 76662306a36Sopenharmony_ci .sample_freq_avail = ad7793_sample_freq_avail, 76762306a36Sopenharmony_ci .flags = AD7793_FLAG_HAS_GAIN | 76862306a36Sopenharmony_ci AD7793_FLAG_HAS_BUFFER, 76962306a36Sopenharmony_ci }, 77062306a36Sopenharmony_ci}; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_cistatic void ad7793_reg_disable(void *reg) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci regulator_disable(reg); 77562306a36Sopenharmony_ci} 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_cistatic int ad7793_probe(struct spi_device *spi) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci const struct ad7793_platform_data *pdata = spi->dev.platform_data; 78062306a36Sopenharmony_ci struct ad7793_state *st; 78162306a36Sopenharmony_ci struct iio_dev *indio_dev; 78262306a36Sopenharmony_ci int ret, vref_mv = 0; 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci if (!pdata) { 78562306a36Sopenharmony_ci dev_err(&spi->dev, "no platform data?\n"); 78662306a36Sopenharmony_ci return -ENODEV; 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (!spi->irq) { 79062306a36Sopenharmony_ci dev_err(&spi->dev, "no IRQ?\n"); 79162306a36Sopenharmony_ci return -ENODEV; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 79562306a36Sopenharmony_ci if (indio_dev == NULL) 79662306a36Sopenharmony_ci return -ENOMEM; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci st = iio_priv(indio_dev); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci if (pdata->refsel != AD7793_REFSEL_INTERNAL) { 80362306a36Sopenharmony_ci st->reg = devm_regulator_get(&spi->dev, "refin"); 80462306a36Sopenharmony_ci if (IS_ERR(st->reg)) 80562306a36Sopenharmony_ci return PTR_ERR(st->reg); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci ret = regulator_enable(st->reg); 80862306a36Sopenharmony_ci if (ret) 80962306a36Sopenharmony_ci return ret; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci ret = devm_add_action_or_reset(&spi->dev, ad7793_reg_disable, st->reg); 81262306a36Sopenharmony_ci if (ret) 81362306a36Sopenharmony_ci return ret; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci vref_mv = regulator_get_voltage(st->reg); 81662306a36Sopenharmony_ci if (vref_mv < 0) 81762306a36Sopenharmony_ci return vref_mv; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci vref_mv /= 1000; 82062306a36Sopenharmony_ci } else { 82162306a36Sopenharmony_ci vref_mv = 1170; /* Build-in ref */ 82262306a36Sopenharmony_ci } 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci st->chip_info = 82562306a36Sopenharmony_ci &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci indio_dev->name = spi_get_device_id(spi)->name; 82862306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 82962306a36Sopenharmony_ci indio_dev->channels = st->chip_info->channels; 83062306a36Sopenharmony_ci indio_dev->num_channels = st->chip_info->num_channels; 83162306a36Sopenharmony_ci indio_dev->info = st->chip_info->iio_info; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); 83462306a36Sopenharmony_ci if (ret) 83562306a36Sopenharmony_ci return ret; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci ret = ad7793_setup(indio_dev, pdata, vref_mv); 83862306a36Sopenharmony_ci if (ret) 83962306a36Sopenharmony_ci return ret; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci return devm_iio_device_register(&spi->dev, indio_dev); 84262306a36Sopenharmony_ci} 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_cistatic const struct spi_device_id ad7793_id[] = { 84562306a36Sopenharmony_ci {"ad7785", ID_AD7785}, 84662306a36Sopenharmony_ci {"ad7792", ID_AD7792}, 84762306a36Sopenharmony_ci {"ad7793", ID_AD7793}, 84862306a36Sopenharmony_ci {"ad7794", ID_AD7794}, 84962306a36Sopenharmony_ci {"ad7795", ID_AD7795}, 85062306a36Sopenharmony_ci {"ad7796", ID_AD7796}, 85162306a36Sopenharmony_ci {"ad7797", ID_AD7797}, 85262306a36Sopenharmony_ci {"ad7798", ID_AD7798}, 85362306a36Sopenharmony_ci {"ad7799", ID_AD7799}, 85462306a36Sopenharmony_ci {} 85562306a36Sopenharmony_ci}; 85662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad7793_id); 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_cistatic struct spi_driver ad7793_driver = { 85962306a36Sopenharmony_ci .driver = { 86062306a36Sopenharmony_ci .name = "ad7793", 86162306a36Sopenharmony_ci }, 86262306a36Sopenharmony_ci .probe = ad7793_probe, 86362306a36Sopenharmony_ci .id_table = ad7793_id, 86462306a36Sopenharmony_ci}; 86562306a36Sopenharmony_cimodule_spi_driver(ad7793_driver); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ciMODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 86862306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD7793 and similar ADCs"); 86962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 87062306a36Sopenharmony_ciMODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); 871