162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2021 Analog Devices, Inc.
462306a36Sopenharmony_ci * Author: Cosmin Tanislav <cosmin.tanislav@analog.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <asm/unaligned.h>
862306a36Sopenharmony_ci#include <linux/bitfield.h>
962306a36Sopenharmony_ci#include <linux/crc8.h>
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/err.h>
1262306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1362306a36Sopenharmony_ci#include <linux/iio/buffer.h>
1462306a36Sopenharmony_ci#include <linux/iio/iio.h>
1562306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
1662306a36Sopenharmony_ci#include <linux/iio/trigger.h>
1762306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h>
1862306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h>
1962306a36Sopenharmony_ci#include <linux/interrupt.h>
2062306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
2162306a36Sopenharmony_ci#include <linux/property.h>
2262306a36Sopenharmony_ci#include <linux/regmap.h>
2362306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
2462306a36Sopenharmony_ci#include <linux/spi/spi.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include <dt-bindings/iio/addac/adi,ad74413r.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define AD74413R_CRC_POLYNOMIAL	0x7
2962306a36Sopenharmony_ciDECLARE_CRC8_TABLE(ad74413r_crc8_table);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define AD74413R_CHANNEL_MAX	4
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define AD74413R_FRAME_SIZE	4
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct ad74413r_chip_info {
3662306a36Sopenharmony_ci	const char	*name;
3762306a36Sopenharmony_ci	bool		hart_support;
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct ad74413r_channel_config {
4162306a36Sopenharmony_ci	u32		func;
4262306a36Sopenharmony_ci	u32		drive_strength;
4362306a36Sopenharmony_ci	bool		gpo_comparator;
4462306a36Sopenharmony_ci	bool		initialized;
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistruct ad74413r_channels {
4862306a36Sopenharmony_ci	struct iio_chan_spec	*channels;
4962306a36Sopenharmony_ci	unsigned int		num_channels;
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistruct ad74413r_state {
5362306a36Sopenharmony_ci	struct ad74413r_channel_config	channel_configs[AD74413R_CHANNEL_MAX];
5462306a36Sopenharmony_ci	unsigned int			gpo_gpio_offsets[AD74413R_CHANNEL_MAX];
5562306a36Sopenharmony_ci	unsigned int			comp_gpio_offsets[AD74413R_CHANNEL_MAX];
5662306a36Sopenharmony_ci	struct gpio_chip		gpo_gpiochip;
5762306a36Sopenharmony_ci	struct gpio_chip		comp_gpiochip;
5862306a36Sopenharmony_ci	struct completion		adc_data_completion;
5962306a36Sopenharmony_ci	unsigned int			num_gpo_gpios;
6062306a36Sopenharmony_ci	unsigned int			num_comparator_gpios;
6162306a36Sopenharmony_ci	u32				sense_resistor_ohms;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	/*
6462306a36Sopenharmony_ci	 * Synchronize consecutive operations when doing a one-shot
6562306a36Sopenharmony_ci	 * conversion and when updating the ADC samples SPI message.
6662306a36Sopenharmony_ci	 */
6762306a36Sopenharmony_ci	struct mutex			lock;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	const struct ad74413r_chip_info	*chip_info;
7062306a36Sopenharmony_ci	struct spi_device		*spi;
7162306a36Sopenharmony_ci	struct regulator		*refin_reg;
7262306a36Sopenharmony_ci	struct regmap			*regmap;
7362306a36Sopenharmony_ci	struct device			*dev;
7462306a36Sopenharmony_ci	struct iio_trigger		*trig;
7562306a36Sopenharmony_ci	struct gpio_desc		*reset_gpio;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	size_t			adc_active_channels;
7862306a36Sopenharmony_ci	struct spi_message	adc_samples_msg;
7962306a36Sopenharmony_ci	struct spi_transfer	adc_samples_xfer[AD74413R_CHANNEL_MAX + 1];
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	/*
8262306a36Sopenharmony_ci	 * DMA (thus cache coherency maintenance) may require the
8362306a36Sopenharmony_ci	 * transfer buffers to live in their own cache lines.
8462306a36Sopenharmony_ci	 */
8562306a36Sopenharmony_ci	struct {
8662306a36Sopenharmony_ci		u8 rx_buf[AD74413R_FRAME_SIZE * AD74413R_CHANNEL_MAX];
8762306a36Sopenharmony_ci		s64 timestamp;
8862306a36Sopenharmony_ci	} adc_samples_buf __aligned(IIO_DMA_MINALIGN);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	u8	adc_samples_tx_buf[AD74413R_FRAME_SIZE * AD74413R_CHANNEL_MAX];
9162306a36Sopenharmony_ci	u8	reg_tx_buf[AD74413R_FRAME_SIZE];
9262306a36Sopenharmony_ci	u8	reg_rx_buf[AD74413R_FRAME_SIZE];
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#define AD74413R_REG_NOP		0x00
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define AD74413R_REG_CH_FUNC_SETUP_X(x)	(0x01 + (x))
9862306a36Sopenharmony_ci#define AD74413R_CH_FUNC_SETUP_MASK	GENMASK(3, 0)
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define AD74413R_REG_ADC_CONFIG_X(x)		(0x05 + (x))
10162306a36Sopenharmony_ci#define AD74413R_ADC_CONFIG_RANGE_MASK		GENMASK(7, 5)
10262306a36Sopenharmony_ci#define AD74413R_ADC_CONFIG_REJECTION_MASK	GENMASK(4, 3)
10362306a36Sopenharmony_ci#define AD74413R_ADC_CONFIG_CH_200K_TO_GND	BIT(2)
10462306a36Sopenharmony_ci#define AD74413R_ADC_RANGE_10V			0b000
10562306a36Sopenharmony_ci#define AD74413R_ADC_RANGE_2P5V_EXT_POW		0b001
10662306a36Sopenharmony_ci#define AD74413R_ADC_RANGE_2P5V_INT_POW		0b010
10762306a36Sopenharmony_ci#define AD74413R_ADC_RANGE_5V_BI_DIR		0b011
10862306a36Sopenharmony_ci#define AD74413R_ADC_REJECTION_50_60		0b00
10962306a36Sopenharmony_ci#define AD74413R_ADC_REJECTION_NONE		0b01
11062306a36Sopenharmony_ci#define AD74413R_ADC_REJECTION_50_60_HART	0b10
11162306a36Sopenharmony_ci#define AD74413R_ADC_REJECTION_HART		0b11
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#define AD74413R_REG_DIN_CONFIG_X(x)	(0x09 + (x))
11462306a36Sopenharmony_ci#define AD74413R_DIN_DEBOUNCE_MASK	GENMASK(4, 0)
11562306a36Sopenharmony_ci#define AD74413R_DIN_DEBOUNCE_LEN	BIT(5)
11662306a36Sopenharmony_ci#define AD74413R_DIN_SINK_MASK		GENMASK(9, 6)
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci#define AD74413R_REG_DAC_CODE_X(x)	(0x16 + (x))
11962306a36Sopenharmony_ci#define AD74413R_DAC_CODE_MAX		GENMASK(12, 0)
12062306a36Sopenharmony_ci#define AD74413R_DAC_VOLTAGE_MAX	11000
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#define AD74413R_REG_GPO_PAR_DATA		0x0d
12362306a36Sopenharmony_ci#define AD74413R_REG_GPO_CONFIG_X(x)		(0x0e + (x))
12462306a36Sopenharmony_ci#define AD74413R_GPO_CONFIG_DATA_MASK	BIT(3)
12562306a36Sopenharmony_ci#define AD74413R_GPO_CONFIG_SELECT_MASK		GENMASK(2, 0)
12662306a36Sopenharmony_ci#define AD74413R_GPO_CONFIG_100K_PULL_DOWN	0b000
12762306a36Sopenharmony_ci#define AD74413R_GPO_CONFIG_LOGIC		0b001
12862306a36Sopenharmony_ci#define AD74413R_GPO_CONFIG_LOGIC_PARALLEL	0b010
12962306a36Sopenharmony_ci#define AD74413R_GPO_CONFIG_COMPARATOR		0b011
13062306a36Sopenharmony_ci#define AD74413R_GPO_CONFIG_HIGH_IMPEDANCE	0b100
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci#define AD74413R_REG_ADC_CONV_CTRL	0x23
13362306a36Sopenharmony_ci#define AD74413R_CONV_SEQ_MASK		GENMASK(9, 8)
13462306a36Sopenharmony_ci#define AD74413R_CONV_SEQ_ON		0b00
13562306a36Sopenharmony_ci#define AD74413R_CONV_SEQ_SINGLE	0b01
13662306a36Sopenharmony_ci#define AD74413R_CONV_SEQ_CONTINUOUS	0b10
13762306a36Sopenharmony_ci#define AD74413R_CONV_SEQ_OFF		0b11
13862306a36Sopenharmony_ci#define AD74413R_CH_EN_MASK(x)		BIT(x)
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci#define AD74413R_REG_DIN_COMP_OUT		0x25
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#define AD74413R_REG_ADC_RESULT_X(x)	(0x26 + (x))
14362306a36Sopenharmony_ci#define AD74413R_ADC_RESULT_MAX		GENMASK(15, 0)
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci#define AD74413R_REG_READ_SELECT	0x41
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci#define AD74413R_REG_CMD_KEY		0x44
14862306a36Sopenharmony_ci#define AD74413R_CMD_KEY_LDAC		0x953a
14962306a36Sopenharmony_ci#define AD74413R_CMD_KEY_RESET1		0x15fa
15062306a36Sopenharmony_ci#define AD74413R_CMD_KEY_RESET2		0xaf51
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic const int ad74413r_adc_sampling_rates[] = {
15362306a36Sopenharmony_ci	20, 4800,
15462306a36Sopenharmony_ci};
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic const int ad74413r_adc_sampling_rates_hart[] = {
15762306a36Sopenharmony_ci	10, 20, 1200, 4800,
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic int ad74413r_crc(u8 *buf)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	return crc8(ad74413r_crc8_table, buf, 3, 0);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic void ad74413r_format_reg_write(u8 reg, u16 val, u8 *buf)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	buf[0] = reg;
16862306a36Sopenharmony_ci	put_unaligned_be16(val, &buf[1]);
16962306a36Sopenharmony_ci	buf[3] = ad74413r_crc(buf);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic int ad74413r_reg_write(void *context, unsigned int reg, unsigned int val)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	struct ad74413r_state *st = context;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	ad74413r_format_reg_write(reg, val, st->reg_tx_buf);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	return spi_write(st->spi, st->reg_tx_buf, AD74413R_FRAME_SIZE);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic int ad74413r_crc_check(struct ad74413r_state *st, u8 *buf)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	u8 expected_crc = ad74413r_crc(buf);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	if (buf[3] != expected_crc) {
18662306a36Sopenharmony_ci		dev_err(st->dev, "Bad CRC %02x for %02x%02x%02x\n",
18762306a36Sopenharmony_ci			buf[3], buf[0], buf[1], buf[2]);
18862306a36Sopenharmony_ci		return -EINVAL;
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	return 0;
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic int ad74413r_reg_read(void *context, unsigned int reg, unsigned int *val)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	struct ad74413r_state *st = context;
19762306a36Sopenharmony_ci	struct spi_transfer reg_read_xfer[] = {
19862306a36Sopenharmony_ci		{
19962306a36Sopenharmony_ci			.tx_buf = st->reg_tx_buf,
20062306a36Sopenharmony_ci			.len = AD74413R_FRAME_SIZE,
20162306a36Sopenharmony_ci			.cs_change = 1,
20262306a36Sopenharmony_ci		},
20362306a36Sopenharmony_ci		{
20462306a36Sopenharmony_ci			.rx_buf = st->reg_rx_buf,
20562306a36Sopenharmony_ci			.len = AD74413R_FRAME_SIZE,
20662306a36Sopenharmony_ci		},
20762306a36Sopenharmony_ci	};
20862306a36Sopenharmony_ci	int ret;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	ad74413r_format_reg_write(AD74413R_REG_READ_SELECT, reg,
21162306a36Sopenharmony_ci				  st->reg_tx_buf);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	ret = spi_sync_transfer(st->spi, reg_read_xfer,
21462306a36Sopenharmony_ci				ARRAY_SIZE(reg_read_xfer));
21562306a36Sopenharmony_ci	if (ret)
21662306a36Sopenharmony_ci		return ret;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	ret = ad74413r_crc_check(st, st->reg_rx_buf);
21962306a36Sopenharmony_ci	if (ret)
22062306a36Sopenharmony_ci		return ret;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	*val = get_unaligned_be16(&st->reg_rx_buf[1]);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	return 0;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic const struct regmap_config ad74413r_regmap_config = {
22862306a36Sopenharmony_ci	.reg_bits = 8,
22962306a36Sopenharmony_ci	.val_bits = 16,
23062306a36Sopenharmony_ci	.reg_read = ad74413r_reg_read,
23162306a36Sopenharmony_ci	.reg_write = ad74413r_reg_write,
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic int ad74413r_set_gpo_config(struct ad74413r_state *st,
23562306a36Sopenharmony_ci				   unsigned int offset, u8 mode)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74413R_REG_GPO_CONFIG_X(offset),
23862306a36Sopenharmony_ci				  AD74413R_GPO_CONFIG_SELECT_MASK, mode);
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic const unsigned int ad74413r_debounce_map[AD74413R_DIN_DEBOUNCE_LEN] = {
24262306a36Sopenharmony_ci	0,     13,    18,    24,    32,    42,    56,    75,
24362306a36Sopenharmony_ci	100,   130,   180,   240,   320,   420,   560,   750,
24462306a36Sopenharmony_ci	1000,  1300,  1800,  2400,  3200,  4200,  5600,  7500,
24562306a36Sopenharmony_ci	10000, 13000, 18000, 24000, 32000, 42000, 56000, 75000,
24662306a36Sopenharmony_ci};
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic int ad74413r_set_comp_debounce(struct ad74413r_state *st,
24962306a36Sopenharmony_ci				      unsigned int offset,
25062306a36Sopenharmony_ci				      unsigned int debounce)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	unsigned int val = AD74413R_DIN_DEBOUNCE_LEN - 1;
25362306a36Sopenharmony_ci	unsigned int i;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	for (i = 0; i < AD74413R_DIN_DEBOUNCE_LEN; i++)
25662306a36Sopenharmony_ci		if (debounce <= ad74413r_debounce_map[i]) {
25762306a36Sopenharmony_ci			val = i;
25862306a36Sopenharmony_ci			break;
25962306a36Sopenharmony_ci		}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	return regmap_update_bits(st->regmap,
26262306a36Sopenharmony_ci				  AD74413R_REG_DIN_CONFIG_X(offset),
26362306a36Sopenharmony_ci				  AD74413R_DIN_DEBOUNCE_MASK,
26462306a36Sopenharmony_ci				  val);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic int ad74413r_set_comp_drive_strength(struct ad74413r_state *st,
26862306a36Sopenharmony_ci					    unsigned int offset,
26962306a36Sopenharmony_ci					    unsigned int strength)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	strength = min(strength, 1800U);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74413R_REG_DIN_CONFIG_X(offset),
27462306a36Sopenharmony_ci				  AD74413R_DIN_SINK_MASK,
27562306a36Sopenharmony_ci				  FIELD_PREP(AD74413R_DIN_SINK_MASK, strength / 120));
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistatic void ad74413r_gpio_set(struct gpio_chip *chip,
28062306a36Sopenharmony_ci			      unsigned int offset, int val)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct ad74413r_state *st = gpiochip_get_data(chip);
28362306a36Sopenharmony_ci	unsigned int real_offset = st->gpo_gpio_offsets[offset];
28462306a36Sopenharmony_ci	int ret;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	ret = ad74413r_set_gpo_config(st, real_offset,
28762306a36Sopenharmony_ci				      AD74413R_GPO_CONFIG_LOGIC);
28862306a36Sopenharmony_ci	if (ret)
28962306a36Sopenharmony_ci		return;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	regmap_update_bits(st->regmap, AD74413R_REG_GPO_CONFIG_X(real_offset),
29262306a36Sopenharmony_ci			   AD74413R_GPO_CONFIG_DATA_MASK,
29362306a36Sopenharmony_ci			   val ? AD74413R_GPO_CONFIG_DATA_MASK : 0);
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic void ad74413r_gpio_set_multiple(struct gpio_chip *chip,
29762306a36Sopenharmony_ci				       unsigned long *mask,
29862306a36Sopenharmony_ci				       unsigned long *bits)
29962306a36Sopenharmony_ci{
30062306a36Sopenharmony_ci	struct ad74413r_state *st = gpiochip_get_data(chip);
30162306a36Sopenharmony_ci	unsigned long real_mask = 0;
30262306a36Sopenharmony_ci	unsigned long real_bits = 0;
30362306a36Sopenharmony_ci	unsigned int offset;
30462306a36Sopenharmony_ci	int ret;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	for_each_set_bit(offset, mask, chip->ngpio) {
30762306a36Sopenharmony_ci		unsigned int real_offset = st->gpo_gpio_offsets[offset];
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci		ret = ad74413r_set_gpo_config(st, real_offset,
31062306a36Sopenharmony_ci			AD74413R_GPO_CONFIG_LOGIC_PARALLEL);
31162306a36Sopenharmony_ci		if (ret)
31262306a36Sopenharmony_ci			return;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci		real_mask |= BIT(real_offset);
31562306a36Sopenharmony_ci		if (*bits & offset)
31662306a36Sopenharmony_ci			real_bits |= BIT(real_offset);
31762306a36Sopenharmony_ci	}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	regmap_update_bits(st->regmap, AD74413R_REG_GPO_PAR_DATA,
32062306a36Sopenharmony_ci			   real_mask, real_bits);
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_cistatic int ad74413r_gpio_get(struct gpio_chip *chip, unsigned int offset)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	struct ad74413r_state *st = gpiochip_get_data(chip);
32662306a36Sopenharmony_ci	unsigned int real_offset = st->comp_gpio_offsets[offset];
32762306a36Sopenharmony_ci	unsigned int status;
32862306a36Sopenharmony_ci	int ret;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74413R_REG_DIN_COMP_OUT, &status);
33162306a36Sopenharmony_ci	if (ret)
33262306a36Sopenharmony_ci		return ret;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	status &= BIT(real_offset);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	return status ? 1 : 0;
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistatic int ad74413r_gpio_get_multiple(struct gpio_chip *chip,
34062306a36Sopenharmony_ci				      unsigned long *mask,
34162306a36Sopenharmony_ci				      unsigned long *bits)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	struct ad74413r_state *st = gpiochip_get_data(chip);
34462306a36Sopenharmony_ci	unsigned int offset;
34562306a36Sopenharmony_ci	unsigned int val;
34662306a36Sopenharmony_ci	int ret;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74413R_REG_DIN_COMP_OUT, &val);
34962306a36Sopenharmony_ci	if (ret)
35062306a36Sopenharmony_ci		return ret;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	for_each_set_bit(offset, mask, chip->ngpio) {
35362306a36Sopenharmony_ci		unsigned int real_offset = st->comp_gpio_offsets[offset];
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		__assign_bit(offset, bits, val & BIT(real_offset));
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	return ret;
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_cistatic int ad74413r_gpio_get_gpo_direction(struct gpio_chip *chip,
36262306a36Sopenharmony_ci					   unsigned int offset)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	return GPIO_LINE_DIRECTION_OUT;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic int ad74413r_gpio_get_comp_direction(struct gpio_chip *chip,
36862306a36Sopenharmony_ci					    unsigned int offset)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	return GPIO_LINE_DIRECTION_IN;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int ad74413r_gpio_set_gpo_config(struct gpio_chip *chip,
37462306a36Sopenharmony_ci					unsigned int offset,
37562306a36Sopenharmony_ci					unsigned long config)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	struct ad74413r_state *st = gpiochip_get_data(chip);
37862306a36Sopenharmony_ci	unsigned int real_offset = st->gpo_gpio_offsets[offset];
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	switch (pinconf_to_config_param(config)) {
38162306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_DOWN:
38262306a36Sopenharmony_ci		return ad74413r_set_gpo_config(st, real_offset,
38362306a36Sopenharmony_ci			AD74413R_GPO_CONFIG_100K_PULL_DOWN);
38462306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
38562306a36Sopenharmony_ci		return ad74413r_set_gpo_config(st, real_offset,
38662306a36Sopenharmony_ci			AD74413R_GPO_CONFIG_HIGH_IMPEDANCE);
38762306a36Sopenharmony_ci	default:
38862306a36Sopenharmony_ci		return -ENOTSUPP;
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cistatic int ad74413r_gpio_set_comp_config(struct gpio_chip *chip,
39362306a36Sopenharmony_ci					 unsigned int offset,
39462306a36Sopenharmony_ci					 unsigned long config)
39562306a36Sopenharmony_ci{
39662306a36Sopenharmony_ci	struct ad74413r_state *st = gpiochip_get_data(chip);
39762306a36Sopenharmony_ci	unsigned int real_offset = st->comp_gpio_offsets[offset];
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	switch (pinconf_to_config_param(config)) {
40062306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_DEBOUNCE:
40162306a36Sopenharmony_ci		return ad74413r_set_comp_debounce(st, real_offset,
40262306a36Sopenharmony_ci			pinconf_to_config_argument(config));
40362306a36Sopenharmony_ci	default:
40462306a36Sopenharmony_ci		return -ENOTSUPP;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_cistatic int ad74413r_reset(struct ad74413r_state *st)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	int ret;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	if (st->reset_gpio) {
41362306a36Sopenharmony_ci		gpiod_set_value_cansleep(st->reset_gpio, 1);
41462306a36Sopenharmony_ci		fsleep(50);
41562306a36Sopenharmony_ci		gpiod_set_value_cansleep(st->reset_gpio, 0);
41662306a36Sopenharmony_ci		return 0;
41762306a36Sopenharmony_ci	}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	ret = regmap_write(st->regmap, AD74413R_REG_CMD_KEY,
42062306a36Sopenharmony_ci			   AD74413R_CMD_KEY_RESET1);
42162306a36Sopenharmony_ci	if (ret)
42262306a36Sopenharmony_ci		return ret;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	return regmap_write(st->regmap, AD74413R_REG_CMD_KEY,
42562306a36Sopenharmony_ci			    AD74413R_CMD_KEY_RESET2);
42662306a36Sopenharmony_ci}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_cistatic int ad74413r_set_channel_dac_code(struct ad74413r_state *st,
42962306a36Sopenharmony_ci					 unsigned int channel, int dac_code)
43062306a36Sopenharmony_ci{
43162306a36Sopenharmony_ci	struct reg_sequence reg_seq[2] = {
43262306a36Sopenharmony_ci		{ AD74413R_REG_DAC_CODE_X(channel), dac_code },
43362306a36Sopenharmony_ci		{ AD74413R_REG_CMD_KEY, AD74413R_CMD_KEY_LDAC },
43462306a36Sopenharmony_ci	};
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	return regmap_multi_reg_write(st->regmap, reg_seq, 2);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic int ad74413r_set_channel_function(struct ad74413r_state *st,
44062306a36Sopenharmony_ci					 unsigned int channel, u8 func)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	int ret;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap,
44562306a36Sopenharmony_ci				  AD74413R_REG_CH_FUNC_SETUP_X(channel),
44662306a36Sopenharmony_ci				  AD74413R_CH_FUNC_SETUP_MASK, func);
44762306a36Sopenharmony_ci	if (ret)
44862306a36Sopenharmony_ci		return ret;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	if (func == CH_FUNC_CURRENT_INPUT_LOOP_POWER)
45162306a36Sopenharmony_ci		ret = regmap_set_bits(st->regmap,
45262306a36Sopenharmony_ci				      AD74413R_REG_ADC_CONFIG_X(channel),
45362306a36Sopenharmony_ci				      AD74413R_ADC_CONFIG_CH_200K_TO_GND);
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	return ret;
45662306a36Sopenharmony_ci}
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_cistatic int ad74413r_set_adc_conv_seq(struct ad74413r_state *st,
45962306a36Sopenharmony_ci				     unsigned int status)
46062306a36Sopenharmony_ci{
46162306a36Sopenharmony_ci	int ret;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	/*
46462306a36Sopenharmony_ci	 * These bits do not clear when a conversion completes.
46562306a36Sopenharmony_ci	 * To enable a subsequent conversion, repeat the write.
46662306a36Sopenharmony_ci	 */
46762306a36Sopenharmony_ci	ret = regmap_write_bits(st->regmap, AD74413R_REG_ADC_CONV_CTRL,
46862306a36Sopenharmony_ci				AD74413R_CONV_SEQ_MASK,
46962306a36Sopenharmony_ci				FIELD_PREP(AD74413R_CONV_SEQ_MASK, status));
47062306a36Sopenharmony_ci	if (ret)
47162306a36Sopenharmony_ci		return ret;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	/*
47462306a36Sopenharmony_ci	 * Wait 100us before starting conversions.
47562306a36Sopenharmony_ci	 */
47662306a36Sopenharmony_ci	usleep_range(100, 120);
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	return 0;
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistatic int ad74413r_set_adc_channel_enable(struct ad74413r_state *st,
48262306a36Sopenharmony_ci					   unsigned int channel,
48362306a36Sopenharmony_ci					   bool status)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD74413R_REG_ADC_CONV_CTRL,
48662306a36Sopenharmony_ci				  AD74413R_CH_EN_MASK(channel),
48762306a36Sopenharmony_ci				  status ? AD74413R_CH_EN_MASK(channel) : 0);
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_cistatic int ad74413r_get_adc_range(struct ad74413r_state *st,
49162306a36Sopenharmony_ci				  unsigned int channel,
49262306a36Sopenharmony_ci				  unsigned int *val)
49362306a36Sopenharmony_ci{
49462306a36Sopenharmony_ci	int ret;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74413R_REG_ADC_CONFIG_X(channel), val);
49762306a36Sopenharmony_ci	if (ret)
49862306a36Sopenharmony_ci		return ret;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	*val = FIELD_GET(AD74413R_ADC_CONFIG_RANGE_MASK, *val);
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	return 0;
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic int ad74413r_get_adc_rejection(struct ad74413r_state *st,
50662306a36Sopenharmony_ci				      unsigned int channel,
50762306a36Sopenharmony_ci				      unsigned int *val)
50862306a36Sopenharmony_ci{
50962306a36Sopenharmony_ci	int ret;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74413R_REG_ADC_CONFIG_X(channel), val);
51262306a36Sopenharmony_ci	if (ret)
51362306a36Sopenharmony_ci		return ret;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	*val = FIELD_GET(AD74413R_ADC_CONFIG_REJECTION_MASK, *val);
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	return 0;
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_cistatic int ad74413r_set_adc_rejection(struct ad74413r_state *st,
52162306a36Sopenharmony_ci				      unsigned int channel,
52262306a36Sopenharmony_ci				      unsigned int val)
52362306a36Sopenharmony_ci{
52462306a36Sopenharmony_ci	return regmap_update_bits(st->regmap,
52562306a36Sopenharmony_ci				  AD74413R_REG_ADC_CONFIG_X(channel),
52662306a36Sopenharmony_ci				  AD74413R_ADC_CONFIG_REJECTION_MASK,
52762306a36Sopenharmony_ci				  FIELD_PREP(AD74413R_ADC_CONFIG_REJECTION_MASK,
52862306a36Sopenharmony_ci					     val));
52962306a36Sopenharmony_ci}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_cistatic int ad74413r_rejection_to_rate(struct ad74413r_state *st,
53262306a36Sopenharmony_ci				      unsigned int rej, int *val)
53362306a36Sopenharmony_ci{
53462306a36Sopenharmony_ci	switch (rej) {
53562306a36Sopenharmony_ci	case AD74413R_ADC_REJECTION_50_60:
53662306a36Sopenharmony_ci		*val = 20;
53762306a36Sopenharmony_ci		return 0;
53862306a36Sopenharmony_ci	case AD74413R_ADC_REJECTION_NONE:
53962306a36Sopenharmony_ci		*val = 4800;
54062306a36Sopenharmony_ci		return 0;
54162306a36Sopenharmony_ci	case AD74413R_ADC_REJECTION_50_60_HART:
54262306a36Sopenharmony_ci		*val = 10;
54362306a36Sopenharmony_ci		return 0;
54462306a36Sopenharmony_ci	case AD74413R_ADC_REJECTION_HART:
54562306a36Sopenharmony_ci		*val = 1200;
54662306a36Sopenharmony_ci		return 0;
54762306a36Sopenharmony_ci	default:
54862306a36Sopenharmony_ci		dev_err(st->dev, "ADC rejection invalid\n");
54962306a36Sopenharmony_ci		return -EINVAL;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_cistatic int ad74413r_rate_to_rejection(struct ad74413r_state *st,
55462306a36Sopenharmony_ci				      int rate, unsigned int *val)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	switch (rate) {
55762306a36Sopenharmony_ci	case 20:
55862306a36Sopenharmony_ci		*val = AD74413R_ADC_REJECTION_50_60;
55962306a36Sopenharmony_ci		return 0;
56062306a36Sopenharmony_ci	case 4800:
56162306a36Sopenharmony_ci		*val = AD74413R_ADC_REJECTION_NONE;
56262306a36Sopenharmony_ci		return 0;
56362306a36Sopenharmony_ci	case 10:
56462306a36Sopenharmony_ci		*val = AD74413R_ADC_REJECTION_50_60_HART;
56562306a36Sopenharmony_ci		return 0;
56662306a36Sopenharmony_ci	case 1200:
56762306a36Sopenharmony_ci		*val = AD74413R_ADC_REJECTION_HART;
56862306a36Sopenharmony_ci		return 0;
56962306a36Sopenharmony_ci	default:
57062306a36Sopenharmony_ci		dev_err(st->dev, "ADC rate invalid\n");
57162306a36Sopenharmony_ci		return -EINVAL;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_cistatic int ad74413r_range_to_voltage_range(struct ad74413r_state *st,
57662306a36Sopenharmony_ci					   unsigned int range, int *val)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	switch (range) {
57962306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_10V:
58062306a36Sopenharmony_ci		*val = 10000;
58162306a36Sopenharmony_ci		return 0;
58262306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_2P5V_EXT_POW:
58362306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_2P5V_INT_POW:
58462306a36Sopenharmony_ci		*val = 2500;
58562306a36Sopenharmony_ci		return 0;
58662306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_5V_BI_DIR:
58762306a36Sopenharmony_ci		*val = 5000;
58862306a36Sopenharmony_ci		return 0;
58962306a36Sopenharmony_ci	default:
59062306a36Sopenharmony_ci		dev_err(st->dev, "ADC range invalid\n");
59162306a36Sopenharmony_ci		return -EINVAL;
59262306a36Sopenharmony_ci	}
59362306a36Sopenharmony_ci}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cistatic int ad74413r_range_to_voltage_offset(struct ad74413r_state *st,
59662306a36Sopenharmony_ci					    unsigned int range, int *val)
59762306a36Sopenharmony_ci{
59862306a36Sopenharmony_ci	switch (range) {
59962306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_10V:
60062306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_2P5V_EXT_POW:
60162306a36Sopenharmony_ci		*val = 0;
60262306a36Sopenharmony_ci		return 0;
60362306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_2P5V_INT_POW:
60462306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_5V_BI_DIR:
60562306a36Sopenharmony_ci		*val = -2500;
60662306a36Sopenharmony_ci		return 0;
60762306a36Sopenharmony_ci	default:
60862306a36Sopenharmony_ci		dev_err(st->dev, "ADC range invalid\n");
60962306a36Sopenharmony_ci		return -EINVAL;
61062306a36Sopenharmony_ci	}
61162306a36Sopenharmony_ci}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_cistatic int ad74413r_range_to_voltage_offset_raw(struct ad74413r_state *st,
61462306a36Sopenharmony_ci						unsigned int range, int *val)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	switch (range) {
61762306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_10V:
61862306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_2P5V_EXT_POW:
61962306a36Sopenharmony_ci		*val = 0;
62062306a36Sopenharmony_ci		return 0;
62162306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_2P5V_INT_POW:
62262306a36Sopenharmony_ci		*val = -((int)AD74413R_ADC_RESULT_MAX);
62362306a36Sopenharmony_ci		return 0;
62462306a36Sopenharmony_ci	case AD74413R_ADC_RANGE_5V_BI_DIR:
62562306a36Sopenharmony_ci		*val = -((int)AD74413R_ADC_RESULT_MAX / 2);
62662306a36Sopenharmony_ci		return 0;
62762306a36Sopenharmony_ci	default:
62862306a36Sopenharmony_ci		dev_err(st->dev, "ADC range invalid\n");
62962306a36Sopenharmony_ci		return -EINVAL;
63062306a36Sopenharmony_ci	}
63162306a36Sopenharmony_ci}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_cistatic int ad74413r_get_output_voltage_scale(struct ad74413r_state *st,
63462306a36Sopenharmony_ci					     int *val, int *val2)
63562306a36Sopenharmony_ci{
63662306a36Sopenharmony_ci	*val = AD74413R_DAC_VOLTAGE_MAX;
63762306a36Sopenharmony_ci	*val2 = AD74413R_DAC_CODE_MAX;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_cistatic int ad74413r_get_output_current_scale(struct ad74413r_state *st,
64362306a36Sopenharmony_ci					     int *val, int *val2)
64462306a36Sopenharmony_ci{
64562306a36Sopenharmony_ci	*val = regulator_get_voltage(st->refin_reg);
64662306a36Sopenharmony_ci	*val2 = st->sense_resistor_ohms * AD74413R_DAC_CODE_MAX * 1000;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_cistatic int ad74413r_get_input_voltage_scale(struct ad74413r_state *st,
65262306a36Sopenharmony_ci					    unsigned int channel,
65362306a36Sopenharmony_ci					    int *val, int *val2)
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	unsigned int range;
65662306a36Sopenharmony_ci	int ret;
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	ret = ad74413r_get_adc_range(st, channel, &range);
65962306a36Sopenharmony_ci	if (ret)
66062306a36Sopenharmony_ci		return ret;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	ret = ad74413r_range_to_voltage_range(st, range, val);
66362306a36Sopenharmony_ci	if (ret)
66462306a36Sopenharmony_ci		return ret;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	*val2 = AD74413R_ADC_RESULT_MAX;
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
66962306a36Sopenharmony_ci}
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_cistatic int ad74413r_get_input_voltage_offset(struct ad74413r_state *st,
67262306a36Sopenharmony_ci					     unsigned int channel, int *val)
67362306a36Sopenharmony_ci{
67462306a36Sopenharmony_ci	unsigned int range;
67562306a36Sopenharmony_ci	int ret;
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	ret = ad74413r_get_adc_range(st, channel, &range);
67862306a36Sopenharmony_ci	if (ret)
67962306a36Sopenharmony_ci		return ret;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	ret = ad74413r_range_to_voltage_offset_raw(st, range, val);
68262306a36Sopenharmony_ci	if (ret)
68362306a36Sopenharmony_ci		return ret;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	return IIO_VAL_INT;
68662306a36Sopenharmony_ci}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_cistatic int ad74413r_get_input_current_scale(struct ad74413r_state *st,
68962306a36Sopenharmony_ci					    unsigned int channel, int *val,
69062306a36Sopenharmony_ci					    int *val2)
69162306a36Sopenharmony_ci{
69262306a36Sopenharmony_ci	unsigned int range;
69362306a36Sopenharmony_ci	int ret;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	ret = ad74413r_get_adc_range(st, channel, &range);
69662306a36Sopenharmony_ci	if (ret)
69762306a36Sopenharmony_ci		return ret;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	ret = ad74413r_range_to_voltage_range(st, range, val);
70062306a36Sopenharmony_ci	if (ret)
70162306a36Sopenharmony_ci		return ret;
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	*val2 = AD74413R_ADC_RESULT_MAX * st->sense_resistor_ohms;
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	return IIO_VAL_FRACTIONAL;
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_cistatic int ad74413_get_input_current_offset(struct ad74413r_state *st,
70962306a36Sopenharmony_ci					    unsigned int channel, int *val)
71062306a36Sopenharmony_ci{
71162306a36Sopenharmony_ci	unsigned int range;
71262306a36Sopenharmony_ci	int voltage_range;
71362306a36Sopenharmony_ci	int voltage_offset;
71462306a36Sopenharmony_ci	int ret;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	ret = ad74413r_get_adc_range(st, channel, &range);
71762306a36Sopenharmony_ci	if (ret)
71862306a36Sopenharmony_ci		return ret;
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	ret = ad74413r_range_to_voltage_range(st, range, &voltage_range);
72162306a36Sopenharmony_ci	if (ret)
72262306a36Sopenharmony_ci		return ret;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	ret = ad74413r_range_to_voltage_offset(st, range, &voltage_offset);
72562306a36Sopenharmony_ci	if (ret)
72662306a36Sopenharmony_ci		return ret;
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	*val = voltage_offset * (int)AD74413R_ADC_RESULT_MAX / voltage_range;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	return IIO_VAL_INT;
73162306a36Sopenharmony_ci}
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_cistatic int ad74413r_get_adc_rate(struct ad74413r_state *st,
73462306a36Sopenharmony_ci				 unsigned int channel, int *val)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	unsigned int rejection;
73762306a36Sopenharmony_ci	int ret;
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	ret = ad74413r_get_adc_rejection(st, channel, &rejection);
74062306a36Sopenharmony_ci	if (ret)
74162306a36Sopenharmony_ci		return ret;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	ret = ad74413r_rejection_to_rate(st, rejection, val);
74462306a36Sopenharmony_ci	if (ret)
74562306a36Sopenharmony_ci		return ret;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	return IIO_VAL_INT;
74862306a36Sopenharmony_ci}
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cistatic int ad74413r_set_adc_rate(struct ad74413r_state *st,
75162306a36Sopenharmony_ci				 unsigned int channel, int val)
75262306a36Sopenharmony_ci{
75362306a36Sopenharmony_ci	unsigned int rejection;
75462306a36Sopenharmony_ci	int ret;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	ret = ad74413r_rate_to_rejection(st, val, &rejection);
75762306a36Sopenharmony_ci	if (ret)
75862306a36Sopenharmony_ci		return ret;
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	return ad74413r_set_adc_rejection(st, channel, rejection);
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_cistatic irqreturn_t ad74413r_trigger_handler(int irq, void *p)
76462306a36Sopenharmony_ci{
76562306a36Sopenharmony_ci	struct iio_poll_func *pf = p;
76662306a36Sopenharmony_ci	struct iio_dev *indio_dev = pf->indio_dev;
76762306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
76862306a36Sopenharmony_ci	u8 *rx_buf = st->adc_samples_buf.rx_buf;
76962306a36Sopenharmony_ci	unsigned int i;
77062306a36Sopenharmony_ci	int ret;
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	ret = spi_sync(st->spi, &st->adc_samples_msg);
77362306a36Sopenharmony_ci	if (ret)
77462306a36Sopenharmony_ci		goto out;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	for (i = 0; i < st->adc_active_channels; i++)
77762306a36Sopenharmony_ci		ad74413r_crc_check(st, &rx_buf[i * AD74413R_FRAME_SIZE]);
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	iio_push_to_buffers_with_timestamp(indio_dev, &st->adc_samples_buf,
78062306a36Sopenharmony_ci					   iio_get_time_ns(indio_dev));
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ciout:
78362306a36Sopenharmony_ci	iio_trigger_notify_done(indio_dev->trig);
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	return IRQ_HANDLED;
78662306a36Sopenharmony_ci}
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_cistatic irqreturn_t ad74413r_adc_data_interrupt(int irq, void *data)
78962306a36Sopenharmony_ci{
79062306a36Sopenharmony_ci	struct iio_dev *indio_dev = data;
79162306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	if (iio_buffer_enabled(indio_dev))
79462306a36Sopenharmony_ci		iio_trigger_poll(st->trig);
79562306a36Sopenharmony_ci	else
79662306a36Sopenharmony_ci		complete(&st->adc_data_completion);
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	return IRQ_HANDLED;
79962306a36Sopenharmony_ci}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_cistatic int _ad74413r_get_single_adc_result(struct ad74413r_state *st,
80262306a36Sopenharmony_ci					   unsigned int channel, int *val)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	unsigned int uval;
80562306a36Sopenharmony_ci	int ret;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	reinit_completion(&st->adc_data_completion);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	ret = ad74413r_set_adc_channel_enable(st, channel, true);
81062306a36Sopenharmony_ci	if (ret)
81162306a36Sopenharmony_ci		return ret;
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci	ret = ad74413r_set_adc_conv_seq(st, AD74413R_CONV_SEQ_SINGLE);
81462306a36Sopenharmony_ci	if (ret)
81562306a36Sopenharmony_ci		return ret;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	ret = wait_for_completion_timeout(&st->adc_data_completion,
81862306a36Sopenharmony_ci					  msecs_to_jiffies(1000));
81962306a36Sopenharmony_ci	if (!ret) {
82062306a36Sopenharmony_ci		ret = -ETIMEDOUT;
82162306a36Sopenharmony_ci		return ret;
82262306a36Sopenharmony_ci	}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD74413R_REG_ADC_RESULT_X(channel),
82562306a36Sopenharmony_ci			  &uval);
82662306a36Sopenharmony_ci	if (ret)
82762306a36Sopenharmony_ci		return ret;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	ret = ad74413r_set_adc_conv_seq(st, AD74413R_CONV_SEQ_OFF);
83062306a36Sopenharmony_ci	if (ret)
83162306a36Sopenharmony_ci		return ret;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	ret = ad74413r_set_adc_channel_enable(st, channel, false);
83462306a36Sopenharmony_ci	if (ret)
83562306a36Sopenharmony_ci		return ret;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	*val = uval;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	return IIO_VAL_INT;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic int ad74413r_get_single_adc_result(struct iio_dev *indio_dev,
84362306a36Sopenharmony_ci					  unsigned int channel, int *val)
84462306a36Sopenharmony_ci{
84562306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
84662306a36Sopenharmony_ci	int ret;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	ret = iio_device_claim_direct_mode(indio_dev);
84962306a36Sopenharmony_ci	if (ret)
85062306a36Sopenharmony_ci		return ret;
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	mutex_lock(&st->lock);
85362306a36Sopenharmony_ci	ret = _ad74413r_get_single_adc_result(st, channel, val);
85462306a36Sopenharmony_ci	mutex_unlock(&st->lock);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	iio_device_release_direct_mode(indio_dev);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	return ret;
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic void ad74413r_adc_to_resistance_result(int adc_result, int *val)
86262306a36Sopenharmony_ci{
86362306a36Sopenharmony_ci	if (adc_result == AD74413R_ADC_RESULT_MAX)
86462306a36Sopenharmony_ci		adc_result = AD74413R_ADC_RESULT_MAX - 1;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	*val = DIV_ROUND_CLOSEST(adc_result * 2100,
86762306a36Sopenharmony_ci				 AD74413R_ADC_RESULT_MAX - adc_result);
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
87162306a36Sopenharmony_ci				     const unsigned long *active_scan_mask)
87262306a36Sopenharmony_ci{
87362306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
87462306a36Sopenharmony_ci	struct spi_transfer *xfer = st->adc_samples_xfer;
87562306a36Sopenharmony_ci	u8 *rx_buf = st->adc_samples_buf.rx_buf;
87662306a36Sopenharmony_ci	u8 *tx_buf = st->adc_samples_tx_buf;
87762306a36Sopenharmony_ci	unsigned int channel;
87862306a36Sopenharmony_ci	int ret = -EINVAL;
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	mutex_lock(&st->lock);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	spi_message_init(&st->adc_samples_msg);
88362306a36Sopenharmony_ci	st->adc_active_channels = 0;
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	for_each_clear_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
88662306a36Sopenharmony_ci		ret = ad74413r_set_adc_channel_enable(st, channel, false);
88762306a36Sopenharmony_ci		if (ret)
88862306a36Sopenharmony_ci			goto out;
88962306a36Sopenharmony_ci	}
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	if (*active_scan_mask == 0)
89262306a36Sopenharmony_ci		goto out;
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	/*
89562306a36Sopenharmony_ci	 * The read select register is used to select which register's value
89662306a36Sopenharmony_ci	 * will be sent by the slave on the next SPI frame.
89762306a36Sopenharmony_ci	 *
89862306a36Sopenharmony_ci	 * Create an SPI message that, on each step, writes to the read select
89962306a36Sopenharmony_ci	 * register to select the ADC result of the next enabled channel, and
90062306a36Sopenharmony_ci	 * reads the ADC result of the previous enabled channel.
90162306a36Sopenharmony_ci	 *
90262306a36Sopenharmony_ci	 * Example:
90362306a36Sopenharmony_ci	 * W: [WCH1] [WCH2] [WCH2] [WCH3] [    ]
90462306a36Sopenharmony_ci	 * R: [    ] [RCH1] [RCH2] [RCH3] [RCH4]
90562306a36Sopenharmony_ci	 */
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	for_each_set_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
90862306a36Sopenharmony_ci		ret = ad74413r_set_adc_channel_enable(st, channel, true);
90962306a36Sopenharmony_ci		if (ret)
91062306a36Sopenharmony_ci			goto out;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci		st->adc_active_channels++;
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci		if (xfer == st->adc_samples_xfer)
91562306a36Sopenharmony_ci			xfer->rx_buf = NULL;
91662306a36Sopenharmony_ci		else
91762306a36Sopenharmony_ci			xfer->rx_buf = rx_buf;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci		xfer->tx_buf = tx_buf;
92062306a36Sopenharmony_ci		xfer->len = AD74413R_FRAME_SIZE;
92162306a36Sopenharmony_ci		xfer->cs_change = 1;
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci		ad74413r_format_reg_write(AD74413R_REG_READ_SELECT,
92462306a36Sopenharmony_ci					  AD74413R_REG_ADC_RESULT_X(channel),
92562306a36Sopenharmony_ci					  tx_buf);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci		spi_message_add_tail(xfer, &st->adc_samples_msg);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci		tx_buf += AD74413R_FRAME_SIZE;
93062306a36Sopenharmony_ci		if (xfer != st->adc_samples_xfer)
93162306a36Sopenharmony_ci			rx_buf += AD74413R_FRAME_SIZE;
93262306a36Sopenharmony_ci		xfer++;
93362306a36Sopenharmony_ci	}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	xfer->rx_buf = rx_buf;
93662306a36Sopenharmony_ci	xfer->tx_buf = NULL;
93762306a36Sopenharmony_ci	xfer->len = AD74413R_FRAME_SIZE;
93862306a36Sopenharmony_ci	xfer->cs_change = 0;
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	spi_message_add_tail(xfer, &st->adc_samples_msg);
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ciout:
94362306a36Sopenharmony_ci	mutex_unlock(&st->lock);
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	return ret;
94662306a36Sopenharmony_ci}
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_cistatic int ad74413r_buffer_postenable(struct iio_dev *indio_dev)
94962306a36Sopenharmony_ci{
95062306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	return ad74413r_set_adc_conv_seq(st, AD74413R_CONV_SEQ_CONTINUOUS);
95362306a36Sopenharmony_ci}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_cistatic int ad74413r_buffer_predisable(struct iio_dev *indio_dev)
95662306a36Sopenharmony_ci{
95762306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	return ad74413r_set_adc_conv_seq(st, AD74413R_CONV_SEQ_OFF);
96062306a36Sopenharmony_ci}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_cistatic int ad74413r_read_raw(struct iio_dev *indio_dev,
96362306a36Sopenharmony_ci			     struct iio_chan_spec const *chan,
96462306a36Sopenharmony_ci			     int *val, int *val2, long info)
96562306a36Sopenharmony_ci{
96662306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	switch (info) {
96962306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
97062306a36Sopenharmony_ci		switch (chan->type) {
97162306a36Sopenharmony_ci		case IIO_VOLTAGE:
97262306a36Sopenharmony_ci			if (chan->output)
97362306a36Sopenharmony_ci				return ad74413r_get_output_voltage_scale(st,
97462306a36Sopenharmony_ci					val, val2);
97562306a36Sopenharmony_ci			else
97662306a36Sopenharmony_ci				return ad74413r_get_input_voltage_scale(st,
97762306a36Sopenharmony_ci					chan->channel, val, val2);
97862306a36Sopenharmony_ci		case IIO_CURRENT:
97962306a36Sopenharmony_ci			if (chan->output)
98062306a36Sopenharmony_ci				return ad74413r_get_output_current_scale(st,
98162306a36Sopenharmony_ci					val, val2);
98262306a36Sopenharmony_ci			else
98362306a36Sopenharmony_ci				return ad74413r_get_input_current_scale(st,
98462306a36Sopenharmony_ci					chan->channel, val, val2);
98562306a36Sopenharmony_ci		default:
98662306a36Sopenharmony_ci			return -EINVAL;
98762306a36Sopenharmony_ci		}
98862306a36Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
98962306a36Sopenharmony_ci		switch (chan->type) {
99062306a36Sopenharmony_ci		case IIO_VOLTAGE:
99162306a36Sopenharmony_ci			return ad74413r_get_input_voltage_offset(st,
99262306a36Sopenharmony_ci				chan->channel, val);
99362306a36Sopenharmony_ci		case IIO_CURRENT:
99462306a36Sopenharmony_ci			return ad74413_get_input_current_offset(st,
99562306a36Sopenharmony_ci				chan->channel, val);
99662306a36Sopenharmony_ci		default:
99762306a36Sopenharmony_ci			return -EINVAL;
99862306a36Sopenharmony_ci		}
99962306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
100062306a36Sopenharmony_ci		if (chan->output)
100162306a36Sopenharmony_ci			return -EINVAL;
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci		return ad74413r_get_single_adc_result(indio_dev, chan->channel,
100462306a36Sopenharmony_ci						      val);
100562306a36Sopenharmony_ci	case IIO_CHAN_INFO_PROCESSED: {
100662306a36Sopenharmony_ci		int ret;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci		ret = ad74413r_get_single_adc_result(indio_dev, chan->channel,
100962306a36Sopenharmony_ci						     val);
101062306a36Sopenharmony_ci		if (ret < 0)
101162306a36Sopenharmony_ci			return ret;
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci		ad74413r_adc_to_resistance_result(*val, val);
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci		return ret;
101662306a36Sopenharmony_ci	}
101762306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
101862306a36Sopenharmony_ci		return ad74413r_get_adc_rate(st, chan->channel, val);
101962306a36Sopenharmony_ci	default:
102062306a36Sopenharmony_ci		return -EINVAL;
102162306a36Sopenharmony_ci	}
102262306a36Sopenharmony_ci}
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_cistatic int ad74413r_write_raw(struct iio_dev *indio_dev,
102562306a36Sopenharmony_ci			      struct iio_chan_spec const *chan,
102662306a36Sopenharmony_ci			      int val, int val2, long info)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	switch (info) {
103162306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
103262306a36Sopenharmony_ci		if (!chan->output)
103362306a36Sopenharmony_ci			return -EINVAL;
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci		if (val < 0 || val > AD74413R_DAC_CODE_MAX) {
103662306a36Sopenharmony_ci			dev_err(st->dev, "Invalid DAC code\n");
103762306a36Sopenharmony_ci			return -EINVAL;
103862306a36Sopenharmony_ci		}
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci		return ad74413r_set_channel_dac_code(st, chan->channel, val);
104162306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
104262306a36Sopenharmony_ci		return ad74413r_set_adc_rate(st, chan->channel, val);
104362306a36Sopenharmony_ci	default:
104462306a36Sopenharmony_ci		return -EINVAL;
104562306a36Sopenharmony_ci	}
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_cistatic int ad74413r_read_avail(struct iio_dev *indio_dev,
104962306a36Sopenharmony_ci			       struct iio_chan_spec const *chan,
105062306a36Sopenharmony_ci			       const int **vals, int *type, int *length,
105162306a36Sopenharmony_ci			       long info)
105262306a36Sopenharmony_ci{
105362306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	switch (info) {
105662306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
105762306a36Sopenharmony_ci		if (st->chip_info->hart_support) {
105862306a36Sopenharmony_ci			*vals = ad74413r_adc_sampling_rates_hart;
105962306a36Sopenharmony_ci			*length = ARRAY_SIZE(ad74413r_adc_sampling_rates_hart);
106062306a36Sopenharmony_ci		} else {
106162306a36Sopenharmony_ci			*vals = ad74413r_adc_sampling_rates;
106262306a36Sopenharmony_ci			*length = ARRAY_SIZE(ad74413r_adc_sampling_rates);
106362306a36Sopenharmony_ci		}
106462306a36Sopenharmony_ci		*type = IIO_VAL_INT;
106562306a36Sopenharmony_ci		return IIO_AVAIL_LIST;
106662306a36Sopenharmony_ci	default:
106762306a36Sopenharmony_ci		return -EINVAL;
106862306a36Sopenharmony_ci	}
106962306a36Sopenharmony_ci}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops ad74413r_buffer_ops = {
107262306a36Sopenharmony_ci	.postenable = &ad74413r_buffer_postenable,
107362306a36Sopenharmony_ci	.predisable = &ad74413r_buffer_predisable,
107462306a36Sopenharmony_ci};
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_cistatic const struct iio_trigger_ops ad74413r_trigger_ops = {
107762306a36Sopenharmony_ci	.validate_device = iio_trigger_validate_own_device,
107862306a36Sopenharmony_ci};
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_cistatic const struct iio_info ad74413r_info = {
108162306a36Sopenharmony_ci	.read_raw = &ad74413r_read_raw,
108262306a36Sopenharmony_ci	.write_raw = &ad74413r_write_raw,
108362306a36Sopenharmony_ci	.read_avail = &ad74413r_read_avail,
108462306a36Sopenharmony_ci	.update_scan_mode = &ad74413r_update_scan_mode,
108562306a36Sopenharmony_ci};
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci#define AD74413R_DAC_CHANNEL(_type, extra_mask_separate)		\
108862306a36Sopenharmony_ci	{								\
108962306a36Sopenharmony_ci		.type = (_type),					\
109062306a36Sopenharmony_ci		.indexed = 1,						\
109162306a36Sopenharmony_ci		.output = 1,						\
109262306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)		\
109362306a36Sopenharmony_ci				      | (extra_mask_separate),		\
109462306a36Sopenharmony_ci	}
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci#define AD74413R_ADC_CHANNEL(_type, extra_mask_separate)		\
109762306a36Sopenharmony_ci	{								\
109862306a36Sopenharmony_ci		.type = (_type),					\
109962306a36Sopenharmony_ci		.indexed = 1,						\
110062306a36Sopenharmony_ci		.output = 0,						\
110162306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)		\
110262306a36Sopenharmony_ci				      | BIT(IIO_CHAN_INFO_SAMP_FREQ)	\
110362306a36Sopenharmony_ci				      | (extra_mask_separate),		\
110462306a36Sopenharmony_ci		.info_mask_separate_available =				\
110562306a36Sopenharmony_ci					BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
110662306a36Sopenharmony_ci		.scan_type = {						\
110762306a36Sopenharmony_ci			.sign = 'u',					\
110862306a36Sopenharmony_ci			.realbits = 16,					\
110962306a36Sopenharmony_ci			.storagebits = 32,				\
111062306a36Sopenharmony_ci			.shift = 8,					\
111162306a36Sopenharmony_ci			.endianness = IIO_BE,				\
111262306a36Sopenharmony_ci		},							\
111362306a36Sopenharmony_ci	}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci#define AD74413R_ADC_VOLTAGE_CHANNEL					\
111662306a36Sopenharmony_ci	AD74413R_ADC_CHANNEL(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE)	\
111762306a36Sopenharmony_ci			     | BIT(IIO_CHAN_INFO_OFFSET))
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci#define AD74413R_ADC_CURRENT_CHANNEL					\
112062306a36Sopenharmony_ci	AD74413R_ADC_CHANNEL(IIO_CURRENT,  BIT(IIO_CHAN_INFO_SCALE)	\
112162306a36Sopenharmony_ci			     | BIT(IIO_CHAN_INFO_OFFSET))
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_cistatic struct iio_chan_spec ad74413r_voltage_output_channels[] = {
112462306a36Sopenharmony_ci	AD74413R_DAC_CHANNEL(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE)),
112562306a36Sopenharmony_ci	AD74413R_ADC_CURRENT_CHANNEL,
112662306a36Sopenharmony_ci};
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_cistatic struct iio_chan_spec ad74413r_current_output_channels[] = {
112962306a36Sopenharmony_ci	AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
113062306a36Sopenharmony_ci	AD74413R_ADC_VOLTAGE_CHANNEL,
113162306a36Sopenharmony_ci};
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_cistatic struct iio_chan_spec ad74413r_voltage_input_channels[] = {
113462306a36Sopenharmony_ci	AD74413R_ADC_VOLTAGE_CHANNEL,
113562306a36Sopenharmony_ci};
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_cistatic struct iio_chan_spec ad74413r_current_input_channels[] = {
113862306a36Sopenharmony_ci	AD74413R_ADC_CURRENT_CHANNEL,
113962306a36Sopenharmony_ci};
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_cistatic struct iio_chan_spec ad74413r_current_input_loop_channels[] = {
114262306a36Sopenharmony_ci	AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
114362306a36Sopenharmony_ci	AD74413R_ADC_CURRENT_CHANNEL,
114462306a36Sopenharmony_ci};
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_cistatic struct iio_chan_spec ad74413r_resistance_input_channels[] = {
114762306a36Sopenharmony_ci	AD74413R_ADC_CHANNEL(IIO_RESISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)),
114862306a36Sopenharmony_ci};
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_cistatic struct iio_chan_spec ad74413r_digital_input_channels[] = {
115162306a36Sopenharmony_ci	AD74413R_ADC_VOLTAGE_CHANNEL,
115262306a36Sopenharmony_ci};
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci#define _AD74413R_CHANNELS(_channels)			\
115562306a36Sopenharmony_ci	{						\
115662306a36Sopenharmony_ci		.channels = _channels,			\
115762306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(_channels),	\
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci#define AD74413R_CHANNELS(name) \
116162306a36Sopenharmony_ci	_AD74413R_CHANNELS(ad74413r_ ## name ## _channels)
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_cistatic const struct ad74413r_channels ad74413r_channels_map[] = {
116462306a36Sopenharmony_ci	[CH_FUNC_HIGH_IMPEDANCE] = AD74413R_CHANNELS(voltage_input),
116562306a36Sopenharmony_ci	[CH_FUNC_VOLTAGE_OUTPUT] = AD74413R_CHANNELS(voltage_output),
116662306a36Sopenharmony_ci	[CH_FUNC_CURRENT_OUTPUT] = AD74413R_CHANNELS(current_output),
116762306a36Sopenharmony_ci	[CH_FUNC_VOLTAGE_INPUT] = AD74413R_CHANNELS(voltage_input),
116862306a36Sopenharmony_ci	[CH_FUNC_CURRENT_INPUT_EXT_POWER] = AD74413R_CHANNELS(current_input),
116962306a36Sopenharmony_ci	[CH_FUNC_CURRENT_INPUT_LOOP_POWER] = AD74413R_CHANNELS(current_input_loop),
117062306a36Sopenharmony_ci	[CH_FUNC_RESISTANCE_INPUT] = AD74413R_CHANNELS(resistance_input),
117162306a36Sopenharmony_ci	[CH_FUNC_DIGITAL_INPUT_LOGIC] = AD74413R_CHANNELS(digital_input),
117262306a36Sopenharmony_ci	[CH_FUNC_DIGITAL_INPUT_LOOP_POWER] = AD74413R_CHANNELS(digital_input),
117362306a36Sopenharmony_ci	[CH_FUNC_CURRENT_INPUT_EXT_POWER_HART] = AD74413R_CHANNELS(current_input),
117462306a36Sopenharmony_ci	[CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART] = AD74413R_CHANNELS(current_input),
117562306a36Sopenharmony_ci};
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_cistatic int ad74413r_parse_channel_config(struct iio_dev *indio_dev,
117862306a36Sopenharmony_ci					 struct fwnode_handle *channel_node)
117962306a36Sopenharmony_ci{
118062306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
118162306a36Sopenharmony_ci	struct ad74413r_channel_config *config;
118262306a36Sopenharmony_ci	u32 index;
118362306a36Sopenharmony_ci	int ret;
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	ret = fwnode_property_read_u32(channel_node, "reg", &index);
118662306a36Sopenharmony_ci	if (ret) {
118762306a36Sopenharmony_ci		dev_err(st->dev, "Failed to read channel reg: %d\n", ret);
118862306a36Sopenharmony_ci		return ret;
118962306a36Sopenharmony_ci	}
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	if (index >= AD74413R_CHANNEL_MAX) {
119262306a36Sopenharmony_ci		dev_err(st->dev, "Channel index %u is too large\n", index);
119362306a36Sopenharmony_ci		return -EINVAL;
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	config = &st->channel_configs[index];
119762306a36Sopenharmony_ci	if (config->initialized) {
119862306a36Sopenharmony_ci		dev_err(st->dev, "Channel %u already initialized\n", index);
119962306a36Sopenharmony_ci		return -EINVAL;
120062306a36Sopenharmony_ci	}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	config->func = CH_FUNC_HIGH_IMPEDANCE;
120362306a36Sopenharmony_ci	fwnode_property_read_u32(channel_node, "adi,ch-func", &config->func);
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	if (config->func < CH_FUNC_MIN || config->func > CH_FUNC_MAX) {
120662306a36Sopenharmony_ci		dev_err(st->dev, "Invalid channel function %u\n", config->func);
120762306a36Sopenharmony_ci		return -EINVAL;
120862306a36Sopenharmony_ci	}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	if (!st->chip_info->hart_support &&
121162306a36Sopenharmony_ci	    (config->func == CH_FUNC_CURRENT_INPUT_EXT_POWER_HART ||
121262306a36Sopenharmony_ci	     config->func == CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART)) {
121362306a36Sopenharmony_ci		dev_err(st->dev, "Unsupported HART function %u\n", config->func);
121462306a36Sopenharmony_ci		return -EINVAL;
121562306a36Sopenharmony_ci	}
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	if (config->func == CH_FUNC_DIGITAL_INPUT_LOGIC ||
121862306a36Sopenharmony_ci	    config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER)
121962306a36Sopenharmony_ci		st->num_comparator_gpios++;
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	config->gpo_comparator = fwnode_property_read_bool(channel_node,
122262306a36Sopenharmony_ci		"adi,gpo-comparator");
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	fwnode_property_read_u32(channel_node, "drive-strength-microamp",
122562306a36Sopenharmony_ci				 &config->drive_strength);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	if (!config->gpo_comparator)
122862306a36Sopenharmony_ci		st->num_gpo_gpios++;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	indio_dev->num_channels += ad74413r_channels_map[config->func].num_channels;
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	config->initialized = true;
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	return 0;
123562306a36Sopenharmony_ci}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_cistatic int ad74413r_parse_channel_configs(struct iio_dev *indio_dev)
123862306a36Sopenharmony_ci{
123962306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
124062306a36Sopenharmony_ci	struct fwnode_handle *channel_node = NULL;
124162306a36Sopenharmony_ci	int ret;
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci	fwnode_for_each_available_child_node(dev_fwnode(st->dev), channel_node) {
124462306a36Sopenharmony_ci		ret = ad74413r_parse_channel_config(indio_dev, channel_node);
124562306a36Sopenharmony_ci		if (ret)
124662306a36Sopenharmony_ci			goto put_channel_node;
124762306a36Sopenharmony_ci	}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	return 0;
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ciput_channel_node:
125262306a36Sopenharmony_ci	fwnode_handle_put(channel_node);
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	return ret;
125562306a36Sopenharmony_ci}
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_cistatic int ad74413r_setup_channels(struct iio_dev *indio_dev)
125862306a36Sopenharmony_ci{
125962306a36Sopenharmony_ci	struct ad74413r_state *st = iio_priv(indio_dev);
126062306a36Sopenharmony_ci	struct ad74413r_channel_config *config;
126162306a36Sopenharmony_ci	struct iio_chan_spec *channels, *chans;
126262306a36Sopenharmony_ci	unsigned int i, num_chans, chan_i;
126362306a36Sopenharmony_ci	int ret;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	channels = devm_kcalloc(st->dev, sizeof(*channels),
126662306a36Sopenharmony_ci				indio_dev->num_channels, GFP_KERNEL);
126762306a36Sopenharmony_ci	if (!channels)
126862306a36Sopenharmony_ci		return -ENOMEM;
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	indio_dev->channels = channels;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	for (i = 0; i < AD74413R_CHANNEL_MAX; i++) {
127362306a36Sopenharmony_ci		config = &st->channel_configs[i];
127462306a36Sopenharmony_ci		chans = ad74413r_channels_map[config->func].channels;
127562306a36Sopenharmony_ci		num_chans = ad74413r_channels_map[config->func].num_channels;
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci		memcpy(channels, chans, num_chans * sizeof(*chans));
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci		for (chan_i = 0; chan_i < num_chans; chan_i++) {
128062306a36Sopenharmony_ci			struct iio_chan_spec *chan = &channels[chan_i];
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci			chan->channel = i;
128362306a36Sopenharmony_ci			if (chan->output)
128462306a36Sopenharmony_ci				chan->scan_index = -1;
128562306a36Sopenharmony_ci			else
128662306a36Sopenharmony_ci				chan->scan_index = i;
128762306a36Sopenharmony_ci		}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci		ret = ad74413r_set_channel_function(st, i, config->func);
129062306a36Sopenharmony_ci		if (ret)
129162306a36Sopenharmony_ci			return ret;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci		channels += num_chans;
129462306a36Sopenharmony_ci	}
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	return 0;
129762306a36Sopenharmony_ci}
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_cistatic int ad74413r_setup_gpios(struct ad74413r_state *st)
130062306a36Sopenharmony_ci{
130162306a36Sopenharmony_ci	struct ad74413r_channel_config *config;
130262306a36Sopenharmony_ci	unsigned int comp_gpio_i = 0;
130362306a36Sopenharmony_ci	unsigned int gpo_gpio_i = 0;
130462306a36Sopenharmony_ci	unsigned int i;
130562306a36Sopenharmony_ci	u8 gpo_config;
130662306a36Sopenharmony_ci	u32 strength;
130762306a36Sopenharmony_ci	int ret;
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	for (i = 0; i < AD74413R_CHANNEL_MAX; i++) {
131062306a36Sopenharmony_ci		config = &st->channel_configs[i];
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci		if (config->gpo_comparator) {
131362306a36Sopenharmony_ci			gpo_config = AD74413R_GPO_CONFIG_COMPARATOR;
131462306a36Sopenharmony_ci		} else {
131562306a36Sopenharmony_ci			gpo_config = AD74413R_GPO_CONFIG_LOGIC;
131662306a36Sopenharmony_ci			st->gpo_gpio_offsets[gpo_gpio_i++] = i;
131762306a36Sopenharmony_ci		}
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci		if (config->func == CH_FUNC_DIGITAL_INPUT_LOGIC ||
132062306a36Sopenharmony_ci		    config->func == CH_FUNC_DIGITAL_INPUT_LOOP_POWER) {
132162306a36Sopenharmony_ci			st->comp_gpio_offsets[comp_gpio_i++] = i;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci			strength = config->drive_strength;
132462306a36Sopenharmony_ci			ret = ad74413r_set_comp_drive_strength(st, i, strength);
132562306a36Sopenharmony_ci			if (ret)
132662306a36Sopenharmony_ci				return ret;
132762306a36Sopenharmony_ci		}
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci		ret = ad74413r_set_gpo_config(st, i, gpo_config);
133062306a36Sopenharmony_ci		if (ret)
133162306a36Sopenharmony_ci			return ret;
133262306a36Sopenharmony_ci	}
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	return 0;
133562306a36Sopenharmony_ci}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_cistatic void ad74413r_regulator_disable(void *regulator)
133862306a36Sopenharmony_ci{
133962306a36Sopenharmony_ci	regulator_disable(regulator);
134062306a36Sopenharmony_ci}
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_cistatic int ad74413r_probe(struct spi_device *spi)
134362306a36Sopenharmony_ci{
134462306a36Sopenharmony_ci	struct ad74413r_state *st;
134562306a36Sopenharmony_ci	struct iio_dev *indio_dev;
134662306a36Sopenharmony_ci	int ret;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
134962306a36Sopenharmony_ci	if (!indio_dev)
135062306a36Sopenharmony_ci		return -ENOMEM;
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci	st = iio_priv(indio_dev);
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	st->spi = spi;
135562306a36Sopenharmony_ci	st->dev = &spi->dev;
135662306a36Sopenharmony_ci	st->chip_info = device_get_match_data(&spi->dev);
135762306a36Sopenharmony_ci	if (!st->chip_info) {
135862306a36Sopenharmony_ci		const struct spi_device_id *id = spi_get_device_id(spi);
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci		if (id)
136162306a36Sopenharmony_ci			st->chip_info =
136262306a36Sopenharmony_ci				(struct ad74413r_chip_info *)id->driver_data;
136362306a36Sopenharmony_ci		if (!st->chip_info)
136462306a36Sopenharmony_ci			return -EINVAL;
136562306a36Sopenharmony_ci	}
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci	mutex_init(&st->lock);
136862306a36Sopenharmony_ci	init_completion(&st->adc_data_completion);
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	st->regmap = devm_regmap_init(st->dev, NULL, st,
137162306a36Sopenharmony_ci				      &ad74413r_regmap_config);
137262306a36Sopenharmony_ci	if (IS_ERR(st->regmap))
137362306a36Sopenharmony_ci		return PTR_ERR(st->regmap);
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ci	st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
137662306a36Sopenharmony_ci	if (IS_ERR(st->reset_gpio))
137762306a36Sopenharmony_ci		return PTR_ERR(st->reset_gpio);
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci	st->refin_reg = devm_regulator_get(st->dev, "refin");
138062306a36Sopenharmony_ci	if (IS_ERR(st->refin_reg))
138162306a36Sopenharmony_ci		return dev_err_probe(st->dev, PTR_ERR(st->refin_reg),
138262306a36Sopenharmony_ci				     "Failed to get refin regulator\n");
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	ret = regulator_enable(st->refin_reg);
138562306a36Sopenharmony_ci	if (ret)
138662306a36Sopenharmony_ci		return ret;
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	ret = devm_add_action_or_reset(st->dev, ad74413r_regulator_disable,
138962306a36Sopenharmony_ci				       st->refin_reg);
139062306a36Sopenharmony_ci	if (ret)
139162306a36Sopenharmony_ci		return ret;
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	st->sense_resistor_ohms = 100000000;
139462306a36Sopenharmony_ci	device_property_read_u32(st->dev, "shunt-resistor-micro-ohms",
139562306a36Sopenharmony_ci				 &st->sense_resistor_ohms);
139662306a36Sopenharmony_ci	st->sense_resistor_ohms /= 1000000;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	st->trig = devm_iio_trigger_alloc(st->dev, "%s-dev%d",
139962306a36Sopenharmony_ci					  st->chip_info->name, iio_device_id(indio_dev));
140062306a36Sopenharmony_ci	if (!st->trig)
140162306a36Sopenharmony_ci		return -ENOMEM;
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	st->trig->ops = &ad74413r_trigger_ops;
140462306a36Sopenharmony_ci	iio_trigger_set_drvdata(st->trig, st);
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	ret = devm_iio_trigger_register(st->dev, st->trig);
140762306a36Sopenharmony_ci	if (ret)
140862306a36Sopenharmony_ci		return ret;
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	indio_dev->name = st->chip_info->name;
141162306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
141262306a36Sopenharmony_ci	indio_dev->info = &ad74413r_info;
141362306a36Sopenharmony_ci	indio_dev->trig = iio_trigger_get(st->trig);
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	ret = ad74413r_reset(st);
141662306a36Sopenharmony_ci	if (ret)
141762306a36Sopenharmony_ci		return ret;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	ret = ad74413r_parse_channel_configs(indio_dev);
142062306a36Sopenharmony_ci	if (ret)
142162306a36Sopenharmony_ci		return ret;
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	ret = ad74413r_setup_channels(indio_dev);
142462306a36Sopenharmony_ci	if (ret)
142562306a36Sopenharmony_ci		return ret;
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	ret = ad74413r_setup_gpios(st);
142862306a36Sopenharmony_ci	if (ret)
142962306a36Sopenharmony_ci		return ret;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	if (st->num_gpo_gpios) {
143262306a36Sopenharmony_ci		st->gpo_gpiochip.owner = THIS_MODULE;
143362306a36Sopenharmony_ci		st->gpo_gpiochip.label = st->chip_info->name;
143462306a36Sopenharmony_ci		st->gpo_gpiochip.base = -1;
143562306a36Sopenharmony_ci		st->gpo_gpiochip.ngpio = st->num_gpo_gpios;
143662306a36Sopenharmony_ci		st->gpo_gpiochip.parent = st->dev;
143762306a36Sopenharmony_ci		st->gpo_gpiochip.can_sleep = true;
143862306a36Sopenharmony_ci		st->gpo_gpiochip.set = ad74413r_gpio_set;
143962306a36Sopenharmony_ci		st->gpo_gpiochip.set_multiple = ad74413r_gpio_set_multiple;
144062306a36Sopenharmony_ci		st->gpo_gpiochip.set_config = ad74413r_gpio_set_gpo_config;
144162306a36Sopenharmony_ci		st->gpo_gpiochip.get_direction =
144262306a36Sopenharmony_ci			ad74413r_gpio_get_gpo_direction;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci		ret = devm_gpiochip_add_data(st->dev, &st->gpo_gpiochip, st);
144562306a36Sopenharmony_ci		if (ret)
144662306a36Sopenharmony_ci			return ret;
144762306a36Sopenharmony_ci	}
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	if (st->num_comparator_gpios) {
145062306a36Sopenharmony_ci		st->comp_gpiochip.owner = THIS_MODULE;
145162306a36Sopenharmony_ci		st->comp_gpiochip.label = st->chip_info->name;
145262306a36Sopenharmony_ci		st->comp_gpiochip.base = -1;
145362306a36Sopenharmony_ci		st->comp_gpiochip.ngpio = st->num_comparator_gpios;
145462306a36Sopenharmony_ci		st->comp_gpiochip.parent = st->dev;
145562306a36Sopenharmony_ci		st->comp_gpiochip.can_sleep = true;
145662306a36Sopenharmony_ci		st->comp_gpiochip.get = ad74413r_gpio_get;
145762306a36Sopenharmony_ci		st->comp_gpiochip.get_multiple = ad74413r_gpio_get_multiple;
145862306a36Sopenharmony_ci		st->comp_gpiochip.set_config = ad74413r_gpio_set_comp_config;
145962306a36Sopenharmony_ci		st->comp_gpiochip.get_direction =
146062306a36Sopenharmony_ci			ad74413r_gpio_get_comp_direction;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci		ret = devm_gpiochip_add_data(st->dev, &st->comp_gpiochip, st);
146362306a36Sopenharmony_ci		if (ret)
146462306a36Sopenharmony_ci			return ret;
146562306a36Sopenharmony_ci	}
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	ret = ad74413r_set_adc_conv_seq(st, AD74413R_CONV_SEQ_OFF);
146862306a36Sopenharmony_ci	if (ret)
146962306a36Sopenharmony_ci		return ret;
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	ret = devm_request_irq(st->dev, spi->irq, ad74413r_adc_data_interrupt,
147262306a36Sopenharmony_ci			       0, st->chip_info->name, indio_dev);
147362306a36Sopenharmony_ci	if (ret)
147462306a36Sopenharmony_ci		return dev_err_probe(st->dev, ret, "Failed to request irq\n");
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	ret = devm_iio_triggered_buffer_setup(st->dev, indio_dev,
147762306a36Sopenharmony_ci					      &iio_pollfunc_store_time,
147862306a36Sopenharmony_ci					      &ad74413r_trigger_handler,
147962306a36Sopenharmony_ci					      &ad74413r_buffer_ops);
148062306a36Sopenharmony_ci	if (ret)
148162306a36Sopenharmony_ci		return ret;
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	return devm_iio_device_register(st->dev, indio_dev);
148462306a36Sopenharmony_ci}
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_cistatic int ad74413r_unregister_driver(struct spi_driver *spi)
148762306a36Sopenharmony_ci{
148862306a36Sopenharmony_ci	spi_unregister_driver(spi);
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	return 0;
149162306a36Sopenharmony_ci}
149262306a36Sopenharmony_ci
149362306a36Sopenharmony_cistatic int __init ad74413r_register_driver(struct spi_driver *spi)
149462306a36Sopenharmony_ci{
149562306a36Sopenharmony_ci	crc8_populate_msb(ad74413r_crc8_table, AD74413R_CRC_POLYNOMIAL);
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	return spi_register_driver(spi);
149862306a36Sopenharmony_ci}
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_cistatic const struct ad74413r_chip_info ad74412r_chip_info_data = {
150162306a36Sopenharmony_ci	.hart_support = false,
150262306a36Sopenharmony_ci	.name = "ad74412r",
150362306a36Sopenharmony_ci};
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_cistatic const struct ad74413r_chip_info ad74413r_chip_info_data = {
150662306a36Sopenharmony_ci	.hart_support = true,
150762306a36Sopenharmony_ci	.name = "ad74413r",
150862306a36Sopenharmony_ci};
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_cistatic const struct of_device_id ad74413r_dt_id[] = {
151162306a36Sopenharmony_ci	{
151262306a36Sopenharmony_ci		.compatible = "adi,ad74412r",
151362306a36Sopenharmony_ci		.data = &ad74412r_chip_info_data,
151462306a36Sopenharmony_ci	},
151562306a36Sopenharmony_ci	{
151662306a36Sopenharmony_ci		.compatible = "adi,ad74413r",
151762306a36Sopenharmony_ci		.data = &ad74413r_chip_info_data,
151862306a36Sopenharmony_ci	},
151962306a36Sopenharmony_ci	{},
152062306a36Sopenharmony_ci};
152162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad74413r_dt_id);
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_cistatic const struct spi_device_id ad74413r_spi_id[] = {
152462306a36Sopenharmony_ci	{ .name = "ad74412r", .driver_data = (kernel_ulong_t)&ad74412r_chip_info_data },
152562306a36Sopenharmony_ci	{ .name = "ad74413r", .driver_data = (kernel_ulong_t)&ad74413r_chip_info_data },
152662306a36Sopenharmony_ci	{}
152762306a36Sopenharmony_ci};
152862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad74413r_spi_id);
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_cistatic struct spi_driver ad74413r_driver = {
153162306a36Sopenharmony_ci	.driver = {
153262306a36Sopenharmony_ci		   .name = "ad74413r",
153362306a36Sopenharmony_ci		   .of_match_table = ad74413r_dt_id,
153462306a36Sopenharmony_ci	},
153562306a36Sopenharmony_ci	.probe = ad74413r_probe,
153662306a36Sopenharmony_ci	.id_table = ad74413r_spi_id,
153762306a36Sopenharmony_ci};
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_cimodule_driver(ad74413r_driver,
154062306a36Sopenharmony_ci	      ad74413r_register_driver,
154162306a36Sopenharmony_ci	      ad74413r_unregister_driver);
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ciMODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
154462306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD74413R ADDAC");
154562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1546