162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2022 Analog Devices, Inc.
462306a36Sopenharmony_ci * Author: Cosmin Tanislav <cosmin.tanislav@analog.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/bitfield.h>
862306a36Sopenharmony_ci#include <linux/bitops.h>
962306a36Sopenharmony_ci#include <linux/crc8.h>
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1262306a36Sopenharmony_ci#include <linux/interrupt.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/regmap.h>
1562306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1662306a36Sopenharmony_ci#include <linux/spi/spi.h>
1762306a36Sopenharmony_ci#include <linux/units.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <asm/unaligned.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <linux/iio/buffer.h>
2262306a36Sopenharmony_ci#include <linux/iio/iio.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
2762306a36Sopenharmony_ci#define AD74115_NAME				"ad74115"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define AD74115_CH_FUNC_SETUP_REG		0x01
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_REG			0x02
3262306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV2_RATE_MASK	GENMASK(15, 13)
3362306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV1_RATE_MASK	GENMASK(12, 10)
3462306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV2_RANGE_MASK	GENMASK(9, 7)
3562306a36Sopenharmony_ci#define AD74115_ADC_CONFIG_CONV1_RANGE_MASK	GENMASK(6, 4)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define AD74115_PWR_OPTIM_CONFIG_REG		0x03
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define AD74115_DIN_CONFIG1_REG			0x04
4062306a36Sopenharmony_ci#define AD74115_DIN_COMPARATOR_EN_MASK		BIT(13)
4162306a36Sopenharmony_ci#define AD74115_DIN_SINK_MASK			GENMASK(11, 7)
4262306a36Sopenharmony_ci#define AD74115_DIN_DEBOUNCE_MASK		GENMASK(4, 0)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define AD74115_DIN_CONFIG2_REG			0x05
4562306a36Sopenharmony_ci#define AD74115_COMP_THRESH_MASK		GENMASK(6, 0)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define AD74115_OUTPUT_CONFIG_REG		0x06
4862306a36Sopenharmony_ci#define AD74115_OUTPUT_SLEW_EN_MASK		GENMASK(6, 5)
4962306a36Sopenharmony_ci#define AD74115_OUTPUT_SLEW_LIN_STEP_MASK	GENMASK(4, 3)
5062306a36Sopenharmony_ci#define AD74115_OUTPUT_SLEW_LIN_RATE_MASK	GENMASK(2, 1)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define AD74115_RTD3W4W_CONFIG_REG		0x07
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define AD74115_BURNOUT_CONFIG_REG		0x0a
5562306a36Sopenharmony_ci#define AD74115_BURNOUT_EXT2_EN_MASK		BIT(10)
5662306a36Sopenharmony_ci#define AD74115_BURNOUT_EXT1_EN_MASK		BIT(5)
5762306a36Sopenharmony_ci#define AD74115_BURNOUT_VIOUT_EN_MASK		BIT(0)
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#define AD74115_DAC_CODE_REG			0x0b
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define AD74115_DAC_ACTIVE_REG			0x0d
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_X_REG(x)		(0x35 + (x))
6462306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_GPI_DATA		BIT(5)
6562306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_GPO_DATA		BIT(4)
6662306a36Sopenharmony_ci#define AD74115_GPIO_CONFIG_SELECT_MASK		GENMASK(2, 0)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#define AD74115_CHARGE_PUMP_REG			0x3a
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define AD74115_ADC_CONV_CTRL_REG		0x3b
7162306a36Sopenharmony_ci#define AD74115_ADC_CONV_SEQ_MASK		GENMASK(13, 12)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define AD74115_DIN_COMP_OUT_REG		0x40
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci#define AD74115_LIVE_STATUS_REG			0x42
7662306a36Sopenharmony_ci#define AD74115_ADC_DATA_RDY_MASK		BIT(3)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define AD74115_READ_SELECT_REG			0x64
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define AD74115_CMD_KEY_REG			0x78
8162306a36Sopenharmony_ci#define AD74115_CMD_KEY_RESET1			0x15fa
8262306a36Sopenharmony_ci#define AD74115_CMD_KEY_RESET2			0xaf51
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define AD74115_CRC_POLYNOMIAL			0x7
8562306a36Sopenharmony_ciDECLARE_CRC8_TABLE(ad74115_crc8_table);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define AD74115_ADC_CODE_MAX			((int)GENMASK(15, 0))
8862306a36Sopenharmony_ci#define AD74115_ADC_CODE_HALF			(AD74115_ADC_CODE_MAX / 2)
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define AD74115_DAC_VOLTAGE_MAX			12000
9162306a36Sopenharmony_ci#define AD74115_DAC_CURRENT_MAX			25
9262306a36Sopenharmony_ci#define AD74115_DAC_CODE_MAX			((int)GENMASK(13, 0))
9362306a36Sopenharmony_ci#define AD74115_DAC_CODE_HALF			(AD74115_DAC_CODE_MAX / 2)
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#define AD74115_COMP_THRESH_MAX			98
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define AD74115_SENSE_RESISTOR_OHMS		100
9862306a36Sopenharmony_ci#define AD74115_REF_RESISTOR_OHMS		2100
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define AD74115_DIN_SINK_LOW_STEP		120
10162306a36Sopenharmony_ci#define AD74115_DIN_SINK_HIGH_STEP		240
10262306a36Sopenharmony_ci#define AD74115_DIN_SINK_MAX			31
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci#define AD74115_FRAME_SIZE			4
10562306a36Sopenharmony_ci#define AD74115_GPIO_NUM			4
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci#define AD74115_CONV_TIME_US			1000000
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cienum ad74115_dac_ch {
11062306a36Sopenharmony_ci	AD74115_DAC_CH_MAIN,
11162306a36Sopenharmony_ci	AD74115_DAC_CH_COMPARATOR,
11262306a36Sopenharmony_ci};
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cienum ad74115_adc_ch {
11562306a36Sopenharmony_ci	AD74115_ADC_CH_CONV1,
11662306a36Sopenharmony_ci	AD74115_ADC_CH_CONV2,
11762306a36Sopenharmony_ci	AD74115_ADC_CH_NUM
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cienum ad74115_ch_func {
12162306a36Sopenharmony_ci	AD74115_CH_FUNC_HIGH_IMPEDANCE,
12262306a36Sopenharmony_ci	AD74115_CH_FUNC_VOLTAGE_OUTPUT,
12362306a36Sopenharmony_ci	AD74115_CH_FUNC_CURRENT_OUTPUT,
12462306a36Sopenharmony_ci	AD74115_CH_FUNC_VOLTAGE_INPUT,
12562306a36Sopenharmony_ci	AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER,
12662306a36Sopenharmony_ci	AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER,
12762306a36Sopenharmony_ci	AD74115_CH_FUNC_2_WIRE_RESISTANCE_INPUT,
12862306a36Sopenharmony_ci	AD74115_CH_FUNC_3_4_WIRE_RESISTANCE_INPUT,
12962306a36Sopenharmony_ci	AD74115_CH_FUNC_DIGITAL_INPUT_LOGIC,
13062306a36Sopenharmony_ci	AD74115_CH_FUNC_DIGITAL_INPUT_LOOP_POWER,
13162306a36Sopenharmony_ci	AD74115_CH_FUNC_CURRENT_OUTPUT_HART,
13262306a36Sopenharmony_ci	AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER_HART,
13362306a36Sopenharmony_ci	AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART,
13462306a36Sopenharmony_ci	AD74115_CH_FUNC_MAX = AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART,
13562306a36Sopenharmony_ci	AD74115_CH_FUNC_NUM
13662306a36Sopenharmony_ci};
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cienum ad74115_adc_range {
13962306a36Sopenharmony_ci	AD74115_ADC_RANGE_12V,
14062306a36Sopenharmony_ci	AD74115_ADC_RANGE_12V_BIPOLAR,
14162306a36Sopenharmony_ci	AD74115_ADC_RANGE_2_5V_BIPOLAR,
14262306a36Sopenharmony_ci	AD74115_ADC_RANGE_2_5V_NEG,
14362306a36Sopenharmony_ci	AD74115_ADC_RANGE_2_5V,
14462306a36Sopenharmony_ci	AD74115_ADC_RANGE_0_625V,
14562306a36Sopenharmony_ci	AD74115_ADC_RANGE_104MV_BIPOLAR,
14662306a36Sopenharmony_ci	AD74115_ADC_RANGE_12V_OTHER,
14762306a36Sopenharmony_ci	AD74115_ADC_RANGE_MAX = AD74115_ADC_RANGE_12V_OTHER,
14862306a36Sopenharmony_ci	AD74115_ADC_RANGE_NUM
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cienum ad74115_adc_conv_seq {
15262306a36Sopenharmony_ci	AD74115_ADC_CONV_SEQ_STANDBY = 0b00,
15362306a36Sopenharmony_ci	AD74115_ADC_CONV_SEQ_SINGLE = 0b01,
15462306a36Sopenharmony_ci	AD74115_ADC_CONV_SEQ_CONTINUOUS = 0b10,
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cienum ad74115_din_threshold_mode {
15862306a36Sopenharmony_ci	AD74115_DIN_THRESHOLD_MODE_AVDD,
15962306a36Sopenharmony_ci	AD74115_DIN_THRESHOLD_MODE_FIXED,
16062306a36Sopenharmony_ci	AD74115_DIN_THRESHOLD_MODE_MAX = AD74115_DIN_THRESHOLD_MODE_FIXED,
16162306a36Sopenharmony_ci};
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cienum ad74115_slew_mode {
16462306a36Sopenharmony_ci	AD74115_SLEW_MODE_DISABLED,
16562306a36Sopenharmony_ci	AD74115_SLEW_MODE_LINEAR,
16662306a36Sopenharmony_ci	AD74115_SLEW_MODE_HART,
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cienum ad74115_slew_step {
17062306a36Sopenharmony_ci	AD74115_SLEW_STEP_0_8_PERCENT,
17162306a36Sopenharmony_ci	AD74115_SLEW_STEP_1_5_PERCENT,
17262306a36Sopenharmony_ci	AD74115_SLEW_STEP_6_1_PERCENT,
17362306a36Sopenharmony_ci	AD74115_SLEW_STEP_22_2_PERCENT,
17462306a36Sopenharmony_ci};
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cienum ad74115_slew_rate {
17762306a36Sopenharmony_ci	AD74115_SLEW_RATE_4KHZ,
17862306a36Sopenharmony_ci	AD74115_SLEW_RATE_64KHZ,
17962306a36Sopenharmony_ci	AD74115_SLEW_RATE_150KHZ,
18062306a36Sopenharmony_ci	AD74115_SLEW_RATE_240KHZ,
18162306a36Sopenharmony_ci};
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cienum ad74115_gpio_config {
18462306a36Sopenharmony_ci	AD74115_GPIO_CONFIG_OUTPUT_BUFFERED = 0b010,
18562306a36Sopenharmony_ci	AD74115_GPIO_CONFIG_INPUT = 0b011,
18662306a36Sopenharmony_ci};
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_cienum ad74115_gpio_mode {
18962306a36Sopenharmony_ci	AD74115_GPIO_MODE_LOGIC = 1,
19062306a36Sopenharmony_ci	AD74115_GPIO_MODE_SPECIAL = 2,
19162306a36Sopenharmony_ci};
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistruct ad74115_channels {
19462306a36Sopenharmony_ci	struct iio_chan_spec		*channels;
19562306a36Sopenharmony_ci	unsigned int			num_channels;
19662306a36Sopenharmony_ci};
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistruct ad74115_state {
19962306a36Sopenharmony_ci	struct spi_device		*spi;
20062306a36Sopenharmony_ci	struct regmap			*regmap;
20162306a36Sopenharmony_ci	struct iio_trigger		*trig;
20262306a36Sopenharmony_ci	struct regulator		*avdd;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	/*
20562306a36Sopenharmony_ci	 * Synchronize consecutive operations when doing a one-shot
20662306a36Sopenharmony_ci	 * conversion and when updating the ADC samples SPI message.
20762306a36Sopenharmony_ci	 */
20862306a36Sopenharmony_ci	struct mutex			lock;
20962306a36Sopenharmony_ci	struct gpio_chip		gc;
21062306a36Sopenharmony_ci	struct gpio_chip		comp_gc;
21162306a36Sopenharmony_ci	int				irq;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	unsigned int			avdd_mv;
21462306a36Sopenharmony_ci	unsigned long			gpio_valid_mask;
21562306a36Sopenharmony_ci	bool				dac_bipolar;
21662306a36Sopenharmony_ci	bool				dac_hart_slew;
21762306a36Sopenharmony_ci	bool				rtd_mode_4_wire;
21862306a36Sopenharmony_ci	enum ad74115_ch_func		ch_func;
21962306a36Sopenharmony_ci	enum ad74115_din_threshold_mode	din_threshold_mode;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	struct completion		adc_data_completion;
22262306a36Sopenharmony_ci	struct spi_message		adc_samples_msg;
22362306a36Sopenharmony_ci	struct spi_transfer		adc_samples_xfer[AD74115_ADC_CH_NUM + 1];
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	/*
22662306a36Sopenharmony_ci	 * DMA (thus cache coherency maintenance) requires the
22762306a36Sopenharmony_ci	 * transfer buffers to live in their own cache lines.
22862306a36Sopenharmony_ci	 */
22962306a36Sopenharmony_ci	u8				reg_tx_buf[AD74115_FRAME_SIZE] __aligned(IIO_DMA_MINALIGN);
23062306a36Sopenharmony_ci	u8				reg_rx_buf[AD74115_FRAME_SIZE];
23162306a36Sopenharmony_ci	u8				adc_samples_tx_buf[AD74115_FRAME_SIZE * AD74115_ADC_CH_NUM];
23262306a36Sopenharmony_ci	u8				adc_samples_rx_buf[AD74115_FRAME_SIZE * AD74115_ADC_CH_NUM];
23362306a36Sopenharmony_ci};
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistruct ad74115_fw_prop {
23662306a36Sopenharmony_ci	const char			*name;
23762306a36Sopenharmony_ci	bool				is_boolean;
23862306a36Sopenharmony_ci	bool				negate;
23962306a36Sopenharmony_ci	unsigned int			max;
24062306a36Sopenharmony_ci	unsigned int			reg;
24162306a36Sopenharmony_ci	unsigned int			mask;
24262306a36Sopenharmony_ci	const unsigned int		*lookup_tbl;
24362306a36Sopenharmony_ci	unsigned int			lookup_tbl_len;
24462306a36Sopenharmony_ci};
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci#define AD74115_FW_PROP(_name, _max, _reg, _mask)		\
24762306a36Sopenharmony_ci{								\
24862306a36Sopenharmony_ci	.name = (_name),					\
24962306a36Sopenharmony_ci	.max = (_max),						\
25062306a36Sopenharmony_ci	.reg = (_reg),						\
25162306a36Sopenharmony_ci	.mask = (_mask),					\
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci#define AD74115_FW_PROP_TBL(_name, _tbl, _reg, _mask)		\
25562306a36Sopenharmony_ci{								\
25662306a36Sopenharmony_ci	.name = (_name),					\
25762306a36Sopenharmony_ci	.reg = (_reg),						\
25862306a36Sopenharmony_ci	.mask = (_mask),					\
25962306a36Sopenharmony_ci	.lookup_tbl = (_tbl),					\
26062306a36Sopenharmony_ci	.lookup_tbl_len = ARRAY_SIZE(_tbl),			\
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci#define AD74115_FW_PROP_BOOL(_name, _reg, _mask)		\
26462306a36Sopenharmony_ci{								\
26562306a36Sopenharmony_ci	.name = (_name),					\
26662306a36Sopenharmony_ci	.is_boolean = true,					\
26762306a36Sopenharmony_ci	.reg = (_reg),						\
26862306a36Sopenharmony_ci	.mask = (_mask),					\
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci#define AD74115_FW_PROP_BOOL_NEG(_name, _reg, _mask)		\
27262306a36Sopenharmony_ci{								\
27362306a36Sopenharmony_ci	.name = (_name),					\
27462306a36Sopenharmony_ci	.is_boolean = true,					\
27562306a36Sopenharmony_ci	.negate = true,						\
27662306a36Sopenharmony_ci	.reg = (_reg),						\
27762306a36Sopenharmony_ci	.mask = (_mask),					\
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic const int ad74115_dac_rate_tbl[] = {
28162306a36Sopenharmony_ci	0,
28262306a36Sopenharmony_ci	4 * 8,
28362306a36Sopenharmony_ci	4 * 15,
28462306a36Sopenharmony_ci	4 * 61,
28562306a36Sopenharmony_ci	4 * 222,
28662306a36Sopenharmony_ci	64 * 8,
28762306a36Sopenharmony_ci	64 * 15,
28862306a36Sopenharmony_ci	64 * 61,
28962306a36Sopenharmony_ci	64 * 222,
29062306a36Sopenharmony_ci	150 * 8,
29162306a36Sopenharmony_ci	150 * 15,
29262306a36Sopenharmony_ci	150 * 61,
29362306a36Sopenharmony_ci	150 * 222,
29462306a36Sopenharmony_ci	240 * 8,
29562306a36Sopenharmony_ci	240 * 15,
29662306a36Sopenharmony_ci	240 * 61,
29762306a36Sopenharmony_ci	240 * 222,
29862306a36Sopenharmony_ci};
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic const unsigned int ad74115_dac_rate_step_tbl[][3] = {
30162306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_DISABLED },
30262306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_4KHZ },
30362306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_4KHZ },
30462306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_4KHZ },
30562306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_4KHZ },
30662306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_64KHZ },
30762306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_64KHZ },
30862306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_64KHZ },
30962306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_64KHZ },
31062306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_150KHZ },
31162306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_150KHZ },
31262306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_150KHZ },
31362306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_150KHZ },
31462306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_240KHZ },
31562306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_240KHZ },
31662306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_240KHZ },
31762306a36Sopenharmony_ci	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_240KHZ },
31862306a36Sopenharmony_ci};
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_cistatic const unsigned int ad74115_rtd_excitation_current_ua_tbl[] = {
32162306a36Sopenharmony_ci	250, 500, 750, 1000
32262306a36Sopenharmony_ci};
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic const unsigned int ad74115_burnout_current_na_tbl[] = {
32562306a36Sopenharmony_ci	0, 50, 0, 500, 1000, 0, 10000, 0
32662306a36Sopenharmony_ci};
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic const unsigned int ad74115_viout_burnout_current_na_tbl[] = {
32962306a36Sopenharmony_ci	0, 0, 0, 0, 1000, 0, 10000, 0
33062306a36Sopenharmony_ci};
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistatic const unsigned int ad74115_gpio_mode_tbl[] = {
33362306a36Sopenharmony_ci	0, 0, 0, 1, 2, 3, 4, 5
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic const unsigned int ad74115_adc_conv_rate_tbl[] = {
33762306a36Sopenharmony_ci	10, 20, 1200, 4800, 9600
33862306a36Sopenharmony_ci};
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistatic const unsigned int ad74115_debounce_tbl[] = {
34162306a36Sopenharmony_ci	0,     13,    18,    24,    32,    42,    56,    75,
34262306a36Sopenharmony_ci	100,   130,   180,   240,   320,   420,   560,   750,
34362306a36Sopenharmony_ci	1000,  1300,  1800,  2400,  3200,  4200,  5600,  7500,
34462306a36Sopenharmony_ci	10000, 13000, 18000, 24000, 32000, 42000, 56000, 75000,
34562306a36Sopenharmony_ci};
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic const unsigned int ad74115_adc_ch_data_regs_tbl[] = {
34862306a36Sopenharmony_ci	[AD74115_ADC_CH_CONV1] = 0x44,
34962306a36Sopenharmony_ci	[AD74115_ADC_CH_CONV2] = 0x46,
35062306a36Sopenharmony_ci};
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_cistatic const unsigned int ad74115_adc_ch_en_bit_tbl[] = {
35362306a36Sopenharmony_ci	[AD74115_ADC_CH_CONV1] = BIT(0),
35462306a36Sopenharmony_ci	[AD74115_ADC_CH_CONV2] = BIT(1),
35562306a36Sopenharmony_ci};
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic const bool ad74115_adc_bipolar_tbl[AD74115_ADC_RANGE_NUM] = {
35862306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V_BIPOLAR]		= true,
35962306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= true,
36062306a36Sopenharmony_ci	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= true,
36162306a36Sopenharmony_ci};
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic const unsigned int ad74115_adc_conv_mul_tbl[AD74115_ADC_RANGE_NUM] = {
36462306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V]			= 12000,
36562306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V_BIPOLAR]		= 24000,
36662306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= 5000,
36762306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V_NEG]		= 2500,
36862306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V]		= 2500,
36962306a36Sopenharmony_ci	[AD74115_ADC_RANGE_0_625V]		= 625,
37062306a36Sopenharmony_ci	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= 208,
37162306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V_OTHER]		= 12000,
37262306a36Sopenharmony_ci};
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_cistatic const unsigned int ad74115_adc_gain_tbl[AD74115_ADC_RANGE_NUM][2] = {
37562306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V]			= { 5, 24 },
37662306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V_BIPOLAR]		= { 5, 24 },
37762306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= { 1, 1 },
37862306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V_NEG]		= { 1, 1 },
37962306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V]		= { 1, 1 },
38062306a36Sopenharmony_ci	[AD74115_ADC_RANGE_0_625V]		= { 4, 1 },
38162306a36Sopenharmony_ci	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= { 24, 1 },
38262306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V_OTHER]		= { 5, 24 },
38362306a36Sopenharmony_ci};
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cistatic const int ad74115_adc_range_tbl[AD74115_ADC_RANGE_NUM][2] = {
38662306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V]			= { 0,         12000000 },
38762306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V_BIPOLAR]		= { -12000000, 12000000 },
38862306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= { -2500000,  2500000 },
38962306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V_NEG]		= { -2500000,  0 },
39062306a36Sopenharmony_ci	[AD74115_ADC_RANGE_2_5V]		= { 0,         2500000 },
39162306a36Sopenharmony_ci	[AD74115_ADC_RANGE_0_625V]		= { 0,         625000 },
39262306a36Sopenharmony_ci	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= { -104000,   104000 },
39362306a36Sopenharmony_ci	[AD74115_ADC_RANGE_12V_OTHER]		= { 0,         12000000 },
39462306a36Sopenharmony_ci};
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic int _ad74115_find_tbl_index(const unsigned int *tbl, unsigned int tbl_len,
39762306a36Sopenharmony_ci				   unsigned int val, unsigned int *index)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	unsigned int i;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	for (i = 0; i < tbl_len; i++)
40262306a36Sopenharmony_ci		if (val == tbl[i]) {
40362306a36Sopenharmony_ci			*index = i;
40462306a36Sopenharmony_ci			return 0;
40562306a36Sopenharmony_ci		}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	return -EINVAL;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci#define ad74115_find_tbl_index(tbl, val, index)	\
41162306a36Sopenharmony_ci	_ad74115_find_tbl_index(tbl, ARRAY_SIZE(tbl), val, index)
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic int ad74115_crc(u8 *buf)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	return crc8(ad74115_crc8_table, buf, 3, 0);
41662306a36Sopenharmony_ci}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_cistatic void ad74115_format_reg_write(u8 reg, u16 val, u8 *buf)
41962306a36Sopenharmony_ci{
42062306a36Sopenharmony_ci	buf[0] = reg;
42162306a36Sopenharmony_ci	put_unaligned_be16(val, &buf[1]);
42262306a36Sopenharmony_ci	buf[3] = ad74115_crc(buf);
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_cistatic int ad74115_reg_write(void *context, unsigned int reg, unsigned int val)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	struct ad74115_state *st = context;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	ad74115_format_reg_write(reg, val, st->reg_tx_buf);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	return spi_write(st->spi, st->reg_tx_buf, AD74115_FRAME_SIZE);
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic int ad74115_crc_check(struct ad74115_state *st, u8 *buf)
43562306a36Sopenharmony_ci{
43662306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
43762306a36Sopenharmony_ci	u8 expected_crc = ad74115_crc(buf);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	if (buf[3] != expected_crc) {
44062306a36Sopenharmony_ci		dev_err(dev, "Bad CRC %02x for %02x%02x%02x, expected %02x\n",
44162306a36Sopenharmony_ci			buf[3], buf[0], buf[1], buf[2], expected_crc);
44262306a36Sopenharmony_ci		return -EINVAL;
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	return 0;
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_cistatic int ad74115_reg_read(void *context, unsigned int reg, unsigned int *val)
44962306a36Sopenharmony_ci{
45062306a36Sopenharmony_ci	struct ad74115_state *st = context;
45162306a36Sopenharmony_ci	struct spi_transfer reg_read_xfer[] = {
45262306a36Sopenharmony_ci		{
45362306a36Sopenharmony_ci			.tx_buf = st->reg_tx_buf,
45462306a36Sopenharmony_ci			.len = sizeof(st->reg_tx_buf),
45562306a36Sopenharmony_ci			.cs_change = 1,
45662306a36Sopenharmony_ci		},
45762306a36Sopenharmony_ci		{
45862306a36Sopenharmony_ci			.rx_buf = st->reg_rx_buf,
45962306a36Sopenharmony_ci			.len = sizeof(st->reg_rx_buf),
46062306a36Sopenharmony_ci		},
46162306a36Sopenharmony_ci	};
46262306a36Sopenharmony_ci	int ret;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	ad74115_format_reg_write(AD74115_READ_SELECT_REG, reg, st->reg_tx_buf);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	ret = spi_sync_transfer(st->spi, reg_read_xfer, ARRAY_SIZE(reg_read_xfer));
46762306a36Sopenharmony_ci	if (ret)
46862306a36Sopenharmony_ci		return ret;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	ret = ad74115_crc_check(st, st->reg_rx_buf);
47162306a36Sopenharmony_ci	if (ret)
47262306a36Sopenharmony_ci		return ret;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	*val = get_unaligned_be16(&st->reg_rx_buf[1]);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	return 0;
47762306a36Sopenharmony_ci}
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_cistatic const struct regmap_config ad74115_regmap_config = {
48062306a36Sopenharmony_ci	.reg_bits = 8,
48162306a36Sopenharmony_ci	.val_bits = 16,
48262306a36Sopenharmony_ci	.reg_read = ad74115_reg_read,
48362306a36Sopenharmony_ci	.reg_write = ad74115_reg_write,
48462306a36Sopenharmony_ci};
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_cistatic int ad74115_gpio_config_set(struct ad74115_state *st, unsigned int offset,
48762306a36Sopenharmony_ci				   enum ad74115_gpio_config cfg)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset),
49062306a36Sopenharmony_ci				  AD74115_GPIO_CONFIG_SELECT_MASK,
49162306a36Sopenharmony_ci				  FIELD_PREP(AD74115_GPIO_CONFIG_SELECT_MASK, cfg));
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_cistatic int ad74115_gpio_init_valid_mask(struct gpio_chip *gc,
49562306a36Sopenharmony_ci					unsigned long *valid_mask,
49662306a36Sopenharmony_ci					unsigned int ngpios)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(gc);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	*valid_mask = st->gpio_valid_mask;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	return 0;
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic int ad74115_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(gc);
50862306a36Sopenharmony_ci	unsigned int val;
50962306a36Sopenharmony_ci	int ret;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), &val);
51262306a36Sopenharmony_ci	if (ret)
51362306a36Sopenharmony_ci		return ret;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	return FIELD_GET(AD74115_GPIO_CONFIG_SELECT_MASK, val) == AD74115_GPIO_CONFIG_INPUT;
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic int ad74115_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(gc);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	return ad74115_gpio_config_set(st, offset, AD74115_GPIO_CONFIG_INPUT);
52362306a36Sopenharmony_ci}
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_cistatic int ad74115_gpio_direction_output(struct gpio_chip *gc, unsigned int offset,
52662306a36Sopenharmony_ci					 int value)
52762306a36Sopenharmony_ci{
52862306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(gc);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	return ad74115_gpio_config_set(st, offset, AD74115_GPIO_CONFIG_OUTPUT_BUFFERED);
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_cistatic int ad74115_gpio_get(struct gpio_chip *gc, unsigned int offset)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(gc);
53662306a36Sopenharmony_ci	unsigned int val;
53762306a36Sopenharmony_ci	int ret;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), &val);
54062306a36Sopenharmony_ci	if (ret)
54162306a36Sopenharmony_ci		return ret;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	return FIELD_GET(AD74115_GPIO_CONFIG_GPI_DATA, val);
54462306a36Sopenharmony_ci}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_cistatic void ad74115_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
54762306a36Sopenharmony_ci{
54862306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(gc);
54962306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
55062306a36Sopenharmony_ci	int ret;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset),
55362306a36Sopenharmony_ci				 AD74115_GPIO_CONFIG_GPO_DATA,
55462306a36Sopenharmony_ci				 FIELD_PREP(AD74115_GPIO_CONFIG_GPO_DATA, value));
55562306a36Sopenharmony_ci	if (ret)
55662306a36Sopenharmony_ci		dev_err(dev, "Failed to set GPIO %u output value, err: %d\n",
55762306a36Sopenharmony_ci			offset, ret);
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_cistatic int ad74115_set_comp_debounce(struct ad74115_state *st, unsigned int val)
56162306a36Sopenharmony_ci{
56262306a36Sopenharmony_ci	unsigned int len = ARRAY_SIZE(ad74115_debounce_tbl);
56362306a36Sopenharmony_ci	unsigned int i;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	for (i = 0; i < len; i++)
56662306a36Sopenharmony_ci		if (val <= ad74115_debounce_tbl[i])
56762306a36Sopenharmony_ci			break;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	if (i == len)
57062306a36Sopenharmony_ci		i = len - 1;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74115_DIN_CONFIG1_REG,
57362306a36Sopenharmony_ci				  AD74115_DIN_DEBOUNCE_MASK,
57462306a36Sopenharmony_ci				  FIELD_PREP(AD74115_DIN_DEBOUNCE_MASK, val));
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cistatic int ad74115_comp_gpio_get_direction(struct gpio_chip *chip,
57862306a36Sopenharmony_ci					   unsigned int offset)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	return GPIO_LINE_DIRECTION_IN;
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_cistatic int ad74115_comp_gpio_set_config(struct gpio_chip *chip,
58462306a36Sopenharmony_ci					unsigned int offset,
58562306a36Sopenharmony_ci					unsigned long config)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(chip);
58862306a36Sopenharmony_ci	u32 param = pinconf_to_config_param(config);
58962306a36Sopenharmony_ci	u32 arg = pinconf_to_config_argument(config);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	switch (param) {
59262306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_DEBOUNCE:
59362306a36Sopenharmony_ci		return ad74115_set_comp_debounce(st, arg);
59462306a36Sopenharmony_ci	default:
59562306a36Sopenharmony_ci		return -ENOTSUPP;
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_cistatic int ad74115_comp_gpio_get(struct gpio_chip *chip, unsigned int offset)
60062306a36Sopenharmony_ci{
60162306a36Sopenharmony_ci	struct ad74115_state *st = gpiochip_get_data(chip);
60262306a36Sopenharmony_ci	unsigned int val;
60362306a36Sopenharmony_ci	int ret;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_DIN_COMP_OUT_REG, &val);
60662306a36Sopenharmony_ci	if (ret)
60762306a36Sopenharmony_ci		return ret;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	return !!val;
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic irqreturn_t ad74115_trigger_handler(int irq, void *p)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	struct iio_poll_func *pf = p;
61562306a36Sopenharmony_ci	struct iio_dev *indio_dev = pf->indio_dev;
61662306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
61762306a36Sopenharmony_ci	int ret;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	ret = spi_sync(st->spi, &st->adc_samples_msg);
62062306a36Sopenharmony_ci	if (ret)
62162306a36Sopenharmony_ci		goto out;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	iio_push_to_buffers(indio_dev, st->adc_samples_rx_buf);
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ciout:
62662306a36Sopenharmony_ci	iio_trigger_notify_done(indio_dev->trig);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	return IRQ_HANDLED;
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic irqreturn_t ad74115_adc_data_interrupt(int irq, void *data)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	struct iio_dev *indio_dev = data;
63462306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	if (iio_buffer_enabled(indio_dev))
63762306a36Sopenharmony_ci		iio_trigger_poll(st->trig);
63862306a36Sopenharmony_ci	else
63962306a36Sopenharmony_ci		complete(&st->adc_data_completion);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	return IRQ_HANDLED;
64262306a36Sopenharmony_ci}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_cistatic int ad74115_set_adc_ch_en(struct ad74115_state *st,
64562306a36Sopenharmony_ci				 enum ad74115_adc_ch channel, bool status)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	unsigned int mask = ad74115_adc_ch_en_bit_tbl[channel];
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74115_ADC_CONV_CTRL_REG, mask,
65062306a36Sopenharmony_ci				  status ? mask : 0);
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic int ad74115_set_adc_conv_seq(struct ad74115_state *st,
65462306a36Sopenharmony_ci				    enum ad74115_adc_conv_seq conv_seq)
65562306a36Sopenharmony_ci{
65662306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74115_ADC_CONV_CTRL_REG,
65762306a36Sopenharmony_ci				  AD74115_ADC_CONV_SEQ_MASK,
65862306a36Sopenharmony_ci				  FIELD_PREP(AD74115_ADC_CONV_SEQ_MASK, conv_seq));
65962306a36Sopenharmony_ci}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_cistatic int ad74115_update_scan_mode(struct iio_dev *indio_dev,
66262306a36Sopenharmony_ci				    const unsigned long *active_scan_mask)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
66562306a36Sopenharmony_ci	struct spi_transfer *xfer = st->adc_samples_xfer;
66662306a36Sopenharmony_ci	u8 *rx_buf = st->adc_samples_rx_buf;
66762306a36Sopenharmony_ci	u8 *tx_buf = st->adc_samples_tx_buf;
66862306a36Sopenharmony_ci	unsigned int i;
66962306a36Sopenharmony_ci	int ret = 0;
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	mutex_lock(&st->lock);
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	spi_message_init(&st->adc_samples_msg);
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	for_each_clear_bit(i, active_scan_mask, AD74115_ADC_CH_NUM) {
67662306a36Sopenharmony_ci		ret = ad74115_set_adc_ch_en(st, i, false);
67762306a36Sopenharmony_ci		if (ret)
67862306a36Sopenharmony_ci			goto out;
67962306a36Sopenharmony_ci	}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/*
68262306a36Sopenharmony_ci	 * The read select register is used to select which register's value
68362306a36Sopenharmony_ci	 * will be sent by the slave on the next SPI frame.
68462306a36Sopenharmony_ci	 *
68562306a36Sopenharmony_ci	 * Create an SPI message that, on each step, writes to the read select
68662306a36Sopenharmony_ci	 * register to select the ADC result of the next enabled channel, and
68762306a36Sopenharmony_ci	 * reads the ADC result of the previous enabled channel.
68862306a36Sopenharmony_ci	 *
68962306a36Sopenharmony_ci	 * Example:
69062306a36Sopenharmony_ci	 * W: [WCH1] [WCH2] [WCH2] [WCH3] [    ]
69162306a36Sopenharmony_ci	 * R: [    ] [RCH1] [RCH2] [RCH3] [RCH4]
69262306a36Sopenharmony_ci	 */
69362306a36Sopenharmony_ci	for_each_set_bit(i, active_scan_mask, AD74115_ADC_CH_NUM) {
69462306a36Sopenharmony_ci		ret = ad74115_set_adc_ch_en(st, i, true);
69562306a36Sopenharmony_ci		if (ret)
69662306a36Sopenharmony_ci			goto out;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci		if (xfer == st->adc_samples_xfer)
69962306a36Sopenharmony_ci			xfer->rx_buf = NULL;
70062306a36Sopenharmony_ci		else
70162306a36Sopenharmony_ci			xfer->rx_buf = rx_buf;
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci		xfer->tx_buf = tx_buf;
70462306a36Sopenharmony_ci		xfer->len = AD74115_FRAME_SIZE;
70562306a36Sopenharmony_ci		xfer->cs_change = 1;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci		ad74115_format_reg_write(AD74115_READ_SELECT_REG,
70862306a36Sopenharmony_ci					 ad74115_adc_ch_data_regs_tbl[i], tx_buf);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci		spi_message_add_tail(xfer, &st->adc_samples_msg);
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci		tx_buf += AD74115_FRAME_SIZE;
71362306a36Sopenharmony_ci		if (xfer != st->adc_samples_xfer)
71462306a36Sopenharmony_ci			rx_buf += AD74115_FRAME_SIZE;
71562306a36Sopenharmony_ci		xfer++;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	xfer->rx_buf = rx_buf;
71962306a36Sopenharmony_ci	xfer->tx_buf = NULL;
72062306a36Sopenharmony_ci	xfer->len = AD74115_FRAME_SIZE;
72162306a36Sopenharmony_ci	xfer->cs_change = 0;
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci	spi_message_add_tail(xfer, &st->adc_samples_msg);
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ciout:
72662306a36Sopenharmony_ci	mutex_unlock(&st->lock);
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	return ret;
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_cistatic int ad74115_buffer_postenable(struct iio_dev *indio_dev)
73262306a36Sopenharmony_ci{
73362306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	return ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_CONTINUOUS);
73662306a36Sopenharmony_ci}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_cistatic int ad74115_buffer_predisable(struct iio_dev *indio_dev)
73962306a36Sopenharmony_ci{
74062306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
74162306a36Sopenharmony_ci	unsigned int i;
74262306a36Sopenharmony_ci	int ret;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	mutex_lock(&st->lock);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_STANDBY);
74762306a36Sopenharmony_ci	if (ret)
74862306a36Sopenharmony_ci		goto out;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	/*
75162306a36Sopenharmony_ci	 * update_scan_mode() is not called in the disable path, disable all
75262306a36Sopenharmony_ci	 * channels here.
75362306a36Sopenharmony_ci	 */
75462306a36Sopenharmony_ci	for (i = 0; i < AD74115_ADC_CH_NUM; i++) {
75562306a36Sopenharmony_ci		ret = ad74115_set_adc_ch_en(st, i, false);
75662306a36Sopenharmony_ci		if (ret)
75762306a36Sopenharmony_ci			goto out;
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ciout:
76162306a36Sopenharmony_ci	mutex_unlock(&st->lock);
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	return ret;
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops ad74115_buffer_ops = {
76762306a36Sopenharmony_ci	.postenable = &ad74115_buffer_postenable,
76862306a36Sopenharmony_ci	.predisable = &ad74115_buffer_predisable,
76962306a36Sopenharmony_ci};
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cistatic const struct iio_trigger_ops ad74115_trigger_ops = {
77262306a36Sopenharmony_ci	.validate_device = iio_trigger_validate_own_device,
77362306a36Sopenharmony_ci};
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_cistatic int ad74115_get_adc_rate(struct ad74115_state *st,
77662306a36Sopenharmony_ci				enum ad74115_adc_ch channel, int *val)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	unsigned int i;
77962306a36Sopenharmony_ci	int ret;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_ADC_CONFIG_REG, &i);
78262306a36Sopenharmony_ci	if (ret)
78362306a36Sopenharmony_ci		return ret;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	if (channel == AD74115_ADC_CH_CONV1)
78662306a36Sopenharmony_ci		i = FIELD_GET(AD74115_ADC_CONFIG_CONV1_RATE_MASK, i);
78762306a36Sopenharmony_ci	else
78862306a36Sopenharmony_ci		i = FIELD_GET(AD74115_ADC_CONFIG_CONV2_RATE_MASK, i);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	*val = ad74115_adc_conv_rate_tbl[i];
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	return IIO_VAL_INT;
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_cistatic int _ad74115_get_adc_code(struct ad74115_state *st,
79662306a36Sopenharmony_ci				 enum ad74115_adc_ch channel, int *val)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	unsigned int uval;
79962306a36Sopenharmony_ci	int ret;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	reinit_completion(&st->adc_data_completion);
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	ret = ad74115_set_adc_ch_en(st, channel, true);
80462306a36Sopenharmony_ci	if (ret)
80562306a36Sopenharmony_ci		return ret;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_SINGLE);
80862306a36Sopenharmony_ci	if (ret)
80962306a36Sopenharmony_ci		return ret;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	if (st->irq) {
81262306a36Sopenharmony_ci		ret = wait_for_completion_timeout(&st->adc_data_completion,
81362306a36Sopenharmony_ci						  msecs_to_jiffies(1000));
81462306a36Sopenharmony_ci		if (!ret)
81562306a36Sopenharmony_ci			return -ETIMEDOUT;
81662306a36Sopenharmony_ci	} else {
81762306a36Sopenharmony_ci		unsigned int regval, wait_time;
81862306a36Sopenharmony_ci		int rate;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci		ret = ad74115_get_adc_rate(st, channel, &rate);
82162306a36Sopenharmony_ci		if (ret < 0)
82262306a36Sopenharmony_ci			return ret;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci		wait_time = DIV_ROUND_CLOSEST(AD74115_CONV_TIME_US, rate);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci		ret = regmap_read_poll_timeout(st->regmap, AD74115_LIVE_STATUS_REG,
82762306a36Sopenharmony_ci					       regval, regval & AD74115_ADC_DATA_RDY_MASK,
82862306a36Sopenharmony_ci					       wait_time, 5 * wait_time);
82962306a36Sopenharmony_ci		if (ret)
83062306a36Sopenharmony_ci			return ret;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci		/*
83362306a36Sopenharmony_ci		 * The ADC_DATA_RDY bit is W1C.
83462306a36Sopenharmony_ci		 * See datasheet page 98, Table 62. Bit Descriptions for
83562306a36Sopenharmony_ci		 * LIVE_STATUS.
83662306a36Sopenharmony_ci		 * Although the datasheet mentions that the bit will auto-clear
83762306a36Sopenharmony_ci		 * when writing to the ADC_CONV_CTRL register, this does not
83862306a36Sopenharmony_ci		 * seem to happen.
83962306a36Sopenharmony_ci		 */
84062306a36Sopenharmony_ci		ret = regmap_write_bits(st->regmap, AD74115_LIVE_STATUS_REG,
84162306a36Sopenharmony_ci					AD74115_ADC_DATA_RDY_MASK,
84262306a36Sopenharmony_ci					FIELD_PREP(AD74115_ADC_DATA_RDY_MASK, 1));
84362306a36Sopenharmony_ci		if (ret)
84462306a36Sopenharmony_ci			return ret;
84562306a36Sopenharmony_ci	}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	ret = regmap_read(st->regmap, ad74115_adc_ch_data_regs_tbl[channel], &uval);
84862306a36Sopenharmony_ci	if (ret)
84962306a36Sopenharmony_ci		return ret;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_STANDBY);
85262306a36Sopenharmony_ci	if (ret)
85362306a36Sopenharmony_ci		return ret;
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	ret = ad74115_set_adc_ch_en(st, channel, false);
85662306a36Sopenharmony_ci	if (ret)
85762306a36Sopenharmony_ci		return ret;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	*val = uval;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	return IIO_VAL_INT;
86262306a36Sopenharmony_ci}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_cistatic int ad74115_get_adc_code(struct iio_dev *indio_dev,
86562306a36Sopenharmony_ci				enum ad74115_adc_ch channel, int *val)
86662306a36Sopenharmony_ci{
86762306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
86862306a36Sopenharmony_ci	int ret;
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	ret = iio_device_claim_direct_mode(indio_dev);
87162306a36Sopenharmony_ci	if (ret)
87262306a36Sopenharmony_ci		return ret;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	mutex_lock(&st->lock);
87562306a36Sopenharmony_ci	ret = _ad74115_get_adc_code(st, channel, val);
87662306a36Sopenharmony_ci	mutex_unlock(&st->lock);
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	iio_device_release_direct_mode(indio_dev);
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	return ret;
88162306a36Sopenharmony_ci}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_cistatic int ad74115_adc_code_to_resistance(int code, int *val, int *val2)
88462306a36Sopenharmony_ci{
88562306a36Sopenharmony_ci	if (code == AD74115_ADC_CODE_MAX)
88662306a36Sopenharmony_ci		code--;
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	*val = code * AD74115_REF_RESISTOR_OHMS;
88962306a36Sopenharmony_ci	*val2 = AD74115_ADC_CODE_MAX - code;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
89262306a36Sopenharmony_ci}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_cistatic int ad74115_set_dac_code(struct ad74115_state *st,
89562306a36Sopenharmony_ci				enum ad74115_dac_ch channel, int val)
89662306a36Sopenharmony_ci{
89762306a36Sopenharmony_ci	if (val < 0)
89862306a36Sopenharmony_ci		return -EINVAL;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	if (channel == AD74115_DAC_CH_COMPARATOR) {
90162306a36Sopenharmony_ci		if (val > AD74115_COMP_THRESH_MAX)
90262306a36Sopenharmony_ci			return -EINVAL;
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci		return regmap_update_bits(st->regmap, AD74115_DIN_CONFIG2_REG,
90562306a36Sopenharmony_ci					  AD74115_COMP_THRESH_MASK,
90662306a36Sopenharmony_ci					  FIELD_PREP(AD74115_COMP_THRESH_MASK, val));
90762306a36Sopenharmony_ci	}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	if (val > AD74115_DAC_CODE_MAX)
91062306a36Sopenharmony_ci		return -EINVAL;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	return regmap_write(st->regmap, AD74115_DAC_CODE_REG, val);
91362306a36Sopenharmony_ci}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_cistatic int ad74115_get_dac_code(struct ad74115_state *st,
91662306a36Sopenharmony_ci				enum ad74115_dac_ch channel, int *val)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	unsigned int uval;
91962306a36Sopenharmony_ci	int ret;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	if (channel == AD74115_DAC_CH_COMPARATOR)
92262306a36Sopenharmony_ci		return -EINVAL;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_DAC_ACTIVE_REG, &uval);
92562306a36Sopenharmony_ci	if (ret)
92662306a36Sopenharmony_ci		return ret;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	*val = uval;
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	return IIO_VAL_INT;
93162306a36Sopenharmony_ci}
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_cistatic int ad74115_set_adc_rate(struct ad74115_state *st,
93462306a36Sopenharmony_ci				enum ad74115_adc_ch channel, int val)
93562306a36Sopenharmony_ci{
93662306a36Sopenharmony_ci	unsigned int i;
93762306a36Sopenharmony_ci	int ret;
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	ret = ad74115_find_tbl_index(ad74115_adc_conv_rate_tbl, val, &i);
94062306a36Sopenharmony_ci	if (ret)
94162306a36Sopenharmony_ci		return ret;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	if (channel == AD74115_ADC_CH_CONV1)
94462306a36Sopenharmony_ci		return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG,
94562306a36Sopenharmony_ci					  AD74115_ADC_CONFIG_CONV1_RATE_MASK,
94662306a36Sopenharmony_ci					  FIELD_PREP(AD74115_ADC_CONFIG_CONV1_RATE_MASK, i));
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG,
94962306a36Sopenharmony_ci				  AD74115_ADC_CONFIG_CONV2_RATE_MASK,
95062306a36Sopenharmony_ci				  FIELD_PREP(AD74115_ADC_CONFIG_CONV2_RATE_MASK, i));
95162306a36Sopenharmony_ci}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_cistatic int ad74115_get_dac_rate(struct ad74115_state *st, int *val)
95462306a36Sopenharmony_ci{
95562306a36Sopenharmony_ci	unsigned int i, en_val, step_val, rate_val, tmp;
95662306a36Sopenharmony_ci	int ret;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_OUTPUT_CONFIG_REG, &tmp);
95962306a36Sopenharmony_ci	if (ret)
96062306a36Sopenharmony_ci		return ret;
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	en_val = FIELD_GET(AD74115_OUTPUT_SLEW_EN_MASK, tmp);
96362306a36Sopenharmony_ci	step_val = FIELD_GET(AD74115_OUTPUT_SLEW_LIN_STEP_MASK, tmp);
96462306a36Sopenharmony_ci	rate_val = FIELD_GET(AD74115_OUTPUT_SLEW_LIN_RATE_MASK, tmp);
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ad74115_dac_rate_step_tbl); i++)
96762306a36Sopenharmony_ci		if (en_val == ad74115_dac_rate_step_tbl[i][0] &&
96862306a36Sopenharmony_ci		    step_val == ad74115_dac_rate_step_tbl[i][1] &&
96962306a36Sopenharmony_ci		    rate_val == ad74115_dac_rate_step_tbl[i][2])
97062306a36Sopenharmony_ci			break;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	if (i == ARRAY_SIZE(ad74115_dac_rate_step_tbl))
97362306a36Sopenharmony_ci		return -EINVAL;
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	*val = ad74115_dac_rate_tbl[i];
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	return IIO_VAL_INT;
97862306a36Sopenharmony_ci}
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_cistatic int ad74115_set_dac_rate(struct ad74115_state *st, int val)
98162306a36Sopenharmony_ci{
98262306a36Sopenharmony_ci	unsigned int i, en_val, step_val, rate_val, mask, tmp;
98362306a36Sopenharmony_ci	int ret;
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	ret = ad74115_find_tbl_index(ad74115_dac_rate_tbl, val, &i);
98662306a36Sopenharmony_ci	if (ret)
98762306a36Sopenharmony_ci		return ret;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	en_val = ad74115_dac_rate_step_tbl[i][0];
99062306a36Sopenharmony_ci	step_val = ad74115_dac_rate_step_tbl[i][1];
99162306a36Sopenharmony_ci	rate_val = ad74115_dac_rate_step_tbl[i][2];
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	mask = AD74115_OUTPUT_SLEW_EN_MASK;
99462306a36Sopenharmony_ci	mask |= AD74115_OUTPUT_SLEW_LIN_STEP_MASK;
99562306a36Sopenharmony_ci	mask |= AD74115_OUTPUT_SLEW_LIN_RATE_MASK;
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	tmp = FIELD_PREP(AD74115_OUTPUT_SLEW_EN_MASK, en_val);
99862306a36Sopenharmony_ci	tmp |= FIELD_PREP(AD74115_OUTPUT_SLEW_LIN_STEP_MASK, step_val);
99962306a36Sopenharmony_ci	tmp |= FIELD_PREP(AD74115_OUTPUT_SLEW_LIN_RATE_MASK, rate_val);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74115_OUTPUT_CONFIG_REG, mask, tmp);
100262306a36Sopenharmony_ci}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_cistatic int ad74115_get_dac_scale(struct ad74115_state *st,
100562306a36Sopenharmony_ci				 struct iio_chan_spec const *chan,
100662306a36Sopenharmony_ci				 int *val, int *val2)
100762306a36Sopenharmony_ci{
100862306a36Sopenharmony_ci	if (chan->channel == AD74115_DAC_CH_MAIN) {
100962306a36Sopenharmony_ci		if (chan->type == IIO_VOLTAGE) {
101062306a36Sopenharmony_ci			*val = AD74115_DAC_VOLTAGE_MAX;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci			if (st->dac_bipolar)
101362306a36Sopenharmony_ci				*val *= 2;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci		} else {
101662306a36Sopenharmony_ci			*val = AD74115_DAC_CURRENT_MAX;
101762306a36Sopenharmony_ci		}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci		*val2 = AD74115_DAC_CODE_MAX;
102062306a36Sopenharmony_ci	} else {
102162306a36Sopenharmony_ci		if (st->din_threshold_mode == AD74115_DIN_THRESHOLD_MODE_AVDD) {
102262306a36Sopenharmony_ci			*val = 196 * st->avdd_mv;
102362306a36Sopenharmony_ci			*val2 = 10 * AD74115_COMP_THRESH_MAX;
102462306a36Sopenharmony_ci		} else {
102562306a36Sopenharmony_ci			*val = 49000;
102662306a36Sopenharmony_ci			*val2 = AD74115_COMP_THRESH_MAX;
102762306a36Sopenharmony_ci		}
102862306a36Sopenharmony_ci	}
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
103162306a36Sopenharmony_ci}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_cistatic int ad74115_get_dac_offset(struct ad74115_state *st,
103462306a36Sopenharmony_ci				  struct iio_chan_spec const *chan, int *val)
103562306a36Sopenharmony_ci{
103662306a36Sopenharmony_ci	if (chan->channel == AD74115_DAC_CH_MAIN) {
103762306a36Sopenharmony_ci		if (chan->type == IIO_VOLTAGE && st->dac_bipolar)
103862306a36Sopenharmony_ci			*val = -AD74115_DAC_CODE_HALF;
103962306a36Sopenharmony_ci		else
104062306a36Sopenharmony_ci			*val = 0;
104162306a36Sopenharmony_ci	} else {
104262306a36Sopenharmony_ci		if (st->din_threshold_mode == AD74115_DIN_THRESHOLD_MODE_AVDD)
104362306a36Sopenharmony_ci			*val = -48;
104462306a36Sopenharmony_ci		else
104562306a36Sopenharmony_ci			*val = -38;
104662306a36Sopenharmony_ci	}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	return IIO_VAL_INT;
104962306a36Sopenharmony_ci}
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_cistatic int ad74115_get_adc_range(struct ad74115_state *st,
105262306a36Sopenharmony_ci				 enum ad74115_adc_ch channel, unsigned int *val)
105362306a36Sopenharmony_ci{
105462306a36Sopenharmony_ci	int ret;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_ADC_CONFIG_REG, val);
105762306a36Sopenharmony_ci	if (ret)
105862306a36Sopenharmony_ci		return ret;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	if (channel == AD74115_ADC_CH_CONV1)
106162306a36Sopenharmony_ci		*val = FIELD_GET(AD74115_ADC_CONFIG_CONV1_RANGE_MASK, *val);
106262306a36Sopenharmony_ci	else
106362306a36Sopenharmony_ci		*val = FIELD_GET(AD74115_ADC_CONFIG_CONV2_RANGE_MASK, *val);
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	return 0;
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_cistatic int ad74115_get_adc_resistance_scale(struct ad74115_state *st,
106962306a36Sopenharmony_ci					    unsigned int range,
107062306a36Sopenharmony_ci					    int *val, int *val2)
107162306a36Sopenharmony_ci{
107262306a36Sopenharmony_ci	*val = ad74115_adc_gain_tbl[range][1] * AD74115_REF_RESISTOR_OHMS;
107362306a36Sopenharmony_ci	*val2 = ad74115_adc_gain_tbl[range][0];
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	if (ad74115_adc_bipolar_tbl[range])
107662306a36Sopenharmony_ci		*val2 *= AD74115_ADC_CODE_HALF;
107762306a36Sopenharmony_ci	else
107862306a36Sopenharmony_ci		*val2 *= AD74115_ADC_CODE_MAX;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
108162306a36Sopenharmony_ci}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_cistatic int ad74115_get_adc_scale(struct ad74115_state *st,
108462306a36Sopenharmony_ci				 struct iio_chan_spec const *chan,
108562306a36Sopenharmony_ci				 int *val, int *val2)
108662306a36Sopenharmony_ci{
108762306a36Sopenharmony_ci	unsigned int range;
108862306a36Sopenharmony_ci	int ret;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	ret = ad74115_get_adc_range(st, chan->channel, &range);
109162306a36Sopenharmony_ci	if (ret)
109262306a36Sopenharmony_ci		return ret;
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	if (chan->type == IIO_RESISTANCE)
109562306a36Sopenharmony_ci		return ad74115_get_adc_resistance_scale(st, range, val, val2);
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	*val = ad74115_adc_conv_mul_tbl[range];
109862306a36Sopenharmony_ci	*val2 = AD74115_ADC_CODE_MAX;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	if (chan->type == IIO_CURRENT)
110162306a36Sopenharmony_ci		*val2 *= AD74115_SENSE_RESISTOR_OHMS;
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
110462306a36Sopenharmony_ci}
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_cistatic int ad74115_get_adc_resistance_offset(struct ad74115_state *st,
110762306a36Sopenharmony_ci					     unsigned int range,
110862306a36Sopenharmony_ci					     int *val, int *val2)
110962306a36Sopenharmony_ci{
111062306a36Sopenharmony_ci	unsigned int d = 10 * AD74115_REF_RESISTOR_OHMS
111162306a36Sopenharmony_ci			 * ad74115_adc_gain_tbl[range][1];
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	*val = 5;
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	if (ad74115_adc_bipolar_tbl[range])
111662306a36Sopenharmony_ci		*val -= AD74115_ADC_CODE_HALF;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	*val *= d;
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	if (!st->rtd_mode_4_wire) {
112162306a36Sopenharmony_ci		/* Add 0.2 Ohm to the final result for 3-wire RTD. */
112262306a36Sopenharmony_ci		unsigned int v = 2 * ad74115_adc_gain_tbl[range][0];
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci		if (ad74115_adc_bipolar_tbl[range])
112562306a36Sopenharmony_ci			v *= AD74115_ADC_CODE_HALF;
112662306a36Sopenharmony_ci		else
112762306a36Sopenharmony_ci			v *= AD74115_ADC_CODE_MAX;
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci		*val += v;
113062306a36Sopenharmony_ci	}
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	*val2 = d;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
113562306a36Sopenharmony_ci}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_cistatic int ad74115_get_adc_offset(struct ad74115_state *st,
113862306a36Sopenharmony_ci				  struct iio_chan_spec const *chan,
113962306a36Sopenharmony_ci				  int *val, int *val2)
114062306a36Sopenharmony_ci{
114162306a36Sopenharmony_ci	unsigned int range;
114262306a36Sopenharmony_ci	int ret;
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	ret = ad74115_get_adc_range(st, chan->channel, &range);
114562306a36Sopenharmony_ci	if (ret)
114662306a36Sopenharmony_ci		return ret;
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	if (chan->type == IIO_RESISTANCE)
114962306a36Sopenharmony_ci		return ad74115_get_adc_resistance_offset(st, range, val, val2);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	if (ad74115_adc_bipolar_tbl[range])
115262306a36Sopenharmony_ci		*val = -AD74115_ADC_CODE_HALF;
115362306a36Sopenharmony_ci	else if (range == AD74115_ADC_RANGE_2_5V_NEG)
115462306a36Sopenharmony_ci		*val = -AD74115_ADC_CODE_MAX;
115562306a36Sopenharmony_ci	else
115662306a36Sopenharmony_ci		*val = 0;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	return IIO_VAL_INT;
115962306a36Sopenharmony_ci}
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_cistatic int ad74115_read_raw(struct iio_dev *indio_dev,
116262306a36Sopenharmony_ci			    struct iio_chan_spec const *chan,
116362306a36Sopenharmony_ci			    int *val, int *val2, long info)
116462306a36Sopenharmony_ci{
116562306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
116662306a36Sopenharmony_ci	int ret;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	switch (info) {
116962306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
117062306a36Sopenharmony_ci		if (chan->output)
117162306a36Sopenharmony_ci			return ad74115_get_dac_code(st, chan->channel, val);
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci		return ad74115_get_adc_code(indio_dev, chan->channel, val);
117462306a36Sopenharmony_ci	case IIO_CHAN_INFO_PROCESSED:
117562306a36Sopenharmony_ci		ret = ad74115_get_adc_code(indio_dev, chan->channel, val);
117662306a36Sopenharmony_ci		if (ret)
117762306a36Sopenharmony_ci			return ret;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci		return ad74115_adc_code_to_resistance(*val, val, val2);
118062306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
118162306a36Sopenharmony_ci		if (chan->output)
118262306a36Sopenharmony_ci			return ad74115_get_dac_scale(st, chan, val, val2);
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci		return ad74115_get_adc_scale(st, chan, val, val2);
118562306a36Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
118662306a36Sopenharmony_ci		if (chan->output)
118762306a36Sopenharmony_ci			return ad74115_get_dac_offset(st, chan, val);
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci		return ad74115_get_adc_offset(st, chan, val, val2);
119062306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
119162306a36Sopenharmony_ci		if (chan->output)
119262306a36Sopenharmony_ci			return ad74115_get_dac_rate(st, val);
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci		return ad74115_get_adc_rate(st, chan->channel, val);
119562306a36Sopenharmony_ci	default:
119662306a36Sopenharmony_ci		return -EINVAL;
119762306a36Sopenharmony_ci	}
119862306a36Sopenharmony_ci}
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_cistatic int ad74115_write_raw(struct iio_dev *indio_dev,
120162306a36Sopenharmony_ci			     struct iio_chan_spec const *chan, int val, int val2,
120262306a36Sopenharmony_ci			     long info)
120362306a36Sopenharmony_ci{
120462306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	switch (info) {
120762306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
120862306a36Sopenharmony_ci		if (!chan->output)
120962306a36Sopenharmony_ci			return -EINVAL;
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci		return ad74115_set_dac_code(st, chan->channel, val);
121262306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
121362306a36Sopenharmony_ci		if (chan->output)
121462306a36Sopenharmony_ci			return ad74115_set_dac_rate(st, val);
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci		return ad74115_set_adc_rate(st, chan->channel, val);
121762306a36Sopenharmony_ci	default:
121862306a36Sopenharmony_ci		return -EINVAL;
121962306a36Sopenharmony_ci	}
122062306a36Sopenharmony_ci}
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_cistatic int ad74115_read_avail(struct iio_dev *indio_dev,
122362306a36Sopenharmony_ci			      struct iio_chan_spec const *chan,
122462306a36Sopenharmony_ci			      const int **vals, int *type, int *length, long info)
122562306a36Sopenharmony_ci{
122662306a36Sopenharmony_ci	switch (info) {
122762306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
122862306a36Sopenharmony_ci		if (chan->output) {
122962306a36Sopenharmony_ci			*vals = ad74115_dac_rate_tbl;
123062306a36Sopenharmony_ci			*length = ARRAY_SIZE(ad74115_dac_rate_tbl);
123162306a36Sopenharmony_ci		} else {
123262306a36Sopenharmony_ci			*vals = ad74115_adc_conv_rate_tbl;
123362306a36Sopenharmony_ci			*length = ARRAY_SIZE(ad74115_adc_conv_rate_tbl);
123462306a36Sopenharmony_ci		}
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci		*type = IIO_VAL_INT;
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci		return IIO_AVAIL_LIST;
123962306a36Sopenharmony_ci	default:
124062306a36Sopenharmony_ci		return -EINVAL;
124162306a36Sopenharmony_ci	}
124262306a36Sopenharmony_ci}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_cistatic int ad74115_reg_access(struct iio_dev *indio_dev, unsigned int reg,
124562306a36Sopenharmony_ci			      unsigned int writeval, unsigned int *readval)
124662306a36Sopenharmony_ci{
124762306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	if (readval)
125062306a36Sopenharmony_ci		return regmap_read(st->regmap, reg, readval);
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	return regmap_write(st->regmap, reg, writeval);
125362306a36Sopenharmony_ci}
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_cistatic const struct iio_info ad74115_info = {
125662306a36Sopenharmony_ci	.read_raw = ad74115_read_raw,
125762306a36Sopenharmony_ci	.write_raw = ad74115_write_raw,
125862306a36Sopenharmony_ci	.read_avail = ad74115_read_avail,
125962306a36Sopenharmony_ci	.update_scan_mode = ad74115_update_scan_mode,
126062306a36Sopenharmony_ci	.debugfs_reg_access = ad74115_reg_access,
126162306a36Sopenharmony_ci};
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci#define AD74115_DAC_CHANNEL(_type, index)				\
126462306a36Sopenharmony_ci	{								\
126562306a36Sopenharmony_ci		.type = (_type),					\
126662306a36Sopenharmony_ci		.channel = (index),					\
126762306a36Sopenharmony_ci		.indexed = 1,						\
126862306a36Sopenharmony_ci		.output = 1,						\
126962306a36Sopenharmony_ci		.scan_index = -1,					\
127062306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)		\
127162306a36Sopenharmony_ci				      | BIT(IIO_CHAN_INFO_SCALE)	\
127262306a36Sopenharmony_ci				      | BIT(IIO_CHAN_INFO_OFFSET),	\
127362306a36Sopenharmony_ci	}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci#define _AD74115_ADC_CHANNEL(_type, index, extra_mask_separate)		\
127662306a36Sopenharmony_ci	{								\
127762306a36Sopenharmony_ci		.type = (_type),					\
127862306a36Sopenharmony_ci		.channel = (index),					\
127962306a36Sopenharmony_ci		.indexed = 1,						\
128062306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)		\
128162306a36Sopenharmony_ci				      | BIT(IIO_CHAN_INFO_SAMP_FREQ)	\
128262306a36Sopenharmony_ci				      | (extra_mask_separate),		\
128362306a36Sopenharmony_ci		.info_mask_separate_available =				\
128462306a36Sopenharmony_ci					BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
128562306a36Sopenharmony_ci		.scan_index = index,					\
128662306a36Sopenharmony_ci		.scan_type = {						\
128762306a36Sopenharmony_ci			.sign = 'u',					\
128862306a36Sopenharmony_ci			.realbits = 16,					\
128962306a36Sopenharmony_ci			.storagebits = 32,				\
129062306a36Sopenharmony_ci			.shift = 8,					\
129162306a36Sopenharmony_ci			.endianness = IIO_BE,				\
129262306a36Sopenharmony_ci		},							\
129362306a36Sopenharmony_ci	}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci#define AD74115_ADC_CHANNEL(_type, index)				\
129662306a36Sopenharmony_ci	_AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE)	\
129762306a36Sopenharmony_ci					   | BIT(IIO_CHAN_INFO_OFFSET))
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_voltage_input_channels[] = {
130062306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
130162306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
130262306a36Sopenharmony_ci};
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_voltage_output_channels[] = {
130562306a36Sopenharmony_ci	AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN),
130662306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
130762306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
130862306a36Sopenharmony_ci};
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_current_input_channels[] = {
131162306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
131262306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
131362306a36Sopenharmony_ci};
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_current_output_channels[] = {
131662306a36Sopenharmony_ci	AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
131762306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
131862306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
131962306a36Sopenharmony_ci};
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
132262306a36Sopenharmony_ci	_AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1,
132362306a36Sopenharmony_ci			     BIT(IIO_CHAN_INFO_PROCESSED)),
132462306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
132562306a36Sopenharmony_ci};
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
132862306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1),
132962306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
133062306a36Sopenharmony_ci};
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
133362306a36Sopenharmony_ci	AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
133462306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
133562306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
133662306a36Sopenharmony_ci};
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_cistatic struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
133962306a36Sopenharmony_ci	AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
134062306a36Sopenharmony_ci	AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
134162306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
134262306a36Sopenharmony_ci	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
134362306a36Sopenharmony_ci};
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci#define _AD74115_CHANNELS(_channels)			\
134662306a36Sopenharmony_ci	{						\
134762306a36Sopenharmony_ci		.channels = _channels,			\
134862306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(_channels),	\
134962306a36Sopenharmony_ci	}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci#define AD74115_CHANNELS(name) \
135262306a36Sopenharmony_ci	_AD74115_CHANNELS(ad74115_ ## name ## _channels)
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_cistatic const struct ad74115_channels ad74115_channels_map[AD74115_CH_FUNC_NUM] = {
135562306a36Sopenharmony_ci	[AD74115_CH_FUNC_HIGH_IMPEDANCE] = AD74115_CHANNELS(voltage_input),
135662306a36Sopenharmony_ci	[AD74115_CH_FUNC_VOLTAGE_INPUT] = AD74115_CHANNELS(voltage_input),
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	[AD74115_CH_FUNC_VOLTAGE_OUTPUT] = AD74115_CHANNELS(voltage_output),
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	[AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER] = AD74115_CHANNELS(current_input),
136162306a36Sopenharmony_ci	[AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER] = AD74115_CHANNELS(current_input),
136262306a36Sopenharmony_ci	[AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER_HART] = AD74115_CHANNELS(current_input),
136362306a36Sopenharmony_ci	[AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART] = AD74115_CHANNELS(current_input),
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	[AD74115_CH_FUNC_CURRENT_OUTPUT] = AD74115_CHANNELS(current_output),
136662306a36Sopenharmony_ci	[AD74115_CH_FUNC_CURRENT_OUTPUT_HART] = AD74115_CHANNELS(current_output),
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	[AD74115_CH_FUNC_2_WIRE_RESISTANCE_INPUT] = AD74115_CHANNELS(2_wire_resistance_input),
136962306a36Sopenharmony_ci	[AD74115_CH_FUNC_3_4_WIRE_RESISTANCE_INPUT] = AD74115_CHANNELS(3_4_wire_resistance_input),
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	[AD74115_CH_FUNC_DIGITAL_INPUT_LOGIC] = AD74115_CHANNELS(digital_input_logic),
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	[AD74115_CH_FUNC_DIGITAL_INPUT_LOOP_POWER] = AD74115_CHANNELS(digital_input_loop),
137462306a36Sopenharmony_ci};
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci#define AD74115_GPIO_MODE_FW_PROP(i)					\
137762306a36Sopenharmony_ci{									\
137862306a36Sopenharmony_ci	.name = "adi,gpio" __stringify(i) "-mode",			\
137962306a36Sopenharmony_ci	.reg = AD74115_GPIO_CONFIG_X_REG(i),				\
138062306a36Sopenharmony_ci	.mask = AD74115_GPIO_CONFIG_SELECT_MASK,			\
138162306a36Sopenharmony_ci	.lookup_tbl = ad74115_gpio_mode_tbl,				\
138262306a36Sopenharmony_ci	.lookup_tbl_len = ARRAY_SIZE(ad74115_gpio_mode_tbl),		\
138362306a36Sopenharmony_ci}
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_gpio_mode_fw_props[] = {
138662306a36Sopenharmony_ci	AD74115_GPIO_MODE_FW_PROP(0),
138762306a36Sopenharmony_ci	AD74115_GPIO_MODE_FW_PROP(1),
138862306a36Sopenharmony_ci	AD74115_GPIO_MODE_FW_PROP(2),
138962306a36Sopenharmony_ci	AD74115_GPIO_MODE_FW_PROP(3),
139062306a36Sopenharmony_ci};
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_din_threshold_mode_fw_prop =
139362306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,digital-input-threshold-mode-fixed",
139462306a36Sopenharmony_ci			     AD74115_DIN_CONFIG2_REG, BIT(7));
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_dac_bipolar_fw_prop =
139762306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,dac-bipolar", AD74115_OUTPUT_CONFIG_REG, BIT(7));
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_ch_func_fw_prop =
140062306a36Sopenharmony_ci	AD74115_FW_PROP("adi,ch-func", AD74115_CH_FUNC_MAX,
140162306a36Sopenharmony_ci			AD74115_CH_FUNC_SETUP_REG, GENMASK(3, 0));
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_rtd_mode_fw_prop =
140462306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,4-wire-rtd", AD74115_RTD3W4W_CONFIG_REG, BIT(3));
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_din_range_fw_prop =
140762306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,digital-input-sink-range-high",
140862306a36Sopenharmony_ci			     AD74115_DIN_CONFIG1_REG, BIT(12));
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_ext2_burnout_current_fw_prop =
141162306a36Sopenharmony_ci	AD74115_FW_PROP_TBL("adi,ext2-burnout-current-nanoamp",
141262306a36Sopenharmony_ci			    ad74115_burnout_current_na_tbl,
141362306a36Sopenharmony_ci			    AD74115_BURNOUT_CONFIG_REG, GENMASK(14, 12));
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_ext1_burnout_current_fw_prop =
141662306a36Sopenharmony_ci	AD74115_FW_PROP_TBL("adi,ext1-burnout-current-nanoamp",
141762306a36Sopenharmony_ci			    ad74115_burnout_current_na_tbl,
141862306a36Sopenharmony_ci			    AD74115_BURNOUT_CONFIG_REG, GENMASK(9, 7));
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_viout_burnout_current_fw_prop =
142162306a36Sopenharmony_ci	AD74115_FW_PROP_TBL("adi,viout-burnout-current-nanoamp",
142262306a36Sopenharmony_ci			    ad74115_viout_burnout_current_na_tbl,
142362306a36Sopenharmony_ci			    AD74115_BURNOUT_CONFIG_REG, GENMASK(4, 2));
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_cistatic const struct ad74115_fw_prop ad74115_fw_props[] = {
142662306a36Sopenharmony_ci	AD74115_FW_PROP("adi,conv2-mux", 3,
142762306a36Sopenharmony_ci			AD74115_ADC_CONFIG_REG, GENMASK(3, 2)),
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL_NEG("adi,sense-agnd-buffer-low-power",
143062306a36Sopenharmony_ci				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(4)),
143162306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL_NEG("adi,lf-buffer-low-power",
143262306a36Sopenharmony_ci				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(3)),
143362306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL_NEG("adi,hf-buffer-low-power",
143462306a36Sopenharmony_ci				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(2)),
143562306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL_NEG("adi,ext2-buffer-low-power",
143662306a36Sopenharmony_ci				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(1)),
143762306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL_NEG("adi,ext1-buffer-low-power",
143862306a36Sopenharmony_ci				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(0)),
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,comparator-invert",
144162306a36Sopenharmony_ci			     AD74115_DIN_CONFIG1_REG, BIT(14)),
144262306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,digital-input-debounce-mode-counter-reset",
144362306a36Sopenharmony_ci			     AD74115_DIN_CONFIG1_REG, BIT(6)),
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,digital-input-unbuffered",
144662306a36Sopenharmony_ci			     AD74115_DIN_CONFIG2_REG, BIT(10)),
144762306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,digital-input-short-circuit-detection",
144862306a36Sopenharmony_ci			     AD74115_DIN_CONFIG2_REG, BIT(9)),
144962306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,digital-input-open-circuit-detection",
145062306a36Sopenharmony_ci			     AD74115_DIN_CONFIG2_REG, BIT(8)),
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,dac-current-limit-low",
145362306a36Sopenharmony_ci			     AD74115_OUTPUT_CONFIG_REG, BIT(0)),
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,3-wire-rtd-excitation-swap",
145662306a36Sopenharmony_ci			     AD74115_RTD3W4W_CONFIG_REG, BIT(2)),
145762306a36Sopenharmony_ci	AD74115_FW_PROP_TBL("adi,rtd-excitation-current-microamp",
145862306a36Sopenharmony_ci			    ad74115_rtd_excitation_current_ua_tbl,
145962306a36Sopenharmony_ci			    AD74115_RTD3W4W_CONFIG_REG, GENMASK(1, 0)),
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,ext2-burnout-current-polarity-sourcing",
146262306a36Sopenharmony_ci			     AD74115_BURNOUT_CONFIG_REG, BIT(11)),
146362306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,ext1-burnout-current-polarity-sourcing",
146462306a36Sopenharmony_ci			     AD74115_BURNOUT_CONFIG_REG, BIT(6)),
146562306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,viout-burnout-current-polarity-sourcing",
146662306a36Sopenharmony_ci			     AD74115_BURNOUT_CONFIG_REG, BIT(1)),
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	AD74115_FW_PROP_BOOL("adi,charge-pump",
146962306a36Sopenharmony_ci			     AD74115_CHARGE_PUMP_REG, BIT(0)),
147062306a36Sopenharmony_ci};
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_cistatic int ad74115_apply_fw_prop(struct ad74115_state *st,
147362306a36Sopenharmony_ci				 const struct ad74115_fw_prop *prop, u32 *retval)
147462306a36Sopenharmony_ci{
147562306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
147662306a36Sopenharmony_ci	u32 val = 0;
147762306a36Sopenharmony_ci	int ret;
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	if (prop->is_boolean) {
148062306a36Sopenharmony_ci		val = device_property_read_bool(dev, prop->name);
148162306a36Sopenharmony_ci	} else {
148262306a36Sopenharmony_ci		ret = device_property_read_u32(dev, prop->name, &val);
148362306a36Sopenharmony_ci		if (ret && prop->lookup_tbl)
148462306a36Sopenharmony_ci			val = prop->lookup_tbl[0];
148562306a36Sopenharmony_ci	}
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	*retval = val;
148862306a36Sopenharmony_ci
148962306a36Sopenharmony_ci	if (prop->negate)
149062306a36Sopenharmony_ci		val = !val;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	if (prop->lookup_tbl)
149362306a36Sopenharmony_ci		ret = _ad74115_find_tbl_index(prop->lookup_tbl,
149462306a36Sopenharmony_ci					      prop->lookup_tbl_len, val, &val);
149562306a36Sopenharmony_ci	else if (prop->max && val > prop->max)
149662306a36Sopenharmony_ci		ret = -EINVAL;
149762306a36Sopenharmony_ci	else
149862306a36Sopenharmony_ci		ret = 0;
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	if (ret)
150162306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
150262306a36Sopenharmony_ci				     "Invalid value %u for prop %s\n",
150362306a36Sopenharmony_ci				     val, prop->name);
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	WARN(!prop->mask, "Prop %s mask is empty\n", prop->name);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	val = (val << __ffs(prop->mask)) & prop->mask;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, prop->reg, prop->mask, val);
151062306a36Sopenharmony_ci}
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_cistatic int ad74115_setup_adc_conv2_range(struct ad74115_state *st)
151362306a36Sopenharmony_ci{
151462306a36Sopenharmony_ci	unsigned int tbl_len = ARRAY_SIZE(ad74115_adc_range_tbl);
151562306a36Sopenharmony_ci	const char *prop_name = "adi,conv2-range-microvolt";
151662306a36Sopenharmony_ci	s32 vals[2] = {
151762306a36Sopenharmony_ci		ad74115_adc_range_tbl[0][0],
151862306a36Sopenharmony_ci		ad74115_adc_range_tbl[0][1],
151962306a36Sopenharmony_ci	};
152062306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
152162306a36Sopenharmony_ci	unsigned int i;
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	device_property_read_u32_array(dev, prop_name, vals, 2);
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	for (i = 0; i < tbl_len; i++)
152662306a36Sopenharmony_ci		if (vals[0] == ad74115_adc_range_tbl[i][0] &&
152762306a36Sopenharmony_ci		    vals[1] == ad74115_adc_range_tbl[i][1])
152862306a36Sopenharmony_ci			break;
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	if (i == tbl_len)
153162306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
153262306a36Sopenharmony_ci				     "Invalid value %d, %d for prop %s\n",
153362306a36Sopenharmony_ci				     vals[0], vals[1], prop_name);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG,
153662306a36Sopenharmony_ci				  AD74115_ADC_CONFIG_CONV2_RANGE_MASK,
153762306a36Sopenharmony_ci				  FIELD_PREP(AD74115_ADC_CONFIG_CONV2_RANGE_MASK, i));
153862306a36Sopenharmony_ci}
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_cistatic int ad74115_setup_iio_channels(struct iio_dev *indio_dev)
154162306a36Sopenharmony_ci{
154262306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
154362306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
154462306a36Sopenharmony_ci	struct iio_chan_spec *channels;
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	channels = devm_kcalloc(dev, sizeof(*channels),
154762306a36Sopenharmony_ci				indio_dev->num_channels, GFP_KERNEL);
154862306a36Sopenharmony_ci	if (!channels)
154962306a36Sopenharmony_ci		return -ENOMEM;
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	indio_dev->channels = channels;
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	memcpy(channels, ad74115_channels_map[st->ch_func].channels,
155462306a36Sopenharmony_ci	       sizeof(*channels) * ad74115_channels_map[st->ch_func].num_channels);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	if (channels[0].output && channels[0].channel == AD74115_DAC_CH_MAIN &&
155762306a36Sopenharmony_ci	    channels[0].type == IIO_VOLTAGE && !st->dac_hart_slew) {
155862306a36Sopenharmony_ci		channels[0].info_mask_separate |= BIT(IIO_CHAN_INFO_SAMP_FREQ);
155962306a36Sopenharmony_ci		channels[0].info_mask_separate_available |= BIT(IIO_CHAN_INFO_SAMP_FREQ);
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	return 0;
156362306a36Sopenharmony_ci}
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_cistatic int ad74115_setup_gpio_chip(struct ad74115_state *st)
156662306a36Sopenharmony_ci{
156762306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	if (!st->gpio_valid_mask)
157062306a36Sopenharmony_ci		return 0;
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	st->gc = (struct gpio_chip) {
157362306a36Sopenharmony_ci		.owner = THIS_MODULE,
157462306a36Sopenharmony_ci		.label = AD74115_NAME,
157562306a36Sopenharmony_ci		.base = -1,
157662306a36Sopenharmony_ci		.ngpio = AD74115_GPIO_NUM,
157762306a36Sopenharmony_ci		.parent = dev,
157862306a36Sopenharmony_ci		.can_sleep = true,
157962306a36Sopenharmony_ci		.init_valid_mask = ad74115_gpio_init_valid_mask,
158062306a36Sopenharmony_ci		.get_direction = ad74115_gpio_get_direction,
158162306a36Sopenharmony_ci		.direction_input = ad74115_gpio_direction_input,
158262306a36Sopenharmony_ci		.direction_output = ad74115_gpio_direction_output,
158362306a36Sopenharmony_ci		.get = ad74115_gpio_get,
158462306a36Sopenharmony_ci		.set = ad74115_gpio_set,
158562306a36Sopenharmony_ci	};
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	return devm_gpiochip_add_data(dev, &st->gc, st);
158862306a36Sopenharmony_ci}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_cistatic int ad74115_setup_comp_gpio_chip(struct ad74115_state *st)
159162306a36Sopenharmony_ci{
159262306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
159362306a36Sopenharmony_ci	u32 val;
159462306a36Sopenharmony_ci	int ret;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74115_DIN_CONFIG1_REG, &val);
159762306a36Sopenharmony_ci	if (ret)
159862306a36Sopenharmony_ci		return ret;
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	if (!(val & AD74115_DIN_COMPARATOR_EN_MASK))
160162306a36Sopenharmony_ci		return 0;
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	st->comp_gc = (struct gpio_chip) {
160462306a36Sopenharmony_ci		.owner = THIS_MODULE,
160562306a36Sopenharmony_ci		.label = AD74115_NAME,
160662306a36Sopenharmony_ci		.base = -1,
160762306a36Sopenharmony_ci		.ngpio = 1,
160862306a36Sopenharmony_ci		.parent = dev,
160962306a36Sopenharmony_ci		.can_sleep = true,
161062306a36Sopenharmony_ci		.get_direction = ad74115_comp_gpio_get_direction,
161162306a36Sopenharmony_ci		.get = ad74115_comp_gpio_get,
161262306a36Sopenharmony_ci		.set_config = ad74115_comp_gpio_set_config,
161362306a36Sopenharmony_ci	};
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	return devm_gpiochip_add_data(dev, &st->comp_gc, st);
161662306a36Sopenharmony_ci}
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_cistatic int ad74115_setup(struct iio_dev *indio_dev)
161962306a36Sopenharmony_ci{
162062306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
162162306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
162262306a36Sopenharmony_ci	u32 val, din_range_high;
162362306a36Sopenharmony_ci	unsigned int i;
162462306a36Sopenharmony_ci	int ret;
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_ch_func_fw_prop, &val);
162762306a36Sopenharmony_ci	if (ret)
162862306a36Sopenharmony_ci		return ret;
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci	indio_dev->num_channels += ad74115_channels_map[val].num_channels;
163162306a36Sopenharmony_ci	st->ch_func = val;
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	ret = ad74115_setup_adc_conv2_range(st);
163462306a36Sopenharmony_ci	if (ret)
163562306a36Sopenharmony_ci		return ret;
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	val = device_property_read_bool(dev, "adi,dac-hart-slew");
163862306a36Sopenharmony_ci	if (val) {
163962306a36Sopenharmony_ci		st->dac_hart_slew = val;
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci		ret = regmap_update_bits(st->regmap, AD74115_OUTPUT_CONFIG_REG,
164262306a36Sopenharmony_ci					 AD74115_OUTPUT_SLEW_EN_MASK,
164362306a36Sopenharmony_ci					 FIELD_PREP(AD74115_OUTPUT_SLEW_EN_MASK,
164462306a36Sopenharmony_ci						    AD74115_SLEW_MODE_HART));
164562306a36Sopenharmony_ci		if (ret)
164662306a36Sopenharmony_ci			return ret;
164762306a36Sopenharmony_ci	}
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_din_range_fw_prop,
165062306a36Sopenharmony_ci				    &din_range_high);
165162306a36Sopenharmony_ci	if (ret)
165262306a36Sopenharmony_ci		return ret;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	ret = device_property_read_u32(dev, "adi,digital-input-sink-microamp", &val);
165562306a36Sopenharmony_ci	if (!ret) {
165662306a36Sopenharmony_ci		if (din_range_high)
165762306a36Sopenharmony_ci			val = DIV_ROUND_CLOSEST(val, AD74115_DIN_SINK_LOW_STEP);
165862306a36Sopenharmony_ci		else
165962306a36Sopenharmony_ci			val = DIV_ROUND_CLOSEST(val, AD74115_DIN_SINK_HIGH_STEP);
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci		if (val > AD74115_DIN_SINK_MAX)
166262306a36Sopenharmony_ci			val = AD74115_DIN_SINK_MAX;
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci		ret = regmap_update_bits(st->regmap, AD74115_DIN_CONFIG1_REG,
166562306a36Sopenharmony_ci					 AD74115_DIN_SINK_MASK,
166662306a36Sopenharmony_ci					 FIELD_PREP(AD74115_DIN_SINK_MASK, val));
166762306a36Sopenharmony_ci		if (ret)
166862306a36Sopenharmony_ci			return ret;
166962306a36Sopenharmony_ci	}
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_din_threshold_mode_fw_prop, &val);
167262306a36Sopenharmony_ci	if (ret)
167362306a36Sopenharmony_ci		return ret;
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	if (val == AD74115_DIN_THRESHOLD_MODE_AVDD) {
167662306a36Sopenharmony_ci		ret = regulator_get_voltage(st->avdd);
167762306a36Sopenharmony_ci		if (ret < 0)
167862306a36Sopenharmony_ci			return ret;
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_ci		st->avdd_mv = ret / 1000;
168162306a36Sopenharmony_ci	}
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci	st->din_threshold_mode = val;
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_dac_bipolar_fw_prop, &val);
168662306a36Sopenharmony_ci	if (ret)
168762306a36Sopenharmony_ci		return ret;
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	st->dac_bipolar = val;
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_rtd_mode_fw_prop, &val);
169262306a36Sopenharmony_ci	if (ret)
169362306a36Sopenharmony_ci		return ret;
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci	st->rtd_mode_4_wire = val;
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_ext2_burnout_current_fw_prop, &val);
169862306a36Sopenharmony_ci	if (ret)
169962306a36Sopenharmony_ci		return ret;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	if (val) {
170262306a36Sopenharmony_ci		ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG,
170362306a36Sopenharmony_ci					 AD74115_BURNOUT_EXT2_EN_MASK,
170462306a36Sopenharmony_ci					 FIELD_PREP(AD74115_BURNOUT_EXT2_EN_MASK, 1));
170562306a36Sopenharmony_ci		if (ret)
170662306a36Sopenharmony_ci			return ret;
170762306a36Sopenharmony_ci	}
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_ext1_burnout_current_fw_prop, &val);
171062306a36Sopenharmony_ci	if (ret)
171162306a36Sopenharmony_ci		return ret;
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	if (val) {
171462306a36Sopenharmony_ci		ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG,
171562306a36Sopenharmony_ci					 AD74115_BURNOUT_EXT1_EN_MASK,
171662306a36Sopenharmony_ci					 FIELD_PREP(AD74115_BURNOUT_EXT1_EN_MASK, 1));
171762306a36Sopenharmony_ci		if (ret)
171862306a36Sopenharmony_ci			return ret;
171962306a36Sopenharmony_ci	}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	ret = ad74115_apply_fw_prop(st, &ad74115_viout_burnout_current_fw_prop, &val);
172262306a36Sopenharmony_ci	if (ret)
172362306a36Sopenharmony_ci		return ret;
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci	if (val) {
172662306a36Sopenharmony_ci		ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG,
172762306a36Sopenharmony_ci					 AD74115_BURNOUT_VIOUT_EN_MASK,
172862306a36Sopenharmony_ci					 FIELD_PREP(AD74115_BURNOUT_VIOUT_EN_MASK, 1));
172962306a36Sopenharmony_ci		if (ret)
173062306a36Sopenharmony_ci			return ret;
173162306a36Sopenharmony_ci	}
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci	for (i = 0; i < AD74115_GPIO_NUM; i++) {
173462306a36Sopenharmony_ci		ret = ad74115_apply_fw_prop(st, &ad74115_gpio_mode_fw_props[i], &val);
173562306a36Sopenharmony_ci		if (ret)
173662306a36Sopenharmony_ci			return ret;
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ci		if (val == AD74115_GPIO_MODE_LOGIC)
173962306a36Sopenharmony_ci			st->gpio_valid_mask |= BIT(i);
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ad74115_fw_props); i++) {
174362306a36Sopenharmony_ci		ret = ad74115_apply_fw_prop(st, &ad74115_fw_props[i], &val);
174462306a36Sopenharmony_ci		if (ret)
174562306a36Sopenharmony_ci			return ret;
174662306a36Sopenharmony_ci	}
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_ci	ret = ad74115_setup_gpio_chip(st);
174962306a36Sopenharmony_ci	if (ret)
175062306a36Sopenharmony_ci		return ret;
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci	ret = ad74115_setup_comp_gpio_chip(st);
175362306a36Sopenharmony_ci	if (ret)
175462306a36Sopenharmony_ci		return ret;
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	return ad74115_setup_iio_channels(indio_dev);
175762306a36Sopenharmony_ci}
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_cistatic int ad74115_reset(struct ad74115_state *st)
176062306a36Sopenharmony_ci{
176162306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
176262306a36Sopenharmony_ci	struct gpio_desc *reset_gpio;
176362306a36Sopenharmony_ci	int ret;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
176662306a36Sopenharmony_ci	if (IS_ERR(reset_gpio))
176762306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(reset_gpio),
176862306a36Sopenharmony_ci				     "Failed to find reset GPIO\n");
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci	if (reset_gpio) {
177162306a36Sopenharmony_ci		fsleep(100);
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci		gpiod_set_value_cansleep(reset_gpio, 0);
177462306a36Sopenharmony_ci	} else {
177562306a36Sopenharmony_ci		ret = regmap_write(st->regmap, AD74115_CMD_KEY_REG,
177662306a36Sopenharmony_ci				   AD74115_CMD_KEY_RESET1);
177762306a36Sopenharmony_ci		if (ret)
177862306a36Sopenharmony_ci			return ret;
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci		ret = regmap_write(st->regmap, AD74115_CMD_KEY_REG,
178162306a36Sopenharmony_ci				   AD74115_CMD_KEY_RESET2);
178262306a36Sopenharmony_ci		if (ret)
178362306a36Sopenharmony_ci			return ret;
178462306a36Sopenharmony_ci	}
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci	fsleep(1000);
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	return 0;
178962306a36Sopenharmony_ci}
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_cistatic void ad74115_regulator_disable(void *data)
179262306a36Sopenharmony_ci{
179362306a36Sopenharmony_ci	regulator_disable(data);
179462306a36Sopenharmony_ci}
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_cistatic int ad74115_setup_trigger(struct iio_dev *indio_dev)
179762306a36Sopenharmony_ci{
179862306a36Sopenharmony_ci	struct ad74115_state *st = iio_priv(indio_dev);
179962306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
180062306a36Sopenharmony_ci	int ret;
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	st->irq = fwnode_irq_get_byname(dev_fwnode(dev), "adc_rdy");
180362306a36Sopenharmony_ci
180462306a36Sopenharmony_ci	if (st->irq == -EPROBE_DEFER)
180562306a36Sopenharmony_ci		return -EPROBE_DEFER;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	if (st->irq < 0) {
180862306a36Sopenharmony_ci		st->irq = 0;
180962306a36Sopenharmony_ci		return 0;
181062306a36Sopenharmony_ci	}
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	ret = devm_request_irq(dev, st->irq, ad74115_adc_data_interrupt,
181362306a36Sopenharmony_ci			       0, AD74115_NAME, indio_dev);
181462306a36Sopenharmony_ci	if (ret)
181562306a36Sopenharmony_ci		return ret;
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_ci	st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", AD74115_NAME,
181862306a36Sopenharmony_ci					  iio_device_id(indio_dev));
181962306a36Sopenharmony_ci	if (!st->trig)
182062306a36Sopenharmony_ci		return -ENOMEM;
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	st->trig->ops = &ad74115_trigger_ops;
182362306a36Sopenharmony_ci	iio_trigger_set_drvdata(st->trig, st);
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_ci	ret = devm_iio_trigger_register(dev, st->trig);
182662306a36Sopenharmony_ci	if (ret)
182762306a36Sopenharmony_ci		return ret;
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci	indio_dev->trig = iio_trigger_get(st->trig);
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	return 0;
183262306a36Sopenharmony_ci}
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_cistatic int ad74115_probe(struct spi_device *spi)
183562306a36Sopenharmony_ci{
183662306a36Sopenharmony_ci	static const char * const regulator_names[] = {
183762306a36Sopenharmony_ci		"avcc", "dvcc", "dovdd", "refin",
183862306a36Sopenharmony_ci	};
183962306a36Sopenharmony_ci	struct device *dev = &spi->dev;
184062306a36Sopenharmony_ci	struct ad74115_state *st;
184162306a36Sopenharmony_ci	struct iio_dev *indio_dev;
184262306a36Sopenharmony_ci	int ret;
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
184562306a36Sopenharmony_ci	if (!indio_dev)
184662306a36Sopenharmony_ci		return -ENOMEM;
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci	st = iio_priv(indio_dev);
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	st->spi = spi;
185162306a36Sopenharmony_ci	mutex_init(&st->lock);
185262306a36Sopenharmony_ci	init_completion(&st->adc_data_completion);
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci	indio_dev->name = AD74115_NAME;
185562306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
185662306a36Sopenharmony_ci	indio_dev->info = &ad74115_info;
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	st->avdd = devm_regulator_get(dev, "avdd");
185962306a36Sopenharmony_ci	if (IS_ERR(st->avdd))
186062306a36Sopenharmony_ci		return PTR_ERR(st->avdd);
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	ret = regulator_enable(st->avdd);
186362306a36Sopenharmony_ci	if (ret) {
186462306a36Sopenharmony_ci		dev_err(dev, "Failed to enable avdd regulator\n");
186562306a36Sopenharmony_ci		return ret;
186662306a36Sopenharmony_ci	}
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	ret = devm_add_action_or_reset(dev, ad74115_regulator_disable, st->avdd);
186962306a36Sopenharmony_ci	if (ret)
187062306a36Sopenharmony_ci		return ret;
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci	ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
187362306a36Sopenharmony_ci					     regulator_names);
187462306a36Sopenharmony_ci	if (ret)
187562306a36Sopenharmony_ci		return ret;
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	st->regmap = devm_regmap_init(dev, NULL, st, &ad74115_regmap_config);
187862306a36Sopenharmony_ci	if (IS_ERR(st->regmap))
187962306a36Sopenharmony_ci		return PTR_ERR(st->regmap);
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	ret = ad74115_reset(st);
188262306a36Sopenharmony_ci	if (ret)
188362306a36Sopenharmony_ci		return ret;
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci	ret = ad74115_setup(indio_dev);
188662306a36Sopenharmony_ci	if (ret)
188762306a36Sopenharmony_ci		return ret;
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	ret = ad74115_setup_trigger(indio_dev);
189062306a36Sopenharmony_ci	if (ret)
189162306a36Sopenharmony_ci		return ret;
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
189462306a36Sopenharmony_ci					      ad74115_trigger_handler,
189562306a36Sopenharmony_ci					      &ad74115_buffer_ops);
189662306a36Sopenharmony_ci	if (ret)
189762306a36Sopenharmony_ci		return ret;
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	return devm_iio_device_register(dev, indio_dev);
190062306a36Sopenharmony_ci}
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_cistatic int ad74115_unregister_driver(struct spi_driver *spi)
190362306a36Sopenharmony_ci{
190462306a36Sopenharmony_ci	spi_unregister_driver(spi);
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	return 0;
190762306a36Sopenharmony_ci}
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_cistatic int __init ad74115_register_driver(struct spi_driver *spi)
191062306a36Sopenharmony_ci{
191162306a36Sopenharmony_ci	crc8_populate_msb(ad74115_crc8_table, AD74115_CRC_POLYNOMIAL);
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	return spi_register_driver(spi);
191462306a36Sopenharmony_ci}
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_cistatic const struct spi_device_id ad74115_spi_id[] = {
191762306a36Sopenharmony_ci	{ "ad74115h" },
191862306a36Sopenharmony_ci	{ }
191962306a36Sopenharmony_ci};
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad74115_spi_id);
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_cistatic const struct of_device_id ad74115_dt_id[] = {
192462306a36Sopenharmony_ci	{ .compatible = "adi,ad74115h" },
192562306a36Sopenharmony_ci	{ }
192662306a36Sopenharmony_ci};
192762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad74115_dt_id);
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_cistatic struct spi_driver ad74115_driver = {
193062306a36Sopenharmony_ci	.driver = {
193162306a36Sopenharmony_ci		   .name = "ad74115",
193262306a36Sopenharmony_ci		   .of_match_table = ad74115_dt_id,
193362306a36Sopenharmony_ci	},
193462306a36Sopenharmony_ci	.probe = ad74115_probe,
193562306a36Sopenharmony_ci	.id_table = ad74115_spi_id,
193662306a36Sopenharmony_ci};
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_cimodule_driver(ad74115_driver,
193962306a36Sopenharmony_ci	      ad74115_register_driver, ad74115_unregister_driver);
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ciMODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
194262306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD74115 ADDAC");
194362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1944