xref: /openbmc/linux/drivers/iio/addac/ad74115.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1*48ea7559SCosmin Tanislav // SPDX-License-Identifier: GPL-2.0
2*48ea7559SCosmin Tanislav /*
3*48ea7559SCosmin Tanislav  * Copyright (C) 2022 Analog Devices, Inc.
4*48ea7559SCosmin Tanislav  * Author: Cosmin Tanislav <cosmin.tanislav@analog.com>
5*48ea7559SCosmin Tanislav  */
6*48ea7559SCosmin Tanislav 
7*48ea7559SCosmin Tanislav #include <linux/bitfield.h>
8*48ea7559SCosmin Tanislav #include <linux/bitops.h>
9*48ea7559SCosmin Tanislav #include <linux/crc8.h>
10*48ea7559SCosmin Tanislav #include <linux/device.h>
11*48ea7559SCosmin Tanislav #include <linux/gpio/driver.h>
12*48ea7559SCosmin Tanislav #include <linux/interrupt.h>
13*48ea7559SCosmin Tanislav #include <linux/module.h>
14*48ea7559SCosmin Tanislav #include <linux/regmap.h>
15*48ea7559SCosmin Tanislav #include <linux/regulator/consumer.h>
16*48ea7559SCosmin Tanislav #include <linux/spi/spi.h>
17*48ea7559SCosmin Tanislav #include <linux/units.h>
18*48ea7559SCosmin Tanislav 
19*48ea7559SCosmin Tanislav #include <asm/unaligned.h>
20*48ea7559SCosmin Tanislav 
21*48ea7559SCosmin Tanislav #include <linux/iio/buffer.h>
22*48ea7559SCosmin Tanislav #include <linux/iio/iio.h>
23*48ea7559SCosmin Tanislav #include <linux/iio/trigger.h>
24*48ea7559SCosmin Tanislav #include <linux/iio/trigger_consumer.h>
25*48ea7559SCosmin Tanislav #include <linux/iio/triggered_buffer.h>
26*48ea7559SCosmin Tanislav 
27*48ea7559SCosmin Tanislav #define AD74115_NAME				"ad74115"
28*48ea7559SCosmin Tanislav 
29*48ea7559SCosmin Tanislav #define AD74115_CH_FUNC_SETUP_REG		0x01
30*48ea7559SCosmin Tanislav 
31*48ea7559SCosmin Tanislav #define AD74115_ADC_CONFIG_REG			0x02
32*48ea7559SCosmin Tanislav #define AD74115_ADC_CONFIG_CONV2_RATE_MASK	GENMASK(15, 13)
33*48ea7559SCosmin Tanislav #define AD74115_ADC_CONFIG_CONV1_RATE_MASK	GENMASK(12, 10)
34*48ea7559SCosmin Tanislav #define AD74115_ADC_CONFIG_CONV2_RANGE_MASK	GENMASK(9, 7)
35*48ea7559SCosmin Tanislav #define AD74115_ADC_CONFIG_CONV1_RANGE_MASK	GENMASK(6, 4)
36*48ea7559SCosmin Tanislav 
37*48ea7559SCosmin Tanislav #define AD74115_PWR_OPTIM_CONFIG_REG		0x03
38*48ea7559SCosmin Tanislav 
39*48ea7559SCosmin Tanislav #define AD74115_DIN_CONFIG1_REG			0x04
40*48ea7559SCosmin Tanislav #define AD74115_DIN_COMPARATOR_EN_MASK		BIT(13)
41*48ea7559SCosmin Tanislav #define AD74115_DIN_SINK_MASK			GENMASK(11, 7)
42*48ea7559SCosmin Tanislav #define AD74115_DIN_DEBOUNCE_MASK		GENMASK(4, 0)
43*48ea7559SCosmin Tanislav 
44*48ea7559SCosmin Tanislav #define AD74115_DIN_CONFIG2_REG			0x05
45*48ea7559SCosmin Tanislav #define AD74115_COMP_THRESH_MASK		GENMASK(6, 0)
46*48ea7559SCosmin Tanislav 
47*48ea7559SCosmin Tanislav #define AD74115_OUTPUT_CONFIG_REG		0x06
48*48ea7559SCosmin Tanislav #define AD74115_OUTPUT_SLEW_EN_MASK		GENMASK(6, 5)
49*48ea7559SCosmin Tanislav #define AD74115_OUTPUT_SLEW_LIN_STEP_MASK	GENMASK(4, 3)
50*48ea7559SCosmin Tanislav #define AD74115_OUTPUT_SLEW_LIN_RATE_MASK	GENMASK(2, 1)
51*48ea7559SCosmin Tanislav 
52*48ea7559SCosmin Tanislav #define AD74115_RTD3W4W_CONFIG_REG		0x07
53*48ea7559SCosmin Tanislav 
54*48ea7559SCosmin Tanislav #define AD74115_BURNOUT_CONFIG_REG		0x0a
55*48ea7559SCosmin Tanislav #define AD74115_BURNOUT_EXT2_EN_MASK		BIT(10)
56*48ea7559SCosmin Tanislav #define AD74115_BURNOUT_EXT1_EN_MASK		BIT(5)
57*48ea7559SCosmin Tanislav #define AD74115_BURNOUT_VIOUT_EN_MASK		BIT(0)
58*48ea7559SCosmin Tanislav 
59*48ea7559SCosmin Tanislav #define AD74115_DAC_CODE_REG			0x0b
60*48ea7559SCosmin Tanislav 
61*48ea7559SCosmin Tanislav #define AD74115_DAC_ACTIVE_REG			0x0d
62*48ea7559SCosmin Tanislav 
63*48ea7559SCosmin Tanislav #define AD74115_GPIO_CONFIG_X_REG(x)		(0x35 + (x))
64*48ea7559SCosmin Tanislav #define AD74115_GPIO_CONFIG_GPI_DATA		BIT(5)
65*48ea7559SCosmin Tanislav #define AD74115_GPIO_CONFIG_GPO_DATA		BIT(4)
66*48ea7559SCosmin Tanislav #define AD74115_GPIO_CONFIG_SELECT_MASK		GENMASK(2, 0)
67*48ea7559SCosmin Tanislav 
68*48ea7559SCosmin Tanislav #define AD74115_CHARGE_PUMP_REG			0x3a
69*48ea7559SCosmin Tanislav 
70*48ea7559SCosmin Tanislav #define AD74115_ADC_CONV_CTRL_REG		0x3b
71*48ea7559SCosmin Tanislav #define AD74115_ADC_CONV_SEQ_MASK		GENMASK(13, 12)
72*48ea7559SCosmin Tanislav 
73*48ea7559SCosmin Tanislav #define AD74115_DIN_COMP_OUT_REG		0x40
74*48ea7559SCosmin Tanislav 
75*48ea7559SCosmin Tanislav #define AD74115_LIVE_STATUS_REG			0x42
76*48ea7559SCosmin Tanislav #define AD74115_ADC_DATA_RDY_MASK		BIT(3)
77*48ea7559SCosmin Tanislav 
78*48ea7559SCosmin Tanislav #define AD74115_READ_SELECT_REG			0x64
79*48ea7559SCosmin Tanislav 
80*48ea7559SCosmin Tanislav #define AD74115_CMD_KEY_REG			0x78
81*48ea7559SCosmin Tanislav #define AD74115_CMD_KEY_RESET1			0x15fa
82*48ea7559SCosmin Tanislav #define AD74115_CMD_KEY_RESET2			0xaf51
83*48ea7559SCosmin Tanislav 
84*48ea7559SCosmin Tanislav #define AD74115_CRC_POLYNOMIAL			0x7
85*48ea7559SCosmin Tanislav DECLARE_CRC8_TABLE(ad74115_crc8_table);
86*48ea7559SCosmin Tanislav 
87*48ea7559SCosmin Tanislav #define AD74115_ADC_CODE_MAX			((int)GENMASK(15, 0))
88*48ea7559SCosmin Tanislav #define AD74115_ADC_CODE_HALF			(AD74115_ADC_CODE_MAX / 2)
89*48ea7559SCosmin Tanislav 
90*48ea7559SCosmin Tanislav #define AD74115_DAC_VOLTAGE_MAX			12000
91*48ea7559SCosmin Tanislav #define AD74115_DAC_CURRENT_MAX			25
92*48ea7559SCosmin Tanislav #define AD74115_DAC_CODE_MAX			((int)GENMASK(13, 0))
93*48ea7559SCosmin Tanislav #define AD74115_DAC_CODE_HALF			(AD74115_DAC_CODE_MAX / 2)
94*48ea7559SCosmin Tanislav 
95*48ea7559SCosmin Tanislav #define AD74115_COMP_THRESH_MAX			98
96*48ea7559SCosmin Tanislav 
97*48ea7559SCosmin Tanislav #define AD74115_SENSE_RESISTOR_OHMS		100
98*48ea7559SCosmin Tanislav #define AD74115_REF_RESISTOR_OHMS		2100
99*48ea7559SCosmin Tanislav 
100*48ea7559SCosmin Tanislav #define AD74115_DIN_SINK_LOW_STEP		120
101*48ea7559SCosmin Tanislav #define AD74115_DIN_SINK_HIGH_STEP		240
102*48ea7559SCosmin Tanislav #define AD74115_DIN_SINK_MAX			31
103*48ea7559SCosmin Tanislav 
104*48ea7559SCosmin Tanislav #define AD74115_FRAME_SIZE			4
105*48ea7559SCosmin Tanislav #define AD74115_GPIO_NUM			4
106*48ea7559SCosmin Tanislav 
107*48ea7559SCosmin Tanislav #define AD74115_CONV_TIME_US			1000000
108*48ea7559SCosmin Tanislav 
109*48ea7559SCosmin Tanislav enum ad74115_dac_ch {
110*48ea7559SCosmin Tanislav 	AD74115_DAC_CH_MAIN,
111*48ea7559SCosmin Tanislav 	AD74115_DAC_CH_COMPARATOR,
112*48ea7559SCosmin Tanislav };
113*48ea7559SCosmin Tanislav 
114*48ea7559SCosmin Tanislav enum ad74115_adc_ch {
115*48ea7559SCosmin Tanislav 	AD74115_ADC_CH_CONV1,
116*48ea7559SCosmin Tanislav 	AD74115_ADC_CH_CONV2,
117*48ea7559SCosmin Tanislav 	AD74115_ADC_CH_NUM
118*48ea7559SCosmin Tanislav };
119*48ea7559SCosmin Tanislav 
120*48ea7559SCosmin Tanislav enum ad74115_ch_func {
121*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_HIGH_IMPEDANCE,
122*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_VOLTAGE_OUTPUT,
123*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_CURRENT_OUTPUT,
124*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_VOLTAGE_INPUT,
125*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER,
126*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER,
127*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_2_WIRE_RESISTANCE_INPUT,
128*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_3_4_WIRE_RESISTANCE_INPUT,
129*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_DIGITAL_INPUT_LOGIC,
130*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_DIGITAL_INPUT_LOOP_POWER,
131*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_CURRENT_OUTPUT_HART,
132*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER_HART,
133*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART,
134*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_MAX = AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART,
135*48ea7559SCosmin Tanislav 	AD74115_CH_FUNC_NUM
136*48ea7559SCosmin Tanislav };
137*48ea7559SCosmin Tanislav 
138*48ea7559SCosmin Tanislav enum ad74115_adc_range {
139*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_12V,
140*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_12V_BIPOLAR,
141*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_2_5V_BIPOLAR,
142*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_2_5V_NEG,
143*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_2_5V,
144*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_0_625V,
145*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_104MV_BIPOLAR,
146*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_12V_OTHER,
147*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_MAX = AD74115_ADC_RANGE_12V_OTHER,
148*48ea7559SCosmin Tanislav 	AD74115_ADC_RANGE_NUM
149*48ea7559SCosmin Tanislav };
150*48ea7559SCosmin Tanislav 
151*48ea7559SCosmin Tanislav enum ad74115_adc_conv_seq {
152*48ea7559SCosmin Tanislav 	AD74115_ADC_CONV_SEQ_STANDBY = 0b00,
153*48ea7559SCosmin Tanislav 	AD74115_ADC_CONV_SEQ_SINGLE = 0b01,
154*48ea7559SCosmin Tanislav 	AD74115_ADC_CONV_SEQ_CONTINUOUS = 0b10,
155*48ea7559SCosmin Tanislav };
156*48ea7559SCosmin Tanislav 
157*48ea7559SCosmin Tanislav enum ad74115_din_threshold_mode {
158*48ea7559SCosmin Tanislav 	AD74115_DIN_THRESHOLD_MODE_AVDD,
159*48ea7559SCosmin Tanislav 	AD74115_DIN_THRESHOLD_MODE_FIXED,
160*48ea7559SCosmin Tanislav 	AD74115_DIN_THRESHOLD_MODE_MAX = AD74115_DIN_THRESHOLD_MODE_FIXED,
161*48ea7559SCosmin Tanislav };
162*48ea7559SCosmin Tanislav 
163*48ea7559SCosmin Tanislav enum ad74115_slew_mode {
164*48ea7559SCosmin Tanislav 	AD74115_SLEW_MODE_DISABLED,
165*48ea7559SCosmin Tanislav 	AD74115_SLEW_MODE_LINEAR,
166*48ea7559SCosmin Tanislav 	AD74115_SLEW_MODE_HART,
167*48ea7559SCosmin Tanislav };
168*48ea7559SCosmin Tanislav 
169*48ea7559SCosmin Tanislav enum ad74115_slew_step {
170*48ea7559SCosmin Tanislav 	AD74115_SLEW_STEP_0_8_PERCENT,
171*48ea7559SCosmin Tanislav 	AD74115_SLEW_STEP_1_5_PERCENT,
172*48ea7559SCosmin Tanislav 	AD74115_SLEW_STEP_6_1_PERCENT,
173*48ea7559SCosmin Tanislav 	AD74115_SLEW_STEP_22_2_PERCENT,
174*48ea7559SCosmin Tanislav };
175*48ea7559SCosmin Tanislav 
176*48ea7559SCosmin Tanislav enum ad74115_slew_rate {
177*48ea7559SCosmin Tanislav 	AD74115_SLEW_RATE_4KHZ,
178*48ea7559SCosmin Tanislav 	AD74115_SLEW_RATE_64KHZ,
179*48ea7559SCosmin Tanislav 	AD74115_SLEW_RATE_150KHZ,
180*48ea7559SCosmin Tanislav 	AD74115_SLEW_RATE_240KHZ,
181*48ea7559SCosmin Tanislav };
182*48ea7559SCosmin Tanislav 
183*48ea7559SCosmin Tanislav enum ad74115_gpio_config {
184*48ea7559SCosmin Tanislav 	AD74115_GPIO_CONFIG_OUTPUT_BUFFERED = 0b010,
185*48ea7559SCosmin Tanislav 	AD74115_GPIO_CONFIG_INPUT = 0b011,
186*48ea7559SCosmin Tanislav };
187*48ea7559SCosmin Tanislav 
188*48ea7559SCosmin Tanislav enum ad74115_gpio_mode {
189*48ea7559SCosmin Tanislav 	AD74115_GPIO_MODE_LOGIC = 1,
190*48ea7559SCosmin Tanislav 	AD74115_GPIO_MODE_SPECIAL = 2,
191*48ea7559SCosmin Tanislav };
192*48ea7559SCosmin Tanislav 
193*48ea7559SCosmin Tanislav struct ad74115_channels {
194*48ea7559SCosmin Tanislav 	struct iio_chan_spec		*channels;
195*48ea7559SCosmin Tanislav 	unsigned int			num_channels;
196*48ea7559SCosmin Tanislav };
197*48ea7559SCosmin Tanislav 
198*48ea7559SCosmin Tanislav struct ad74115_state {
199*48ea7559SCosmin Tanislav 	struct spi_device		*spi;
200*48ea7559SCosmin Tanislav 	struct regmap			*regmap;
201*48ea7559SCosmin Tanislav 	struct iio_trigger		*trig;
202*48ea7559SCosmin Tanislav 	struct regulator		*avdd;
203*48ea7559SCosmin Tanislav 
204*48ea7559SCosmin Tanislav 	/*
205*48ea7559SCosmin Tanislav 	 * Synchronize consecutive operations when doing a one-shot
206*48ea7559SCosmin Tanislav 	 * conversion and when updating the ADC samples SPI message.
207*48ea7559SCosmin Tanislav 	 */
208*48ea7559SCosmin Tanislav 	struct mutex			lock;
209*48ea7559SCosmin Tanislav 	struct gpio_chip		gc;
210*48ea7559SCosmin Tanislav 	struct gpio_chip		comp_gc;
211*48ea7559SCosmin Tanislav 	int				irq;
212*48ea7559SCosmin Tanislav 
213*48ea7559SCosmin Tanislav 	unsigned int			avdd_mv;
214*48ea7559SCosmin Tanislav 	unsigned long			gpio_valid_mask;
215*48ea7559SCosmin Tanislav 	bool				dac_bipolar;
216*48ea7559SCosmin Tanislav 	bool				dac_hart_slew;
217*48ea7559SCosmin Tanislav 	bool				rtd_mode_4_wire;
218*48ea7559SCosmin Tanislav 	enum ad74115_ch_func		ch_func;
219*48ea7559SCosmin Tanislav 	enum ad74115_din_threshold_mode	din_threshold_mode;
220*48ea7559SCosmin Tanislav 
221*48ea7559SCosmin Tanislav 	struct completion		adc_data_completion;
222*48ea7559SCosmin Tanislav 	struct spi_message		adc_samples_msg;
223*48ea7559SCosmin Tanislav 	struct spi_transfer		adc_samples_xfer[AD74115_ADC_CH_NUM + 1];
224*48ea7559SCosmin Tanislav 
225*48ea7559SCosmin Tanislav 	/*
226*48ea7559SCosmin Tanislav 	 * DMA (thus cache coherency maintenance) requires the
227*48ea7559SCosmin Tanislav 	 * transfer buffers to live in their own cache lines.
228*48ea7559SCosmin Tanislav 	 */
229*48ea7559SCosmin Tanislav 	u8				reg_tx_buf[AD74115_FRAME_SIZE] __aligned(IIO_DMA_MINALIGN);
230*48ea7559SCosmin Tanislav 	u8				reg_rx_buf[AD74115_FRAME_SIZE];
231*48ea7559SCosmin Tanislav 	u8				adc_samples_tx_buf[AD74115_FRAME_SIZE * AD74115_ADC_CH_NUM];
232*48ea7559SCosmin Tanislav 	u8				adc_samples_rx_buf[AD74115_FRAME_SIZE * AD74115_ADC_CH_NUM];
233*48ea7559SCosmin Tanislav };
234*48ea7559SCosmin Tanislav 
235*48ea7559SCosmin Tanislav struct ad74115_fw_prop {
236*48ea7559SCosmin Tanislav 	const char			*name;
237*48ea7559SCosmin Tanislav 	bool				is_boolean;
238*48ea7559SCosmin Tanislav 	bool				negate;
239*48ea7559SCosmin Tanislav 	unsigned int			max;
240*48ea7559SCosmin Tanislav 	unsigned int			reg;
241*48ea7559SCosmin Tanislav 	unsigned int			mask;
242*48ea7559SCosmin Tanislav 	const unsigned int		*lookup_tbl;
243*48ea7559SCosmin Tanislav 	unsigned int			lookup_tbl_len;
244*48ea7559SCosmin Tanislav };
245*48ea7559SCosmin Tanislav 
246*48ea7559SCosmin Tanislav #define AD74115_FW_PROP(_name, _max, _reg, _mask)		\
247*48ea7559SCosmin Tanislav {								\
248*48ea7559SCosmin Tanislav 	.name = (_name),					\
249*48ea7559SCosmin Tanislav 	.max = (_max),						\
250*48ea7559SCosmin Tanislav 	.reg = (_reg),						\
251*48ea7559SCosmin Tanislav 	.mask = (_mask),					\
252*48ea7559SCosmin Tanislav }
253*48ea7559SCosmin Tanislav 
254*48ea7559SCosmin Tanislav #define AD74115_FW_PROP_TBL(_name, _tbl, _reg, _mask)		\
255*48ea7559SCosmin Tanislav {								\
256*48ea7559SCosmin Tanislav 	.name = (_name),					\
257*48ea7559SCosmin Tanislav 	.reg = (_reg),						\
258*48ea7559SCosmin Tanislav 	.mask = (_mask),					\
259*48ea7559SCosmin Tanislav 	.lookup_tbl = (_tbl),					\
260*48ea7559SCosmin Tanislav 	.lookup_tbl_len = ARRAY_SIZE(_tbl),			\
261*48ea7559SCosmin Tanislav }
262*48ea7559SCosmin Tanislav 
263*48ea7559SCosmin Tanislav #define AD74115_FW_PROP_BOOL(_name, _reg, _mask)		\
264*48ea7559SCosmin Tanislav {								\
265*48ea7559SCosmin Tanislav 	.name = (_name),					\
266*48ea7559SCosmin Tanislav 	.is_boolean = true,					\
267*48ea7559SCosmin Tanislav 	.reg = (_reg),						\
268*48ea7559SCosmin Tanislav 	.mask = (_mask),					\
269*48ea7559SCosmin Tanislav }
270*48ea7559SCosmin Tanislav 
271*48ea7559SCosmin Tanislav #define AD74115_FW_PROP_BOOL_NEG(_name, _reg, _mask)		\
272*48ea7559SCosmin Tanislav {								\
273*48ea7559SCosmin Tanislav 	.name = (_name),					\
274*48ea7559SCosmin Tanislav 	.is_boolean = true,					\
275*48ea7559SCosmin Tanislav 	.negate = true,						\
276*48ea7559SCosmin Tanislav 	.reg = (_reg),						\
277*48ea7559SCosmin Tanislav 	.mask = (_mask),					\
278*48ea7559SCosmin Tanislav }
279*48ea7559SCosmin Tanislav 
280*48ea7559SCosmin Tanislav static const int ad74115_dac_rate_tbl[] = {
281*48ea7559SCosmin Tanislav 	0,
282*48ea7559SCosmin Tanislav 	4 * 8,
283*48ea7559SCosmin Tanislav 	4 * 15,
284*48ea7559SCosmin Tanislav 	4 * 61,
285*48ea7559SCosmin Tanislav 	4 * 222,
286*48ea7559SCosmin Tanislav 	64 * 8,
287*48ea7559SCosmin Tanislav 	64 * 15,
288*48ea7559SCosmin Tanislav 	64 * 61,
289*48ea7559SCosmin Tanislav 	64 * 222,
290*48ea7559SCosmin Tanislav 	150 * 8,
291*48ea7559SCosmin Tanislav 	150 * 15,
292*48ea7559SCosmin Tanislav 	150 * 61,
293*48ea7559SCosmin Tanislav 	150 * 222,
294*48ea7559SCosmin Tanislav 	240 * 8,
295*48ea7559SCosmin Tanislav 	240 * 15,
296*48ea7559SCosmin Tanislav 	240 * 61,
297*48ea7559SCosmin Tanislav 	240 * 222,
298*48ea7559SCosmin Tanislav };
299*48ea7559SCosmin Tanislav 
300*48ea7559SCosmin Tanislav static const unsigned int ad74115_dac_rate_step_tbl[][3] = {
301*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_DISABLED },
302*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_4KHZ },
303*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_4KHZ },
304*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_4KHZ },
305*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_4KHZ },
306*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_64KHZ },
307*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_64KHZ },
308*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_64KHZ },
309*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_64KHZ },
310*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_150KHZ },
311*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_150KHZ },
312*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_150KHZ },
313*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_150KHZ },
314*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_0_8_PERCENT, AD74115_SLEW_RATE_240KHZ },
315*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_1_5_PERCENT, AD74115_SLEW_RATE_240KHZ },
316*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_6_1_PERCENT, AD74115_SLEW_RATE_240KHZ },
317*48ea7559SCosmin Tanislav 	{ AD74115_SLEW_MODE_LINEAR, AD74115_SLEW_STEP_22_2_PERCENT, AD74115_SLEW_RATE_240KHZ },
318*48ea7559SCosmin Tanislav };
319*48ea7559SCosmin Tanislav 
320*48ea7559SCosmin Tanislav static const unsigned int ad74115_rtd_excitation_current_ua_tbl[] = {
321*48ea7559SCosmin Tanislav 	250, 500, 750, 1000
322*48ea7559SCosmin Tanislav };
323*48ea7559SCosmin Tanislav 
324*48ea7559SCosmin Tanislav static const unsigned int ad74115_burnout_current_na_tbl[] = {
325*48ea7559SCosmin Tanislav 	0, 50, 0, 500, 1000, 0, 10000, 0
326*48ea7559SCosmin Tanislav };
327*48ea7559SCosmin Tanislav 
328*48ea7559SCosmin Tanislav static const unsigned int ad74115_viout_burnout_current_na_tbl[] = {
329*48ea7559SCosmin Tanislav 	0, 0, 0, 0, 1000, 0, 10000, 0
330*48ea7559SCosmin Tanislav };
331*48ea7559SCosmin Tanislav 
332*48ea7559SCosmin Tanislav static const unsigned int ad74115_gpio_mode_tbl[] = {
333*48ea7559SCosmin Tanislav 	0, 0, 0, 1, 2, 3, 4, 5
334*48ea7559SCosmin Tanislav };
335*48ea7559SCosmin Tanislav 
336*48ea7559SCosmin Tanislav static const unsigned int ad74115_adc_conv_rate_tbl[] = {
337*48ea7559SCosmin Tanislav 	10, 20, 1200, 4800, 9600
338*48ea7559SCosmin Tanislav };
339*48ea7559SCosmin Tanislav 
340*48ea7559SCosmin Tanislav static const unsigned int ad74115_debounce_tbl[] = {
341*48ea7559SCosmin Tanislav 	0,     13,    18,    24,    32,    42,    56,    75,
342*48ea7559SCosmin Tanislav 	100,   130,   180,   240,   320,   420,   560,   750,
343*48ea7559SCosmin Tanislav 	1000,  1300,  1800,  2400,  3200,  4200,  5600,  7500,
344*48ea7559SCosmin Tanislav 	10000, 13000, 18000, 24000, 32000, 42000, 56000, 75000,
345*48ea7559SCosmin Tanislav };
346*48ea7559SCosmin Tanislav 
347*48ea7559SCosmin Tanislav static const unsigned int ad74115_adc_ch_data_regs_tbl[] = {
348*48ea7559SCosmin Tanislav 	[AD74115_ADC_CH_CONV1] = 0x44,
349*48ea7559SCosmin Tanislav 	[AD74115_ADC_CH_CONV2] = 0x46,
350*48ea7559SCosmin Tanislav };
351*48ea7559SCosmin Tanislav 
352*48ea7559SCosmin Tanislav static const unsigned int ad74115_adc_ch_en_bit_tbl[] = {
353*48ea7559SCosmin Tanislav 	[AD74115_ADC_CH_CONV1] = BIT(0),
354*48ea7559SCosmin Tanislav 	[AD74115_ADC_CH_CONV2] = BIT(1),
355*48ea7559SCosmin Tanislav };
356*48ea7559SCosmin Tanislav 
357*48ea7559SCosmin Tanislav static const bool ad74115_adc_bipolar_tbl[AD74115_ADC_RANGE_NUM] = {
358*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V_BIPOLAR]		= true,
359*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= true,
360*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= true,
361*48ea7559SCosmin Tanislav };
362*48ea7559SCosmin Tanislav 
363*48ea7559SCosmin Tanislav static const unsigned int ad74115_adc_conv_mul_tbl[AD74115_ADC_RANGE_NUM] = {
364*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V]			= 12000,
365*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V_BIPOLAR]		= 24000,
366*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= 5000,
367*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V_NEG]		= 2500,
368*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V]		= 2500,
369*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_0_625V]		= 625,
370*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= 208,
371*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V_OTHER]		= 12000,
372*48ea7559SCosmin Tanislav };
373*48ea7559SCosmin Tanislav 
374*48ea7559SCosmin Tanislav static const unsigned int ad74115_adc_gain_tbl[AD74115_ADC_RANGE_NUM][2] = {
375*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V]			= { 5, 24 },
376*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V_BIPOLAR]		= { 5, 24 },
377*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= { 1, 1 },
378*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V_NEG]		= { 1, 1 },
379*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V]		= { 1, 1 },
380*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_0_625V]		= { 4, 1 },
381*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= { 24, 1 },
382*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V_OTHER]		= { 5, 24 },
383*48ea7559SCosmin Tanislav };
384*48ea7559SCosmin Tanislav 
385*48ea7559SCosmin Tanislav static const int ad74115_adc_range_tbl[AD74115_ADC_RANGE_NUM][2] = {
386*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V]			= { 0,         12000000 },
387*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V_BIPOLAR]		= { -12000000, 12000000 },
388*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V_BIPOLAR]	= { -2500000,  2500000 },
389*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V_NEG]		= { -2500000,  0 },
390*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_2_5V]		= { 0,         2500000 },
391*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_0_625V]		= { 0,         625000 },
392*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_104MV_BIPOLAR]	= { -104000,   104000 },
393*48ea7559SCosmin Tanislav 	[AD74115_ADC_RANGE_12V_OTHER]		= { 0,         12000000 },
394*48ea7559SCosmin Tanislav };
395*48ea7559SCosmin Tanislav 
_ad74115_find_tbl_index(const unsigned int * tbl,unsigned int tbl_len,unsigned int val,unsigned int * index)396*48ea7559SCosmin Tanislav static int _ad74115_find_tbl_index(const unsigned int *tbl, unsigned int tbl_len,
397*48ea7559SCosmin Tanislav 				   unsigned int val, unsigned int *index)
398*48ea7559SCosmin Tanislav {
399*48ea7559SCosmin Tanislav 	unsigned int i;
400*48ea7559SCosmin Tanislav 
401*48ea7559SCosmin Tanislav 	for (i = 0; i < tbl_len; i++)
402*48ea7559SCosmin Tanislav 		if (val == tbl[i]) {
403*48ea7559SCosmin Tanislav 			*index = i;
404*48ea7559SCosmin Tanislav 			return 0;
405*48ea7559SCosmin Tanislav 		}
406*48ea7559SCosmin Tanislav 
407*48ea7559SCosmin Tanislav 	return -EINVAL;
408*48ea7559SCosmin Tanislav }
409*48ea7559SCosmin Tanislav 
410*48ea7559SCosmin Tanislav #define ad74115_find_tbl_index(tbl, val, index)	\
411*48ea7559SCosmin Tanislav 	_ad74115_find_tbl_index(tbl, ARRAY_SIZE(tbl), val, index)
412*48ea7559SCosmin Tanislav 
ad74115_crc(u8 * buf)413*48ea7559SCosmin Tanislav static int ad74115_crc(u8 *buf)
414*48ea7559SCosmin Tanislav {
415*48ea7559SCosmin Tanislav 	return crc8(ad74115_crc8_table, buf, 3, 0);
416*48ea7559SCosmin Tanislav }
417*48ea7559SCosmin Tanislav 
ad74115_format_reg_write(u8 reg,u16 val,u8 * buf)418*48ea7559SCosmin Tanislav static void ad74115_format_reg_write(u8 reg, u16 val, u8 *buf)
419*48ea7559SCosmin Tanislav {
420*48ea7559SCosmin Tanislav 	buf[0] = reg;
421*48ea7559SCosmin Tanislav 	put_unaligned_be16(val, &buf[1]);
422*48ea7559SCosmin Tanislav 	buf[3] = ad74115_crc(buf);
423*48ea7559SCosmin Tanislav }
424*48ea7559SCosmin Tanislav 
ad74115_reg_write(void * context,unsigned int reg,unsigned int val)425*48ea7559SCosmin Tanislav static int ad74115_reg_write(void *context, unsigned int reg, unsigned int val)
426*48ea7559SCosmin Tanislav {
427*48ea7559SCosmin Tanislav 	struct ad74115_state *st = context;
428*48ea7559SCosmin Tanislav 
429*48ea7559SCosmin Tanislav 	ad74115_format_reg_write(reg, val, st->reg_tx_buf);
430*48ea7559SCosmin Tanislav 
431*48ea7559SCosmin Tanislav 	return spi_write(st->spi, st->reg_tx_buf, AD74115_FRAME_SIZE);
432*48ea7559SCosmin Tanislav }
433*48ea7559SCosmin Tanislav 
ad74115_crc_check(struct ad74115_state * st,u8 * buf)434*48ea7559SCosmin Tanislav static int ad74115_crc_check(struct ad74115_state *st, u8 *buf)
435*48ea7559SCosmin Tanislav {
436*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
437*48ea7559SCosmin Tanislav 	u8 expected_crc = ad74115_crc(buf);
438*48ea7559SCosmin Tanislav 
439*48ea7559SCosmin Tanislav 	if (buf[3] != expected_crc) {
440*48ea7559SCosmin Tanislav 		dev_err(dev, "Bad CRC %02x for %02x%02x%02x, expected %02x\n",
441*48ea7559SCosmin Tanislav 			buf[3], buf[0], buf[1], buf[2], expected_crc);
442*48ea7559SCosmin Tanislav 		return -EINVAL;
443*48ea7559SCosmin Tanislav 	}
444*48ea7559SCosmin Tanislav 
445*48ea7559SCosmin Tanislav 	return 0;
446*48ea7559SCosmin Tanislav }
447*48ea7559SCosmin Tanislav 
ad74115_reg_read(void * context,unsigned int reg,unsigned int * val)448*48ea7559SCosmin Tanislav static int ad74115_reg_read(void *context, unsigned int reg, unsigned int *val)
449*48ea7559SCosmin Tanislav {
450*48ea7559SCosmin Tanislav 	struct ad74115_state *st = context;
451*48ea7559SCosmin Tanislav 	struct spi_transfer reg_read_xfer[] = {
452*48ea7559SCosmin Tanislav 		{
453*48ea7559SCosmin Tanislav 			.tx_buf = st->reg_tx_buf,
454*48ea7559SCosmin Tanislav 			.len = sizeof(st->reg_tx_buf),
455*48ea7559SCosmin Tanislav 			.cs_change = 1,
456*48ea7559SCosmin Tanislav 		},
457*48ea7559SCosmin Tanislav 		{
458*48ea7559SCosmin Tanislav 			.rx_buf = st->reg_rx_buf,
459*48ea7559SCosmin Tanislav 			.len = sizeof(st->reg_rx_buf),
460*48ea7559SCosmin Tanislav 		},
461*48ea7559SCosmin Tanislav 	};
462*48ea7559SCosmin Tanislav 	int ret;
463*48ea7559SCosmin Tanislav 
464*48ea7559SCosmin Tanislav 	ad74115_format_reg_write(AD74115_READ_SELECT_REG, reg, st->reg_tx_buf);
465*48ea7559SCosmin Tanislav 
466*48ea7559SCosmin Tanislav 	ret = spi_sync_transfer(st->spi, reg_read_xfer, ARRAY_SIZE(reg_read_xfer));
467*48ea7559SCosmin Tanislav 	if (ret)
468*48ea7559SCosmin Tanislav 		return ret;
469*48ea7559SCosmin Tanislav 
470*48ea7559SCosmin Tanislav 	ret = ad74115_crc_check(st, st->reg_rx_buf);
471*48ea7559SCosmin Tanislav 	if (ret)
472*48ea7559SCosmin Tanislav 		return ret;
473*48ea7559SCosmin Tanislav 
474*48ea7559SCosmin Tanislav 	*val = get_unaligned_be16(&st->reg_rx_buf[1]);
475*48ea7559SCosmin Tanislav 
476*48ea7559SCosmin Tanislav 	return 0;
477*48ea7559SCosmin Tanislav }
478*48ea7559SCosmin Tanislav 
479*48ea7559SCosmin Tanislav static const struct regmap_config ad74115_regmap_config = {
480*48ea7559SCosmin Tanislav 	.reg_bits = 8,
481*48ea7559SCosmin Tanislav 	.val_bits = 16,
482*48ea7559SCosmin Tanislav 	.reg_read = ad74115_reg_read,
483*48ea7559SCosmin Tanislav 	.reg_write = ad74115_reg_write,
484*48ea7559SCosmin Tanislav };
485*48ea7559SCosmin Tanislav 
ad74115_gpio_config_set(struct ad74115_state * st,unsigned int offset,enum ad74115_gpio_config cfg)486*48ea7559SCosmin Tanislav static int ad74115_gpio_config_set(struct ad74115_state *st, unsigned int offset,
487*48ea7559SCosmin Tanislav 				   enum ad74115_gpio_config cfg)
488*48ea7559SCosmin Tanislav {
489*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset),
490*48ea7559SCosmin Tanislav 				  AD74115_GPIO_CONFIG_SELECT_MASK,
491*48ea7559SCosmin Tanislav 				  FIELD_PREP(AD74115_GPIO_CONFIG_SELECT_MASK, cfg));
492*48ea7559SCosmin Tanislav }
493*48ea7559SCosmin Tanislav 
ad74115_gpio_init_valid_mask(struct gpio_chip * gc,unsigned long * valid_mask,unsigned int ngpios)494*48ea7559SCosmin Tanislav static int ad74115_gpio_init_valid_mask(struct gpio_chip *gc,
495*48ea7559SCosmin Tanislav 					unsigned long *valid_mask,
496*48ea7559SCosmin Tanislav 					unsigned int ngpios)
497*48ea7559SCosmin Tanislav {
498*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(gc);
499*48ea7559SCosmin Tanislav 
500*48ea7559SCosmin Tanislav 	*valid_mask = st->gpio_valid_mask;
501*48ea7559SCosmin Tanislav 
502*48ea7559SCosmin Tanislav 	return 0;
503*48ea7559SCosmin Tanislav }
504*48ea7559SCosmin Tanislav 
ad74115_gpio_get_direction(struct gpio_chip * gc,unsigned int offset)505*48ea7559SCosmin Tanislav static int ad74115_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
506*48ea7559SCosmin Tanislav {
507*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(gc);
508*48ea7559SCosmin Tanislav 	unsigned int val;
509*48ea7559SCosmin Tanislav 	int ret;
510*48ea7559SCosmin Tanislav 
511*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), &val);
512*48ea7559SCosmin Tanislav 	if (ret)
513*48ea7559SCosmin Tanislav 		return ret;
514*48ea7559SCosmin Tanislav 
515*48ea7559SCosmin Tanislav 	return FIELD_GET(AD74115_GPIO_CONFIG_SELECT_MASK, val) == AD74115_GPIO_CONFIG_INPUT;
516*48ea7559SCosmin Tanislav }
517*48ea7559SCosmin Tanislav 
ad74115_gpio_direction_input(struct gpio_chip * gc,unsigned int offset)518*48ea7559SCosmin Tanislav static int ad74115_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
519*48ea7559SCosmin Tanislav {
520*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(gc);
521*48ea7559SCosmin Tanislav 
522*48ea7559SCosmin Tanislav 	return ad74115_gpio_config_set(st, offset, AD74115_GPIO_CONFIG_INPUT);
523*48ea7559SCosmin Tanislav }
524*48ea7559SCosmin Tanislav 
ad74115_gpio_direction_output(struct gpio_chip * gc,unsigned int offset,int value)525*48ea7559SCosmin Tanislav static int ad74115_gpio_direction_output(struct gpio_chip *gc, unsigned int offset,
526*48ea7559SCosmin Tanislav 					 int value)
527*48ea7559SCosmin Tanislav {
528*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(gc);
529*48ea7559SCosmin Tanislav 
530*48ea7559SCosmin Tanislav 	return ad74115_gpio_config_set(st, offset, AD74115_GPIO_CONFIG_OUTPUT_BUFFERED);
531*48ea7559SCosmin Tanislav }
532*48ea7559SCosmin Tanislav 
ad74115_gpio_get(struct gpio_chip * gc,unsigned int offset)533*48ea7559SCosmin Tanislav static int ad74115_gpio_get(struct gpio_chip *gc, unsigned int offset)
534*48ea7559SCosmin Tanislav {
535*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(gc);
536*48ea7559SCosmin Tanislav 	unsigned int val;
537*48ea7559SCosmin Tanislav 	int ret;
538*48ea7559SCosmin Tanislav 
539*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), &val);
540*48ea7559SCosmin Tanislav 	if (ret)
541*48ea7559SCosmin Tanislav 		return ret;
542*48ea7559SCosmin Tanislav 
543*48ea7559SCosmin Tanislav 	return FIELD_GET(AD74115_GPIO_CONFIG_GPI_DATA, val);
544*48ea7559SCosmin Tanislav }
545*48ea7559SCosmin Tanislav 
ad74115_gpio_set(struct gpio_chip * gc,unsigned int offset,int value)546*48ea7559SCosmin Tanislav static void ad74115_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
547*48ea7559SCosmin Tanislav {
548*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(gc);
549*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
550*48ea7559SCosmin Tanislav 	int ret;
551*48ea7559SCosmin Tanislav 
552*48ea7559SCosmin Tanislav 	ret = regmap_update_bits(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset),
553*48ea7559SCosmin Tanislav 				 AD74115_GPIO_CONFIG_GPO_DATA,
554*48ea7559SCosmin Tanislav 				 FIELD_PREP(AD74115_GPIO_CONFIG_GPO_DATA, value));
555*48ea7559SCosmin Tanislav 	if (ret)
556*48ea7559SCosmin Tanislav 		dev_err(dev, "Failed to set GPIO %u output value, err: %d\n",
557*48ea7559SCosmin Tanislav 			offset, ret);
558*48ea7559SCosmin Tanislav }
559*48ea7559SCosmin Tanislav 
ad74115_set_comp_debounce(struct ad74115_state * st,unsigned int val)560*48ea7559SCosmin Tanislav static int ad74115_set_comp_debounce(struct ad74115_state *st, unsigned int val)
561*48ea7559SCosmin Tanislav {
562*48ea7559SCosmin Tanislav 	unsigned int len = ARRAY_SIZE(ad74115_debounce_tbl);
563*48ea7559SCosmin Tanislav 	unsigned int i;
564*48ea7559SCosmin Tanislav 
565*48ea7559SCosmin Tanislav 	for (i = 0; i < len; i++)
566*48ea7559SCosmin Tanislav 		if (val <= ad74115_debounce_tbl[i])
567*48ea7559SCosmin Tanislav 			break;
568*48ea7559SCosmin Tanislav 
569*48ea7559SCosmin Tanislav 	if (i == len)
570*48ea7559SCosmin Tanislav 		i = len - 1;
571*48ea7559SCosmin Tanislav 
572*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, AD74115_DIN_CONFIG1_REG,
573*48ea7559SCosmin Tanislav 				  AD74115_DIN_DEBOUNCE_MASK,
574*48ea7559SCosmin Tanislav 				  FIELD_PREP(AD74115_DIN_DEBOUNCE_MASK, val));
575*48ea7559SCosmin Tanislav }
576*48ea7559SCosmin Tanislav 
ad74115_comp_gpio_get_direction(struct gpio_chip * chip,unsigned int offset)577*48ea7559SCosmin Tanislav static int ad74115_comp_gpio_get_direction(struct gpio_chip *chip,
578*48ea7559SCosmin Tanislav 					   unsigned int offset)
579*48ea7559SCosmin Tanislav {
580*48ea7559SCosmin Tanislav 	return GPIO_LINE_DIRECTION_IN;
581*48ea7559SCosmin Tanislav }
582*48ea7559SCosmin Tanislav 
ad74115_comp_gpio_set_config(struct gpio_chip * chip,unsigned int offset,unsigned long config)583*48ea7559SCosmin Tanislav static int ad74115_comp_gpio_set_config(struct gpio_chip *chip,
584*48ea7559SCosmin Tanislav 					unsigned int offset,
585*48ea7559SCosmin Tanislav 					unsigned long config)
586*48ea7559SCosmin Tanislav {
587*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(chip);
588*48ea7559SCosmin Tanislav 	u32 param = pinconf_to_config_param(config);
589*48ea7559SCosmin Tanislav 	u32 arg = pinconf_to_config_argument(config);
590*48ea7559SCosmin Tanislav 
591*48ea7559SCosmin Tanislav 	switch (param) {
592*48ea7559SCosmin Tanislav 	case PIN_CONFIG_INPUT_DEBOUNCE:
593*48ea7559SCosmin Tanislav 		return ad74115_set_comp_debounce(st, arg);
594*48ea7559SCosmin Tanislav 	default:
595*48ea7559SCosmin Tanislav 		return -ENOTSUPP;
596*48ea7559SCosmin Tanislav 	}
597*48ea7559SCosmin Tanislav }
598*48ea7559SCosmin Tanislav 
ad74115_comp_gpio_get(struct gpio_chip * chip,unsigned int offset)599*48ea7559SCosmin Tanislav static int ad74115_comp_gpio_get(struct gpio_chip *chip, unsigned int offset)
600*48ea7559SCosmin Tanislav {
601*48ea7559SCosmin Tanislav 	struct ad74115_state *st = gpiochip_get_data(chip);
602*48ea7559SCosmin Tanislav 	unsigned int val;
603*48ea7559SCosmin Tanislav 	int ret;
604*48ea7559SCosmin Tanislav 
605*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_DIN_COMP_OUT_REG, &val);
606*48ea7559SCosmin Tanislav 	if (ret)
607*48ea7559SCosmin Tanislav 		return ret;
608*48ea7559SCosmin Tanislav 
609*48ea7559SCosmin Tanislav 	return !!val;
610*48ea7559SCosmin Tanislav }
611*48ea7559SCosmin Tanislav 
ad74115_trigger_handler(int irq,void * p)612*48ea7559SCosmin Tanislav static irqreturn_t ad74115_trigger_handler(int irq, void *p)
613*48ea7559SCosmin Tanislav {
614*48ea7559SCosmin Tanislav 	struct iio_poll_func *pf = p;
615*48ea7559SCosmin Tanislav 	struct iio_dev *indio_dev = pf->indio_dev;
616*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
617*48ea7559SCosmin Tanislav 	int ret;
618*48ea7559SCosmin Tanislav 
619*48ea7559SCosmin Tanislav 	ret = spi_sync(st->spi, &st->adc_samples_msg);
620*48ea7559SCosmin Tanislav 	if (ret)
621*48ea7559SCosmin Tanislav 		goto out;
622*48ea7559SCosmin Tanislav 
623*48ea7559SCosmin Tanislav 	iio_push_to_buffers(indio_dev, st->adc_samples_rx_buf);
624*48ea7559SCosmin Tanislav 
625*48ea7559SCosmin Tanislav out:
626*48ea7559SCosmin Tanislav 	iio_trigger_notify_done(indio_dev->trig);
627*48ea7559SCosmin Tanislav 
628*48ea7559SCosmin Tanislav 	return IRQ_HANDLED;
629*48ea7559SCosmin Tanislav }
630*48ea7559SCosmin Tanislav 
ad74115_adc_data_interrupt(int irq,void * data)631*48ea7559SCosmin Tanislav static irqreturn_t ad74115_adc_data_interrupt(int irq, void *data)
632*48ea7559SCosmin Tanislav {
633*48ea7559SCosmin Tanislav 	struct iio_dev *indio_dev = data;
634*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
635*48ea7559SCosmin Tanislav 
636*48ea7559SCosmin Tanislav 	if (iio_buffer_enabled(indio_dev))
637*48ea7559SCosmin Tanislav 		iio_trigger_poll(st->trig);
638*48ea7559SCosmin Tanislav 	else
639*48ea7559SCosmin Tanislav 		complete(&st->adc_data_completion);
640*48ea7559SCosmin Tanislav 
641*48ea7559SCosmin Tanislav 	return IRQ_HANDLED;
642*48ea7559SCosmin Tanislav }
643*48ea7559SCosmin Tanislav 
ad74115_set_adc_ch_en(struct ad74115_state * st,enum ad74115_adc_ch channel,bool status)644*48ea7559SCosmin Tanislav static int ad74115_set_adc_ch_en(struct ad74115_state *st,
645*48ea7559SCosmin Tanislav 				 enum ad74115_adc_ch channel, bool status)
646*48ea7559SCosmin Tanislav {
647*48ea7559SCosmin Tanislav 	unsigned int mask = ad74115_adc_ch_en_bit_tbl[channel];
648*48ea7559SCosmin Tanislav 
649*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, AD74115_ADC_CONV_CTRL_REG, mask,
650*48ea7559SCosmin Tanislav 				  status ? mask : 0);
651*48ea7559SCosmin Tanislav }
652*48ea7559SCosmin Tanislav 
ad74115_set_adc_conv_seq(struct ad74115_state * st,enum ad74115_adc_conv_seq conv_seq)653*48ea7559SCosmin Tanislav static int ad74115_set_adc_conv_seq(struct ad74115_state *st,
654*48ea7559SCosmin Tanislav 				    enum ad74115_adc_conv_seq conv_seq)
655*48ea7559SCosmin Tanislav {
656*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, AD74115_ADC_CONV_CTRL_REG,
657*48ea7559SCosmin Tanislav 				  AD74115_ADC_CONV_SEQ_MASK,
658*48ea7559SCosmin Tanislav 				  FIELD_PREP(AD74115_ADC_CONV_SEQ_MASK, conv_seq));
659*48ea7559SCosmin Tanislav }
660*48ea7559SCosmin Tanislav 
ad74115_update_scan_mode(struct iio_dev * indio_dev,const unsigned long * active_scan_mask)661*48ea7559SCosmin Tanislav static int ad74115_update_scan_mode(struct iio_dev *indio_dev,
662*48ea7559SCosmin Tanislav 				    const unsigned long *active_scan_mask)
663*48ea7559SCosmin Tanislav {
664*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
665*48ea7559SCosmin Tanislav 	struct spi_transfer *xfer = st->adc_samples_xfer;
666*48ea7559SCosmin Tanislav 	u8 *rx_buf = st->adc_samples_rx_buf;
667*48ea7559SCosmin Tanislav 	u8 *tx_buf = st->adc_samples_tx_buf;
668*48ea7559SCosmin Tanislav 	unsigned int i;
669*48ea7559SCosmin Tanislav 	int ret = 0;
670*48ea7559SCosmin Tanislav 
671*48ea7559SCosmin Tanislav 	mutex_lock(&st->lock);
672*48ea7559SCosmin Tanislav 
673*48ea7559SCosmin Tanislav 	spi_message_init(&st->adc_samples_msg);
674*48ea7559SCosmin Tanislav 
675*48ea7559SCosmin Tanislav 	for_each_clear_bit(i, active_scan_mask, AD74115_ADC_CH_NUM) {
676*48ea7559SCosmin Tanislav 		ret = ad74115_set_adc_ch_en(st, i, false);
677*48ea7559SCosmin Tanislav 		if (ret)
678*48ea7559SCosmin Tanislav 			goto out;
679*48ea7559SCosmin Tanislav 	}
680*48ea7559SCosmin Tanislav 
681*48ea7559SCosmin Tanislav 	/*
682*48ea7559SCosmin Tanislav 	 * The read select register is used to select which register's value
683*48ea7559SCosmin Tanislav 	 * will be sent by the slave on the next SPI frame.
684*48ea7559SCosmin Tanislav 	 *
685*48ea7559SCosmin Tanislav 	 * Create an SPI message that, on each step, writes to the read select
686*48ea7559SCosmin Tanislav 	 * register to select the ADC result of the next enabled channel, and
687*48ea7559SCosmin Tanislav 	 * reads the ADC result of the previous enabled channel.
688*48ea7559SCosmin Tanislav 	 *
689*48ea7559SCosmin Tanislav 	 * Example:
690*48ea7559SCosmin Tanislav 	 * W: [WCH1] [WCH2] [WCH2] [WCH3] [    ]
691*48ea7559SCosmin Tanislav 	 * R: [    ] [RCH1] [RCH2] [RCH3] [RCH4]
692*48ea7559SCosmin Tanislav 	 */
693*48ea7559SCosmin Tanislav 	for_each_set_bit(i, active_scan_mask, AD74115_ADC_CH_NUM) {
694*48ea7559SCosmin Tanislav 		ret = ad74115_set_adc_ch_en(st, i, true);
695*48ea7559SCosmin Tanislav 		if (ret)
696*48ea7559SCosmin Tanislav 			goto out;
697*48ea7559SCosmin Tanislav 
698*48ea7559SCosmin Tanislav 		if (xfer == st->adc_samples_xfer)
699*48ea7559SCosmin Tanislav 			xfer->rx_buf = NULL;
700*48ea7559SCosmin Tanislav 		else
701*48ea7559SCosmin Tanislav 			xfer->rx_buf = rx_buf;
702*48ea7559SCosmin Tanislav 
703*48ea7559SCosmin Tanislav 		xfer->tx_buf = tx_buf;
704*48ea7559SCosmin Tanislav 		xfer->len = AD74115_FRAME_SIZE;
705*48ea7559SCosmin Tanislav 		xfer->cs_change = 1;
706*48ea7559SCosmin Tanislav 
707*48ea7559SCosmin Tanislav 		ad74115_format_reg_write(AD74115_READ_SELECT_REG,
708*48ea7559SCosmin Tanislav 					 ad74115_adc_ch_data_regs_tbl[i], tx_buf);
709*48ea7559SCosmin Tanislav 
710*48ea7559SCosmin Tanislav 		spi_message_add_tail(xfer, &st->adc_samples_msg);
711*48ea7559SCosmin Tanislav 
712*48ea7559SCosmin Tanislav 		tx_buf += AD74115_FRAME_SIZE;
713*48ea7559SCosmin Tanislav 		if (xfer != st->adc_samples_xfer)
714*48ea7559SCosmin Tanislav 			rx_buf += AD74115_FRAME_SIZE;
715*48ea7559SCosmin Tanislav 		xfer++;
716*48ea7559SCosmin Tanislav 	}
717*48ea7559SCosmin Tanislav 
718*48ea7559SCosmin Tanislav 	xfer->rx_buf = rx_buf;
719*48ea7559SCosmin Tanislav 	xfer->tx_buf = NULL;
720*48ea7559SCosmin Tanislav 	xfer->len = AD74115_FRAME_SIZE;
721*48ea7559SCosmin Tanislav 	xfer->cs_change = 0;
722*48ea7559SCosmin Tanislav 
723*48ea7559SCosmin Tanislav 	spi_message_add_tail(xfer, &st->adc_samples_msg);
724*48ea7559SCosmin Tanislav 
725*48ea7559SCosmin Tanislav out:
726*48ea7559SCosmin Tanislav 	mutex_unlock(&st->lock);
727*48ea7559SCosmin Tanislav 
728*48ea7559SCosmin Tanislav 	return ret;
729*48ea7559SCosmin Tanislav }
730*48ea7559SCosmin Tanislav 
ad74115_buffer_postenable(struct iio_dev * indio_dev)731*48ea7559SCosmin Tanislav static int ad74115_buffer_postenable(struct iio_dev *indio_dev)
732*48ea7559SCosmin Tanislav {
733*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
734*48ea7559SCosmin Tanislav 
735*48ea7559SCosmin Tanislav 	return ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_CONTINUOUS);
736*48ea7559SCosmin Tanislav }
737*48ea7559SCosmin Tanislav 
ad74115_buffer_predisable(struct iio_dev * indio_dev)738*48ea7559SCosmin Tanislav static int ad74115_buffer_predisable(struct iio_dev *indio_dev)
739*48ea7559SCosmin Tanislav {
740*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
741*48ea7559SCosmin Tanislav 	unsigned int i;
742*48ea7559SCosmin Tanislav 	int ret;
743*48ea7559SCosmin Tanislav 
744*48ea7559SCosmin Tanislav 	mutex_lock(&st->lock);
745*48ea7559SCosmin Tanislav 
746*48ea7559SCosmin Tanislav 	ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_STANDBY);
747*48ea7559SCosmin Tanislav 	if (ret)
748*48ea7559SCosmin Tanislav 		goto out;
749*48ea7559SCosmin Tanislav 
750*48ea7559SCosmin Tanislav 	/*
751*48ea7559SCosmin Tanislav 	 * update_scan_mode() is not called in the disable path, disable all
752*48ea7559SCosmin Tanislav 	 * channels here.
753*48ea7559SCosmin Tanislav 	 */
754*48ea7559SCosmin Tanislav 	for (i = 0; i < AD74115_ADC_CH_NUM; i++) {
755*48ea7559SCosmin Tanislav 		ret = ad74115_set_adc_ch_en(st, i, false);
756*48ea7559SCosmin Tanislav 		if (ret)
757*48ea7559SCosmin Tanislav 			goto out;
758*48ea7559SCosmin Tanislav 	}
759*48ea7559SCosmin Tanislav 
760*48ea7559SCosmin Tanislav out:
761*48ea7559SCosmin Tanislav 	mutex_unlock(&st->lock);
762*48ea7559SCosmin Tanislav 
763*48ea7559SCosmin Tanislav 	return ret;
764*48ea7559SCosmin Tanislav }
765*48ea7559SCosmin Tanislav 
766*48ea7559SCosmin Tanislav static const struct iio_buffer_setup_ops ad74115_buffer_ops = {
767*48ea7559SCosmin Tanislav 	.postenable = &ad74115_buffer_postenable,
768*48ea7559SCosmin Tanislav 	.predisable = &ad74115_buffer_predisable,
769*48ea7559SCosmin Tanislav };
770*48ea7559SCosmin Tanislav 
771*48ea7559SCosmin Tanislav static const struct iio_trigger_ops ad74115_trigger_ops = {
772*48ea7559SCosmin Tanislav 	.validate_device = iio_trigger_validate_own_device,
773*48ea7559SCosmin Tanislav };
774*48ea7559SCosmin Tanislav 
ad74115_get_adc_rate(struct ad74115_state * st,enum ad74115_adc_ch channel,int * val)775*48ea7559SCosmin Tanislav static int ad74115_get_adc_rate(struct ad74115_state *st,
776*48ea7559SCosmin Tanislav 				enum ad74115_adc_ch channel, int *val)
777*48ea7559SCosmin Tanislav {
778*48ea7559SCosmin Tanislav 	unsigned int i;
779*48ea7559SCosmin Tanislav 	int ret;
780*48ea7559SCosmin Tanislav 
781*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_ADC_CONFIG_REG, &i);
782*48ea7559SCosmin Tanislav 	if (ret)
783*48ea7559SCosmin Tanislav 		return ret;
784*48ea7559SCosmin Tanislav 
785*48ea7559SCosmin Tanislav 	if (channel == AD74115_ADC_CH_CONV1)
786*48ea7559SCosmin Tanislav 		i = FIELD_GET(AD74115_ADC_CONFIG_CONV1_RATE_MASK, i);
787*48ea7559SCosmin Tanislav 	else
788*48ea7559SCosmin Tanislav 		i = FIELD_GET(AD74115_ADC_CONFIG_CONV2_RATE_MASK, i);
789*48ea7559SCosmin Tanislav 
790*48ea7559SCosmin Tanislav 	*val = ad74115_adc_conv_rate_tbl[i];
791*48ea7559SCosmin Tanislav 
792*48ea7559SCosmin Tanislav 	return IIO_VAL_INT;
793*48ea7559SCosmin Tanislav }
794*48ea7559SCosmin Tanislav 
_ad74115_get_adc_code(struct ad74115_state * st,enum ad74115_adc_ch channel,int * val)795*48ea7559SCosmin Tanislav static int _ad74115_get_adc_code(struct ad74115_state *st,
796*48ea7559SCosmin Tanislav 				 enum ad74115_adc_ch channel, int *val)
797*48ea7559SCosmin Tanislav {
798*48ea7559SCosmin Tanislav 	unsigned int uval;
799*48ea7559SCosmin Tanislav 	int ret;
800*48ea7559SCosmin Tanislav 
801*48ea7559SCosmin Tanislav 	reinit_completion(&st->adc_data_completion);
802*48ea7559SCosmin Tanislav 
803*48ea7559SCosmin Tanislav 	ret = ad74115_set_adc_ch_en(st, channel, true);
804*48ea7559SCosmin Tanislav 	if (ret)
805*48ea7559SCosmin Tanislav 		return ret;
806*48ea7559SCosmin Tanislav 
807*48ea7559SCosmin Tanislav 	ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_SINGLE);
808*48ea7559SCosmin Tanislav 	if (ret)
809*48ea7559SCosmin Tanislav 		return ret;
810*48ea7559SCosmin Tanislav 
811*48ea7559SCosmin Tanislav 	if (st->irq) {
812*48ea7559SCosmin Tanislav 		ret = wait_for_completion_timeout(&st->adc_data_completion,
813*48ea7559SCosmin Tanislav 						  msecs_to_jiffies(1000));
814*48ea7559SCosmin Tanislav 		if (!ret)
815*48ea7559SCosmin Tanislav 			return -ETIMEDOUT;
816*48ea7559SCosmin Tanislav 	} else {
817*48ea7559SCosmin Tanislav 		unsigned int regval, wait_time;
818*48ea7559SCosmin Tanislav 		int rate;
819*48ea7559SCosmin Tanislav 
820*48ea7559SCosmin Tanislav 		ret = ad74115_get_adc_rate(st, channel, &rate);
821*48ea7559SCosmin Tanislav 		if (ret < 0)
822*48ea7559SCosmin Tanislav 			return ret;
823*48ea7559SCosmin Tanislav 
824*48ea7559SCosmin Tanislav 		wait_time = DIV_ROUND_CLOSEST(AD74115_CONV_TIME_US, rate);
825*48ea7559SCosmin Tanislav 
826*48ea7559SCosmin Tanislav 		ret = regmap_read_poll_timeout(st->regmap, AD74115_LIVE_STATUS_REG,
827*48ea7559SCosmin Tanislav 					       regval, regval & AD74115_ADC_DATA_RDY_MASK,
828*48ea7559SCosmin Tanislav 					       wait_time, 5 * wait_time);
829*48ea7559SCosmin Tanislav 		if (ret)
830*48ea7559SCosmin Tanislav 			return ret;
831*48ea7559SCosmin Tanislav 
832*48ea7559SCosmin Tanislav 		/*
833*48ea7559SCosmin Tanislav 		 * The ADC_DATA_RDY bit is W1C.
834*48ea7559SCosmin Tanislav 		 * See datasheet page 98, Table 62. Bit Descriptions for
835*48ea7559SCosmin Tanislav 		 * LIVE_STATUS.
836*48ea7559SCosmin Tanislav 		 * Although the datasheet mentions that the bit will auto-clear
837*48ea7559SCosmin Tanislav 		 * when writing to the ADC_CONV_CTRL register, this does not
838*48ea7559SCosmin Tanislav 		 * seem to happen.
839*48ea7559SCosmin Tanislav 		 */
840*48ea7559SCosmin Tanislav 		ret = regmap_write_bits(st->regmap, AD74115_LIVE_STATUS_REG,
841*48ea7559SCosmin Tanislav 					AD74115_ADC_DATA_RDY_MASK,
842*48ea7559SCosmin Tanislav 					FIELD_PREP(AD74115_ADC_DATA_RDY_MASK, 1));
843*48ea7559SCosmin Tanislav 		if (ret)
844*48ea7559SCosmin Tanislav 			return ret;
845*48ea7559SCosmin Tanislav 	}
846*48ea7559SCosmin Tanislav 
847*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, ad74115_adc_ch_data_regs_tbl[channel], &uval);
848*48ea7559SCosmin Tanislav 	if (ret)
849*48ea7559SCosmin Tanislav 		return ret;
850*48ea7559SCosmin Tanislav 
851*48ea7559SCosmin Tanislav 	ret = ad74115_set_adc_conv_seq(st, AD74115_ADC_CONV_SEQ_STANDBY);
852*48ea7559SCosmin Tanislav 	if (ret)
853*48ea7559SCosmin Tanislav 		return ret;
854*48ea7559SCosmin Tanislav 
855*48ea7559SCosmin Tanislav 	ret = ad74115_set_adc_ch_en(st, channel, false);
856*48ea7559SCosmin Tanislav 	if (ret)
857*48ea7559SCosmin Tanislav 		return ret;
858*48ea7559SCosmin Tanislav 
859*48ea7559SCosmin Tanislav 	*val = uval;
860*48ea7559SCosmin Tanislav 
861*48ea7559SCosmin Tanislav 	return IIO_VAL_INT;
862*48ea7559SCosmin Tanislav }
863*48ea7559SCosmin Tanislav 
ad74115_get_adc_code(struct iio_dev * indio_dev,enum ad74115_adc_ch channel,int * val)864*48ea7559SCosmin Tanislav static int ad74115_get_adc_code(struct iio_dev *indio_dev,
865*48ea7559SCosmin Tanislav 				enum ad74115_adc_ch channel, int *val)
866*48ea7559SCosmin Tanislav {
867*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
868*48ea7559SCosmin Tanislav 	int ret;
869*48ea7559SCosmin Tanislav 
870*48ea7559SCosmin Tanislav 	ret = iio_device_claim_direct_mode(indio_dev);
871*48ea7559SCosmin Tanislav 	if (ret)
872*48ea7559SCosmin Tanislav 		return ret;
873*48ea7559SCosmin Tanislav 
874*48ea7559SCosmin Tanislav 	mutex_lock(&st->lock);
875*48ea7559SCosmin Tanislav 	ret = _ad74115_get_adc_code(st, channel, val);
876*48ea7559SCosmin Tanislav 	mutex_unlock(&st->lock);
877*48ea7559SCosmin Tanislav 
878*48ea7559SCosmin Tanislav 	iio_device_release_direct_mode(indio_dev);
879*48ea7559SCosmin Tanislav 
880*48ea7559SCosmin Tanislav 	return ret;
881*48ea7559SCosmin Tanislav }
882*48ea7559SCosmin Tanislav 
ad74115_adc_code_to_resistance(int code,int * val,int * val2)883*48ea7559SCosmin Tanislav static int ad74115_adc_code_to_resistance(int code, int *val, int *val2)
884*48ea7559SCosmin Tanislav {
885*48ea7559SCosmin Tanislav 	if (code == AD74115_ADC_CODE_MAX)
886*48ea7559SCosmin Tanislav 		code--;
887*48ea7559SCosmin Tanislav 
888*48ea7559SCosmin Tanislav 	*val = code * AD74115_REF_RESISTOR_OHMS;
889*48ea7559SCosmin Tanislav 	*val2 = AD74115_ADC_CODE_MAX - code;
890*48ea7559SCosmin Tanislav 
891*48ea7559SCosmin Tanislav 	return IIO_VAL_FRACTIONAL;
892*48ea7559SCosmin Tanislav }
893*48ea7559SCosmin Tanislav 
ad74115_set_dac_code(struct ad74115_state * st,enum ad74115_dac_ch channel,int val)894*48ea7559SCosmin Tanislav static int ad74115_set_dac_code(struct ad74115_state *st,
895*48ea7559SCosmin Tanislav 				enum ad74115_dac_ch channel, int val)
896*48ea7559SCosmin Tanislav {
897*48ea7559SCosmin Tanislav 	if (val < 0)
898*48ea7559SCosmin Tanislav 		return -EINVAL;
899*48ea7559SCosmin Tanislav 
900*48ea7559SCosmin Tanislav 	if (channel == AD74115_DAC_CH_COMPARATOR) {
901*48ea7559SCosmin Tanislav 		if (val > AD74115_COMP_THRESH_MAX)
902*48ea7559SCosmin Tanislav 			return -EINVAL;
903*48ea7559SCosmin Tanislav 
904*48ea7559SCosmin Tanislav 		return regmap_update_bits(st->regmap, AD74115_DIN_CONFIG2_REG,
905*48ea7559SCosmin Tanislav 					  AD74115_COMP_THRESH_MASK,
906*48ea7559SCosmin Tanislav 					  FIELD_PREP(AD74115_COMP_THRESH_MASK, val));
907*48ea7559SCosmin Tanislav 	}
908*48ea7559SCosmin Tanislav 
909*48ea7559SCosmin Tanislav 	if (val > AD74115_DAC_CODE_MAX)
910*48ea7559SCosmin Tanislav 		return -EINVAL;
911*48ea7559SCosmin Tanislav 
912*48ea7559SCosmin Tanislav 	return regmap_write(st->regmap, AD74115_DAC_CODE_REG, val);
913*48ea7559SCosmin Tanislav }
914*48ea7559SCosmin Tanislav 
ad74115_get_dac_code(struct ad74115_state * st,enum ad74115_dac_ch channel,int * val)915*48ea7559SCosmin Tanislav static int ad74115_get_dac_code(struct ad74115_state *st,
916*48ea7559SCosmin Tanislav 				enum ad74115_dac_ch channel, int *val)
917*48ea7559SCosmin Tanislav {
918*48ea7559SCosmin Tanislav 	unsigned int uval;
919*48ea7559SCosmin Tanislav 	int ret;
920*48ea7559SCosmin Tanislav 
921*48ea7559SCosmin Tanislav 	if (channel == AD74115_DAC_CH_COMPARATOR)
922*48ea7559SCosmin Tanislav 		return -EINVAL;
923*48ea7559SCosmin Tanislav 
924*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_DAC_ACTIVE_REG, &uval);
925*48ea7559SCosmin Tanislav 	if (ret)
926*48ea7559SCosmin Tanislav 		return ret;
927*48ea7559SCosmin Tanislav 
928*48ea7559SCosmin Tanislav 	*val = uval;
929*48ea7559SCosmin Tanislav 
930*48ea7559SCosmin Tanislav 	return IIO_VAL_INT;
931*48ea7559SCosmin Tanislav }
932*48ea7559SCosmin Tanislav 
ad74115_set_adc_rate(struct ad74115_state * st,enum ad74115_adc_ch channel,int val)933*48ea7559SCosmin Tanislav static int ad74115_set_adc_rate(struct ad74115_state *st,
934*48ea7559SCosmin Tanislav 				enum ad74115_adc_ch channel, int val)
935*48ea7559SCosmin Tanislav {
936*48ea7559SCosmin Tanislav 	unsigned int i;
937*48ea7559SCosmin Tanislav 	int ret;
938*48ea7559SCosmin Tanislav 
939*48ea7559SCosmin Tanislav 	ret = ad74115_find_tbl_index(ad74115_adc_conv_rate_tbl, val, &i);
940*48ea7559SCosmin Tanislav 	if (ret)
941*48ea7559SCosmin Tanislav 		return ret;
942*48ea7559SCosmin Tanislav 
943*48ea7559SCosmin Tanislav 	if (channel == AD74115_ADC_CH_CONV1)
944*48ea7559SCosmin Tanislav 		return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG,
945*48ea7559SCosmin Tanislav 					  AD74115_ADC_CONFIG_CONV1_RATE_MASK,
946*48ea7559SCosmin Tanislav 					  FIELD_PREP(AD74115_ADC_CONFIG_CONV1_RATE_MASK, i));
947*48ea7559SCosmin Tanislav 
948*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG,
949*48ea7559SCosmin Tanislav 				  AD74115_ADC_CONFIG_CONV2_RATE_MASK,
950*48ea7559SCosmin Tanislav 				  FIELD_PREP(AD74115_ADC_CONFIG_CONV2_RATE_MASK, i));
951*48ea7559SCosmin Tanislav }
952*48ea7559SCosmin Tanislav 
ad74115_get_dac_rate(struct ad74115_state * st,int * val)953*48ea7559SCosmin Tanislav static int ad74115_get_dac_rate(struct ad74115_state *st, int *val)
954*48ea7559SCosmin Tanislav {
955*48ea7559SCosmin Tanislav 	unsigned int i, en_val, step_val, rate_val, tmp;
956*48ea7559SCosmin Tanislav 	int ret;
957*48ea7559SCosmin Tanislav 
958*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_OUTPUT_CONFIG_REG, &tmp);
959*48ea7559SCosmin Tanislav 	if (ret)
960*48ea7559SCosmin Tanislav 		return ret;
961*48ea7559SCosmin Tanislav 
962*48ea7559SCosmin Tanislav 	en_val = FIELD_GET(AD74115_OUTPUT_SLEW_EN_MASK, tmp);
963*48ea7559SCosmin Tanislav 	step_val = FIELD_GET(AD74115_OUTPUT_SLEW_LIN_STEP_MASK, tmp);
964*48ea7559SCosmin Tanislav 	rate_val = FIELD_GET(AD74115_OUTPUT_SLEW_LIN_RATE_MASK, tmp);
965*48ea7559SCosmin Tanislav 
966*48ea7559SCosmin Tanislav 	for (i = 0; i < ARRAY_SIZE(ad74115_dac_rate_step_tbl); i++)
967*48ea7559SCosmin Tanislav 		if (en_val == ad74115_dac_rate_step_tbl[i][0] &&
968*48ea7559SCosmin Tanislav 		    step_val == ad74115_dac_rate_step_tbl[i][1] &&
969*48ea7559SCosmin Tanislav 		    rate_val == ad74115_dac_rate_step_tbl[i][2])
970*48ea7559SCosmin Tanislav 			break;
971*48ea7559SCosmin Tanislav 
972*48ea7559SCosmin Tanislav 	if (i == ARRAY_SIZE(ad74115_dac_rate_step_tbl))
973*48ea7559SCosmin Tanislav 		return -EINVAL;
974*48ea7559SCosmin Tanislav 
975*48ea7559SCosmin Tanislav 	*val = ad74115_dac_rate_tbl[i];
976*48ea7559SCosmin Tanislav 
977*48ea7559SCosmin Tanislav 	return IIO_VAL_INT;
978*48ea7559SCosmin Tanislav }
979*48ea7559SCosmin Tanislav 
ad74115_set_dac_rate(struct ad74115_state * st,int val)980*48ea7559SCosmin Tanislav static int ad74115_set_dac_rate(struct ad74115_state *st, int val)
981*48ea7559SCosmin Tanislav {
982*48ea7559SCosmin Tanislav 	unsigned int i, en_val, step_val, rate_val, mask, tmp;
983*48ea7559SCosmin Tanislav 	int ret;
984*48ea7559SCosmin Tanislav 
985*48ea7559SCosmin Tanislav 	ret = ad74115_find_tbl_index(ad74115_dac_rate_tbl, val, &i);
986*48ea7559SCosmin Tanislav 	if (ret)
987*48ea7559SCosmin Tanislav 		return ret;
988*48ea7559SCosmin Tanislav 
989*48ea7559SCosmin Tanislav 	en_val = ad74115_dac_rate_step_tbl[i][0];
990*48ea7559SCosmin Tanislav 	step_val = ad74115_dac_rate_step_tbl[i][1];
991*48ea7559SCosmin Tanislav 	rate_val = ad74115_dac_rate_step_tbl[i][2];
992*48ea7559SCosmin Tanislav 
993*48ea7559SCosmin Tanislav 	mask = AD74115_OUTPUT_SLEW_EN_MASK;
994*48ea7559SCosmin Tanislav 	mask |= AD74115_OUTPUT_SLEW_LIN_STEP_MASK;
995*48ea7559SCosmin Tanislav 	mask |= AD74115_OUTPUT_SLEW_LIN_RATE_MASK;
996*48ea7559SCosmin Tanislav 
997*48ea7559SCosmin Tanislav 	tmp = FIELD_PREP(AD74115_OUTPUT_SLEW_EN_MASK, en_val);
998*48ea7559SCosmin Tanislav 	tmp |= FIELD_PREP(AD74115_OUTPUT_SLEW_LIN_STEP_MASK, step_val);
999*48ea7559SCosmin Tanislav 	tmp |= FIELD_PREP(AD74115_OUTPUT_SLEW_LIN_RATE_MASK, rate_val);
1000*48ea7559SCosmin Tanislav 
1001*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, AD74115_OUTPUT_CONFIG_REG, mask, tmp);
1002*48ea7559SCosmin Tanislav }
1003*48ea7559SCosmin Tanislav 
ad74115_get_dac_scale(struct ad74115_state * st,struct iio_chan_spec const * chan,int * val,int * val2)1004*48ea7559SCosmin Tanislav static int ad74115_get_dac_scale(struct ad74115_state *st,
1005*48ea7559SCosmin Tanislav 				 struct iio_chan_spec const *chan,
1006*48ea7559SCosmin Tanislav 				 int *val, int *val2)
1007*48ea7559SCosmin Tanislav {
1008*48ea7559SCosmin Tanislav 	if (chan->channel == AD74115_DAC_CH_MAIN) {
1009*48ea7559SCosmin Tanislav 		if (chan->type == IIO_VOLTAGE) {
1010*48ea7559SCosmin Tanislav 			*val = AD74115_DAC_VOLTAGE_MAX;
1011*48ea7559SCosmin Tanislav 
1012*48ea7559SCosmin Tanislav 			if (st->dac_bipolar)
1013*48ea7559SCosmin Tanislav 				*val *= 2;
1014*48ea7559SCosmin Tanislav 
1015*48ea7559SCosmin Tanislav 		} else {
1016*48ea7559SCosmin Tanislav 			*val = AD74115_DAC_CURRENT_MAX;
1017*48ea7559SCosmin Tanislav 		}
1018*48ea7559SCosmin Tanislav 
1019*48ea7559SCosmin Tanislav 		*val2 = AD74115_DAC_CODE_MAX;
1020*48ea7559SCosmin Tanislav 	} else {
1021*48ea7559SCosmin Tanislav 		if (st->din_threshold_mode == AD74115_DIN_THRESHOLD_MODE_AVDD) {
1022*48ea7559SCosmin Tanislav 			*val = 196 * st->avdd_mv;
1023*48ea7559SCosmin Tanislav 			*val2 = 10 * AD74115_COMP_THRESH_MAX;
1024*48ea7559SCosmin Tanislav 		} else {
1025*48ea7559SCosmin Tanislav 			*val = 49000;
1026*48ea7559SCosmin Tanislav 			*val2 = AD74115_COMP_THRESH_MAX;
1027*48ea7559SCosmin Tanislav 		}
1028*48ea7559SCosmin Tanislav 	}
1029*48ea7559SCosmin Tanislav 
1030*48ea7559SCosmin Tanislav 	return IIO_VAL_FRACTIONAL;
1031*48ea7559SCosmin Tanislav }
1032*48ea7559SCosmin Tanislav 
ad74115_get_dac_offset(struct ad74115_state * st,struct iio_chan_spec const * chan,int * val)1033*48ea7559SCosmin Tanislav static int ad74115_get_dac_offset(struct ad74115_state *st,
1034*48ea7559SCosmin Tanislav 				  struct iio_chan_spec const *chan, int *val)
1035*48ea7559SCosmin Tanislav {
1036*48ea7559SCosmin Tanislav 	if (chan->channel == AD74115_DAC_CH_MAIN) {
1037*48ea7559SCosmin Tanislav 		if (chan->type == IIO_VOLTAGE && st->dac_bipolar)
1038*48ea7559SCosmin Tanislav 			*val = -AD74115_DAC_CODE_HALF;
1039*48ea7559SCosmin Tanislav 		else
1040*48ea7559SCosmin Tanislav 			*val = 0;
1041*48ea7559SCosmin Tanislav 	} else {
1042*48ea7559SCosmin Tanislav 		if (st->din_threshold_mode == AD74115_DIN_THRESHOLD_MODE_AVDD)
1043*48ea7559SCosmin Tanislav 			*val = -48;
1044*48ea7559SCosmin Tanislav 		else
1045*48ea7559SCosmin Tanislav 			*val = -38;
1046*48ea7559SCosmin Tanislav 	}
1047*48ea7559SCosmin Tanislav 
1048*48ea7559SCosmin Tanislav 	return IIO_VAL_INT;
1049*48ea7559SCosmin Tanislav }
1050*48ea7559SCosmin Tanislav 
ad74115_get_adc_range(struct ad74115_state * st,enum ad74115_adc_ch channel,unsigned int * val)1051*48ea7559SCosmin Tanislav static int ad74115_get_adc_range(struct ad74115_state *st,
1052*48ea7559SCosmin Tanislav 				 enum ad74115_adc_ch channel, unsigned int *val)
1053*48ea7559SCosmin Tanislav {
1054*48ea7559SCosmin Tanislav 	int ret;
1055*48ea7559SCosmin Tanislav 
1056*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_ADC_CONFIG_REG, val);
1057*48ea7559SCosmin Tanislav 	if (ret)
1058*48ea7559SCosmin Tanislav 		return ret;
1059*48ea7559SCosmin Tanislav 
1060*48ea7559SCosmin Tanislav 	if (channel == AD74115_ADC_CH_CONV1)
1061*48ea7559SCosmin Tanislav 		*val = FIELD_GET(AD74115_ADC_CONFIG_CONV1_RANGE_MASK, *val);
1062*48ea7559SCosmin Tanislav 	else
1063*48ea7559SCosmin Tanislav 		*val = FIELD_GET(AD74115_ADC_CONFIG_CONV2_RANGE_MASK, *val);
1064*48ea7559SCosmin Tanislav 
1065*48ea7559SCosmin Tanislav 	return 0;
1066*48ea7559SCosmin Tanislav }
1067*48ea7559SCosmin Tanislav 
ad74115_get_adc_resistance_scale(struct ad74115_state * st,unsigned int range,int * val,int * val2)1068*48ea7559SCosmin Tanislav static int ad74115_get_adc_resistance_scale(struct ad74115_state *st,
1069*48ea7559SCosmin Tanislav 					    unsigned int range,
1070*48ea7559SCosmin Tanislav 					    int *val, int *val2)
1071*48ea7559SCosmin Tanislav {
1072*48ea7559SCosmin Tanislav 	*val = ad74115_adc_gain_tbl[range][1] * AD74115_REF_RESISTOR_OHMS;
1073*48ea7559SCosmin Tanislav 	*val2 = ad74115_adc_gain_tbl[range][0];
1074*48ea7559SCosmin Tanislav 
1075*48ea7559SCosmin Tanislav 	if (ad74115_adc_bipolar_tbl[range])
1076*48ea7559SCosmin Tanislav 		*val2 *= AD74115_ADC_CODE_HALF;
1077*48ea7559SCosmin Tanislav 	else
1078*48ea7559SCosmin Tanislav 		*val2 *= AD74115_ADC_CODE_MAX;
1079*48ea7559SCosmin Tanislav 
1080*48ea7559SCosmin Tanislav 	return IIO_VAL_FRACTIONAL;
1081*48ea7559SCosmin Tanislav }
1082*48ea7559SCosmin Tanislav 
ad74115_get_adc_scale(struct ad74115_state * st,struct iio_chan_spec const * chan,int * val,int * val2)1083*48ea7559SCosmin Tanislav static int ad74115_get_adc_scale(struct ad74115_state *st,
1084*48ea7559SCosmin Tanislav 				 struct iio_chan_spec const *chan,
1085*48ea7559SCosmin Tanislav 				 int *val, int *val2)
1086*48ea7559SCosmin Tanislav {
1087*48ea7559SCosmin Tanislav 	unsigned int range;
1088*48ea7559SCosmin Tanislav 	int ret;
1089*48ea7559SCosmin Tanislav 
1090*48ea7559SCosmin Tanislav 	ret = ad74115_get_adc_range(st, chan->channel, &range);
1091*48ea7559SCosmin Tanislav 	if (ret)
1092*48ea7559SCosmin Tanislav 		return ret;
1093*48ea7559SCosmin Tanislav 
1094*48ea7559SCosmin Tanislav 	if (chan->type == IIO_RESISTANCE)
1095*48ea7559SCosmin Tanislav 		return ad74115_get_adc_resistance_scale(st, range, val, val2);
1096*48ea7559SCosmin Tanislav 
1097*48ea7559SCosmin Tanislav 	*val = ad74115_adc_conv_mul_tbl[range];
1098*48ea7559SCosmin Tanislav 	*val2 = AD74115_ADC_CODE_MAX;
1099*48ea7559SCosmin Tanislav 
1100*48ea7559SCosmin Tanislav 	if (chan->type == IIO_CURRENT)
1101*48ea7559SCosmin Tanislav 		*val2 *= AD74115_SENSE_RESISTOR_OHMS;
1102*48ea7559SCosmin Tanislav 
1103*48ea7559SCosmin Tanislav 	return IIO_VAL_FRACTIONAL;
1104*48ea7559SCosmin Tanislav }
1105*48ea7559SCosmin Tanislav 
ad74115_get_adc_resistance_offset(struct ad74115_state * st,unsigned int range,int * val,int * val2)1106*48ea7559SCosmin Tanislav static int ad74115_get_adc_resistance_offset(struct ad74115_state *st,
1107*48ea7559SCosmin Tanislav 					     unsigned int range,
1108*48ea7559SCosmin Tanislav 					     int *val, int *val2)
1109*48ea7559SCosmin Tanislav {
1110*48ea7559SCosmin Tanislav 	unsigned int d = 10 * AD74115_REF_RESISTOR_OHMS
1111*48ea7559SCosmin Tanislav 			 * ad74115_adc_gain_tbl[range][1];
1112*48ea7559SCosmin Tanislav 
1113*48ea7559SCosmin Tanislav 	*val = 5;
1114*48ea7559SCosmin Tanislav 
1115*48ea7559SCosmin Tanislav 	if (ad74115_adc_bipolar_tbl[range])
1116*48ea7559SCosmin Tanislav 		*val -= AD74115_ADC_CODE_HALF;
1117*48ea7559SCosmin Tanislav 
1118*48ea7559SCosmin Tanislav 	*val *= d;
1119*48ea7559SCosmin Tanislav 
1120*48ea7559SCosmin Tanislav 	if (!st->rtd_mode_4_wire) {
1121*48ea7559SCosmin Tanislav 		/* Add 0.2 Ohm to the final result for 3-wire RTD. */
1122*48ea7559SCosmin Tanislav 		unsigned int v = 2 * ad74115_adc_gain_tbl[range][0];
1123*48ea7559SCosmin Tanislav 
1124*48ea7559SCosmin Tanislav 		if (ad74115_adc_bipolar_tbl[range])
1125*48ea7559SCosmin Tanislav 			v *= AD74115_ADC_CODE_HALF;
1126*48ea7559SCosmin Tanislav 		else
1127*48ea7559SCosmin Tanislav 			v *= AD74115_ADC_CODE_MAX;
1128*48ea7559SCosmin Tanislav 
1129*48ea7559SCosmin Tanislav 		*val += v;
1130*48ea7559SCosmin Tanislav 	}
1131*48ea7559SCosmin Tanislav 
1132*48ea7559SCosmin Tanislav 	*val2 = d;
1133*48ea7559SCosmin Tanislav 
1134*48ea7559SCosmin Tanislav 	return IIO_VAL_FRACTIONAL;
1135*48ea7559SCosmin Tanislav }
1136*48ea7559SCosmin Tanislav 
ad74115_get_adc_offset(struct ad74115_state * st,struct iio_chan_spec const * chan,int * val,int * val2)1137*48ea7559SCosmin Tanislav static int ad74115_get_adc_offset(struct ad74115_state *st,
1138*48ea7559SCosmin Tanislav 				  struct iio_chan_spec const *chan,
1139*48ea7559SCosmin Tanislav 				  int *val, int *val2)
1140*48ea7559SCosmin Tanislav {
1141*48ea7559SCosmin Tanislav 	unsigned int range;
1142*48ea7559SCosmin Tanislav 	int ret;
1143*48ea7559SCosmin Tanislav 
1144*48ea7559SCosmin Tanislav 	ret = ad74115_get_adc_range(st, chan->channel, &range);
1145*48ea7559SCosmin Tanislav 	if (ret)
1146*48ea7559SCosmin Tanislav 		return ret;
1147*48ea7559SCosmin Tanislav 
1148*48ea7559SCosmin Tanislav 	if (chan->type == IIO_RESISTANCE)
1149*48ea7559SCosmin Tanislav 		return ad74115_get_adc_resistance_offset(st, range, val, val2);
1150*48ea7559SCosmin Tanislav 
1151*48ea7559SCosmin Tanislav 	if (ad74115_adc_bipolar_tbl[range])
1152*48ea7559SCosmin Tanislav 		*val = -AD74115_ADC_CODE_HALF;
1153*48ea7559SCosmin Tanislav 	else if (range == AD74115_ADC_RANGE_2_5V_NEG)
1154*48ea7559SCosmin Tanislav 		*val = -AD74115_ADC_CODE_MAX;
1155*48ea7559SCosmin Tanislav 	else
1156*48ea7559SCosmin Tanislav 		*val = 0;
1157*48ea7559SCosmin Tanislav 
1158*48ea7559SCosmin Tanislav 	return IIO_VAL_INT;
1159*48ea7559SCosmin Tanislav }
1160*48ea7559SCosmin Tanislav 
ad74115_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)1161*48ea7559SCosmin Tanislav static int ad74115_read_raw(struct iio_dev *indio_dev,
1162*48ea7559SCosmin Tanislav 			    struct iio_chan_spec const *chan,
1163*48ea7559SCosmin Tanislav 			    int *val, int *val2, long info)
1164*48ea7559SCosmin Tanislav {
1165*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
1166*48ea7559SCosmin Tanislav 	int ret;
1167*48ea7559SCosmin Tanislav 
1168*48ea7559SCosmin Tanislav 	switch (info) {
1169*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_RAW:
1170*48ea7559SCosmin Tanislav 		if (chan->output)
1171*48ea7559SCosmin Tanislav 			return ad74115_get_dac_code(st, chan->channel, val);
1172*48ea7559SCosmin Tanislav 
1173*48ea7559SCosmin Tanislav 		return ad74115_get_adc_code(indio_dev, chan->channel, val);
1174*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_PROCESSED:
1175*48ea7559SCosmin Tanislav 		ret = ad74115_get_adc_code(indio_dev, chan->channel, val);
1176*48ea7559SCosmin Tanislav 		if (ret)
1177*48ea7559SCosmin Tanislav 			return ret;
1178*48ea7559SCosmin Tanislav 
1179*48ea7559SCosmin Tanislav 		return ad74115_adc_code_to_resistance(*val, val, val2);
1180*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_SCALE:
1181*48ea7559SCosmin Tanislav 		if (chan->output)
1182*48ea7559SCosmin Tanislav 			return ad74115_get_dac_scale(st, chan, val, val2);
1183*48ea7559SCosmin Tanislav 
1184*48ea7559SCosmin Tanislav 		return ad74115_get_adc_scale(st, chan, val, val2);
1185*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_OFFSET:
1186*48ea7559SCosmin Tanislav 		if (chan->output)
1187*48ea7559SCosmin Tanislav 			return ad74115_get_dac_offset(st, chan, val);
1188*48ea7559SCosmin Tanislav 
1189*48ea7559SCosmin Tanislav 		return ad74115_get_adc_offset(st, chan, val, val2);
1190*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_SAMP_FREQ:
1191*48ea7559SCosmin Tanislav 		if (chan->output)
1192*48ea7559SCosmin Tanislav 			return ad74115_get_dac_rate(st, val);
1193*48ea7559SCosmin Tanislav 
1194*48ea7559SCosmin Tanislav 		return ad74115_get_adc_rate(st, chan->channel, val);
1195*48ea7559SCosmin Tanislav 	default:
1196*48ea7559SCosmin Tanislav 		return -EINVAL;
1197*48ea7559SCosmin Tanislav 	}
1198*48ea7559SCosmin Tanislav }
1199*48ea7559SCosmin Tanislav 
ad74115_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)1200*48ea7559SCosmin Tanislav static int ad74115_write_raw(struct iio_dev *indio_dev,
1201*48ea7559SCosmin Tanislav 			     struct iio_chan_spec const *chan, int val, int val2,
1202*48ea7559SCosmin Tanislav 			     long info)
1203*48ea7559SCosmin Tanislav {
1204*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
1205*48ea7559SCosmin Tanislav 
1206*48ea7559SCosmin Tanislav 	switch (info) {
1207*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_RAW:
1208*48ea7559SCosmin Tanislav 		if (!chan->output)
1209*48ea7559SCosmin Tanislav 			return -EINVAL;
1210*48ea7559SCosmin Tanislav 
1211*48ea7559SCosmin Tanislav 		return ad74115_set_dac_code(st, chan->channel, val);
1212*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_SAMP_FREQ:
1213*48ea7559SCosmin Tanislav 		if (chan->output)
1214*48ea7559SCosmin Tanislav 			return ad74115_set_dac_rate(st, val);
1215*48ea7559SCosmin Tanislav 
1216*48ea7559SCosmin Tanislav 		return ad74115_set_adc_rate(st, chan->channel, val);
1217*48ea7559SCosmin Tanislav 	default:
1218*48ea7559SCosmin Tanislav 		return -EINVAL;
1219*48ea7559SCosmin Tanislav 	}
1220*48ea7559SCosmin Tanislav }
1221*48ea7559SCosmin Tanislav 
ad74115_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long info)1222*48ea7559SCosmin Tanislav static int ad74115_read_avail(struct iio_dev *indio_dev,
1223*48ea7559SCosmin Tanislav 			      struct iio_chan_spec const *chan,
1224*48ea7559SCosmin Tanislav 			      const int **vals, int *type, int *length, long info)
1225*48ea7559SCosmin Tanislav {
1226*48ea7559SCosmin Tanislav 	switch (info) {
1227*48ea7559SCosmin Tanislav 	case IIO_CHAN_INFO_SAMP_FREQ:
1228*48ea7559SCosmin Tanislav 		if (chan->output) {
1229*48ea7559SCosmin Tanislav 			*vals = ad74115_dac_rate_tbl;
1230*48ea7559SCosmin Tanislav 			*length = ARRAY_SIZE(ad74115_dac_rate_tbl);
1231*48ea7559SCosmin Tanislav 		} else {
1232*48ea7559SCosmin Tanislav 			*vals = ad74115_adc_conv_rate_tbl;
1233*48ea7559SCosmin Tanislav 			*length = ARRAY_SIZE(ad74115_adc_conv_rate_tbl);
1234*48ea7559SCosmin Tanislav 		}
1235*48ea7559SCosmin Tanislav 
1236*48ea7559SCosmin Tanislav 		*type = IIO_VAL_INT;
1237*48ea7559SCosmin Tanislav 
1238*48ea7559SCosmin Tanislav 		return IIO_AVAIL_LIST;
1239*48ea7559SCosmin Tanislav 	default:
1240*48ea7559SCosmin Tanislav 		return -EINVAL;
1241*48ea7559SCosmin Tanislav 	}
1242*48ea7559SCosmin Tanislav }
1243*48ea7559SCosmin Tanislav 
ad74115_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)1244*48ea7559SCosmin Tanislav static int ad74115_reg_access(struct iio_dev *indio_dev, unsigned int reg,
1245*48ea7559SCosmin Tanislav 			      unsigned int writeval, unsigned int *readval)
1246*48ea7559SCosmin Tanislav {
1247*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
1248*48ea7559SCosmin Tanislav 
1249*48ea7559SCosmin Tanislav 	if (readval)
1250*48ea7559SCosmin Tanislav 		return regmap_read(st->regmap, reg, readval);
1251*48ea7559SCosmin Tanislav 
1252*48ea7559SCosmin Tanislav 	return regmap_write(st->regmap, reg, writeval);
1253*48ea7559SCosmin Tanislav }
1254*48ea7559SCosmin Tanislav 
1255*48ea7559SCosmin Tanislav static const struct iio_info ad74115_info = {
1256*48ea7559SCosmin Tanislav 	.read_raw = ad74115_read_raw,
1257*48ea7559SCosmin Tanislav 	.write_raw = ad74115_write_raw,
1258*48ea7559SCosmin Tanislav 	.read_avail = ad74115_read_avail,
1259*48ea7559SCosmin Tanislav 	.update_scan_mode = ad74115_update_scan_mode,
1260*48ea7559SCosmin Tanislav 	.debugfs_reg_access = ad74115_reg_access,
1261*48ea7559SCosmin Tanislav };
1262*48ea7559SCosmin Tanislav 
1263*48ea7559SCosmin Tanislav #define AD74115_DAC_CHANNEL(_type, index)				\
1264*48ea7559SCosmin Tanislav 	{								\
1265*48ea7559SCosmin Tanislav 		.type = (_type),					\
1266*48ea7559SCosmin Tanislav 		.channel = (index),					\
1267*48ea7559SCosmin Tanislav 		.indexed = 1,						\
1268*48ea7559SCosmin Tanislav 		.output = 1,						\
1269*48ea7559SCosmin Tanislav 		.scan_index = -1,					\
1270*48ea7559SCosmin Tanislav 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)		\
1271*48ea7559SCosmin Tanislav 				      | BIT(IIO_CHAN_INFO_SCALE)	\
1272*48ea7559SCosmin Tanislav 				      | BIT(IIO_CHAN_INFO_OFFSET),	\
1273*48ea7559SCosmin Tanislav 	}
1274*48ea7559SCosmin Tanislav 
1275*48ea7559SCosmin Tanislav #define _AD74115_ADC_CHANNEL(_type, index, extra_mask_separate)		\
1276*48ea7559SCosmin Tanislav 	{								\
1277*48ea7559SCosmin Tanislav 		.type = (_type),					\
1278*48ea7559SCosmin Tanislav 		.channel = (index),					\
1279*48ea7559SCosmin Tanislav 		.indexed = 1,						\
1280*48ea7559SCosmin Tanislav 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)		\
1281*48ea7559SCosmin Tanislav 				      | BIT(IIO_CHAN_INFO_SAMP_FREQ)	\
1282*48ea7559SCosmin Tanislav 				      | (extra_mask_separate),		\
1283*48ea7559SCosmin Tanislav 		.info_mask_separate_available =				\
1284*48ea7559SCosmin Tanislav 					BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
1285*48ea7559SCosmin Tanislav 		.scan_index = index,					\
1286*48ea7559SCosmin Tanislav 		.scan_type = {						\
1287*48ea7559SCosmin Tanislav 			.sign = 'u',					\
1288*48ea7559SCosmin Tanislav 			.realbits = 16,					\
1289*48ea7559SCosmin Tanislav 			.storagebits = 32,				\
1290*48ea7559SCosmin Tanislav 			.shift = 8,					\
1291*48ea7559SCosmin Tanislav 			.endianness = IIO_BE,				\
1292*48ea7559SCosmin Tanislav 		},							\
1293*48ea7559SCosmin Tanislav 	}
1294*48ea7559SCosmin Tanislav 
1295*48ea7559SCosmin Tanislav #define AD74115_ADC_CHANNEL(_type, index)				\
1296*48ea7559SCosmin Tanislav 	_AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE)	\
1297*48ea7559SCosmin Tanislav 					   | BIT(IIO_CHAN_INFO_OFFSET))
1298*48ea7559SCosmin Tanislav 
1299*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_voltage_input_channels[] = {
1300*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
1301*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1302*48ea7559SCosmin Tanislav };
1303*48ea7559SCosmin Tanislav 
1304*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_voltage_output_channels[] = {
1305*48ea7559SCosmin Tanislav 	AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN),
1306*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
1307*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1308*48ea7559SCosmin Tanislav };
1309*48ea7559SCosmin Tanislav 
1310*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_current_input_channels[] = {
1311*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
1312*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1313*48ea7559SCosmin Tanislav };
1314*48ea7559SCosmin Tanislav 
1315*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_current_output_channels[] = {
1316*48ea7559SCosmin Tanislav 	AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
1317*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
1318*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1319*48ea7559SCosmin Tanislav };
1320*48ea7559SCosmin Tanislav 
1321*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
1322*48ea7559SCosmin Tanislav 	_AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1,
1323*48ea7559SCosmin Tanislav 			     BIT(IIO_CHAN_INFO_PROCESSED)),
1324*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1325*48ea7559SCosmin Tanislav };
1326*48ea7559SCosmin Tanislav 
1327*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
1328*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1),
1329*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1330*48ea7559SCosmin Tanislav };
1331*48ea7559SCosmin Tanislav 
1332*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
1333*48ea7559SCosmin Tanislav 	AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
1334*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
1335*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1336*48ea7559SCosmin Tanislav };
1337*48ea7559SCosmin Tanislav 
1338*48ea7559SCosmin Tanislav static struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
1339*48ea7559SCosmin Tanislav 	AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
1340*48ea7559SCosmin Tanislav 	AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
1341*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
1342*48ea7559SCosmin Tanislav 	AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
1343*48ea7559SCosmin Tanislav };
1344*48ea7559SCosmin Tanislav 
1345*48ea7559SCosmin Tanislav #define _AD74115_CHANNELS(_channels)			\
1346*48ea7559SCosmin Tanislav 	{						\
1347*48ea7559SCosmin Tanislav 		.channels = _channels,			\
1348*48ea7559SCosmin Tanislav 		.num_channels = ARRAY_SIZE(_channels),	\
1349*48ea7559SCosmin Tanislav 	}
1350*48ea7559SCosmin Tanislav 
1351*48ea7559SCosmin Tanislav #define AD74115_CHANNELS(name) \
1352*48ea7559SCosmin Tanislav 	_AD74115_CHANNELS(ad74115_ ## name ## _channels)
1353*48ea7559SCosmin Tanislav 
1354*48ea7559SCosmin Tanislav static const struct ad74115_channels ad74115_channels_map[AD74115_CH_FUNC_NUM] = {
1355*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_HIGH_IMPEDANCE] = AD74115_CHANNELS(voltage_input),
1356*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_VOLTAGE_INPUT] = AD74115_CHANNELS(voltage_input),
1357*48ea7559SCosmin Tanislav 
1358*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_VOLTAGE_OUTPUT] = AD74115_CHANNELS(voltage_output),
1359*48ea7559SCosmin Tanislav 
1360*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER] = AD74115_CHANNELS(current_input),
1361*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER] = AD74115_CHANNELS(current_input),
1362*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_CURRENT_INPUT_EXT_POWER_HART] = AD74115_CHANNELS(current_input),
1363*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART] = AD74115_CHANNELS(current_input),
1364*48ea7559SCosmin Tanislav 
1365*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_CURRENT_OUTPUT] = AD74115_CHANNELS(current_output),
1366*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_CURRENT_OUTPUT_HART] = AD74115_CHANNELS(current_output),
1367*48ea7559SCosmin Tanislav 
1368*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_2_WIRE_RESISTANCE_INPUT] = AD74115_CHANNELS(2_wire_resistance_input),
1369*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_3_4_WIRE_RESISTANCE_INPUT] = AD74115_CHANNELS(3_4_wire_resistance_input),
1370*48ea7559SCosmin Tanislav 
1371*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_DIGITAL_INPUT_LOGIC] = AD74115_CHANNELS(digital_input_logic),
1372*48ea7559SCosmin Tanislav 
1373*48ea7559SCosmin Tanislav 	[AD74115_CH_FUNC_DIGITAL_INPUT_LOOP_POWER] = AD74115_CHANNELS(digital_input_loop),
1374*48ea7559SCosmin Tanislav };
1375*48ea7559SCosmin Tanislav 
1376*48ea7559SCosmin Tanislav #define AD74115_GPIO_MODE_FW_PROP(i)					\
1377*48ea7559SCosmin Tanislav {									\
1378*48ea7559SCosmin Tanislav 	.name = "adi,gpio" __stringify(i) "-mode",			\
1379*48ea7559SCosmin Tanislav 	.reg = AD74115_GPIO_CONFIG_X_REG(i),				\
1380*48ea7559SCosmin Tanislav 	.mask = AD74115_GPIO_CONFIG_SELECT_MASK,			\
1381*48ea7559SCosmin Tanislav 	.lookup_tbl = ad74115_gpio_mode_tbl,				\
1382*48ea7559SCosmin Tanislav 	.lookup_tbl_len = ARRAY_SIZE(ad74115_gpio_mode_tbl),		\
1383*48ea7559SCosmin Tanislav }
1384*48ea7559SCosmin Tanislav 
1385*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_gpio_mode_fw_props[] = {
1386*48ea7559SCosmin Tanislav 	AD74115_GPIO_MODE_FW_PROP(0),
1387*48ea7559SCosmin Tanislav 	AD74115_GPIO_MODE_FW_PROP(1),
1388*48ea7559SCosmin Tanislav 	AD74115_GPIO_MODE_FW_PROP(2),
1389*48ea7559SCosmin Tanislav 	AD74115_GPIO_MODE_FW_PROP(3),
1390*48ea7559SCosmin Tanislav };
1391*48ea7559SCosmin Tanislav 
1392*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_din_threshold_mode_fw_prop =
1393*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,digital-input-threshold-mode-fixed",
1394*48ea7559SCosmin Tanislav 			     AD74115_DIN_CONFIG2_REG, BIT(7));
1395*48ea7559SCosmin Tanislav 
1396*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_dac_bipolar_fw_prop =
1397*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,dac-bipolar", AD74115_OUTPUT_CONFIG_REG, BIT(7));
1398*48ea7559SCosmin Tanislav 
1399*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_ch_func_fw_prop =
1400*48ea7559SCosmin Tanislav 	AD74115_FW_PROP("adi,ch-func", AD74115_CH_FUNC_MAX,
1401*48ea7559SCosmin Tanislav 			AD74115_CH_FUNC_SETUP_REG, GENMASK(3, 0));
1402*48ea7559SCosmin Tanislav 
1403*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_rtd_mode_fw_prop =
1404*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,4-wire-rtd", AD74115_RTD3W4W_CONFIG_REG, BIT(3));
1405*48ea7559SCosmin Tanislav 
1406*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_din_range_fw_prop =
1407*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,digital-input-sink-range-high",
1408*48ea7559SCosmin Tanislav 			     AD74115_DIN_CONFIG1_REG, BIT(12));
1409*48ea7559SCosmin Tanislav 
1410*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_ext2_burnout_current_fw_prop =
1411*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_TBL("adi,ext2-burnout-current-nanoamp",
1412*48ea7559SCosmin Tanislav 			    ad74115_burnout_current_na_tbl,
1413*48ea7559SCosmin Tanislav 			    AD74115_BURNOUT_CONFIG_REG, GENMASK(14, 12));
1414*48ea7559SCosmin Tanislav 
1415*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_ext1_burnout_current_fw_prop =
1416*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_TBL("adi,ext1-burnout-current-nanoamp",
1417*48ea7559SCosmin Tanislav 			    ad74115_burnout_current_na_tbl,
1418*48ea7559SCosmin Tanislav 			    AD74115_BURNOUT_CONFIG_REG, GENMASK(9, 7));
1419*48ea7559SCosmin Tanislav 
1420*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_viout_burnout_current_fw_prop =
1421*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_TBL("adi,viout-burnout-current-nanoamp",
1422*48ea7559SCosmin Tanislav 			    ad74115_viout_burnout_current_na_tbl,
1423*48ea7559SCosmin Tanislav 			    AD74115_BURNOUT_CONFIG_REG, GENMASK(4, 2));
1424*48ea7559SCosmin Tanislav 
1425*48ea7559SCosmin Tanislav static const struct ad74115_fw_prop ad74115_fw_props[] = {
1426*48ea7559SCosmin Tanislav 	AD74115_FW_PROP("adi,conv2-mux", 3,
1427*48ea7559SCosmin Tanislav 			AD74115_ADC_CONFIG_REG, GENMASK(3, 2)),
1428*48ea7559SCosmin Tanislav 
1429*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL_NEG("adi,sense-agnd-buffer-low-power",
1430*48ea7559SCosmin Tanislav 				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(4)),
1431*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL_NEG("adi,lf-buffer-low-power",
1432*48ea7559SCosmin Tanislav 				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(3)),
1433*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL_NEG("adi,hf-buffer-low-power",
1434*48ea7559SCosmin Tanislav 				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(2)),
1435*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL_NEG("adi,ext2-buffer-low-power",
1436*48ea7559SCosmin Tanislav 				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(1)),
1437*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL_NEG("adi,ext1-buffer-low-power",
1438*48ea7559SCosmin Tanislav 				 AD74115_PWR_OPTIM_CONFIG_REG, BIT(0)),
1439*48ea7559SCosmin Tanislav 
1440*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,comparator-invert",
1441*48ea7559SCosmin Tanislav 			     AD74115_DIN_CONFIG1_REG, BIT(14)),
1442*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,digital-input-debounce-mode-counter-reset",
1443*48ea7559SCosmin Tanislav 			     AD74115_DIN_CONFIG1_REG, BIT(6)),
1444*48ea7559SCosmin Tanislav 
1445*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,digital-input-unbuffered",
1446*48ea7559SCosmin Tanislav 			     AD74115_DIN_CONFIG2_REG, BIT(10)),
1447*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,digital-input-short-circuit-detection",
1448*48ea7559SCosmin Tanislav 			     AD74115_DIN_CONFIG2_REG, BIT(9)),
1449*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,digital-input-open-circuit-detection",
1450*48ea7559SCosmin Tanislav 			     AD74115_DIN_CONFIG2_REG, BIT(8)),
1451*48ea7559SCosmin Tanislav 
1452*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,dac-current-limit-low",
1453*48ea7559SCosmin Tanislav 			     AD74115_OUTPUT_CONFIG_REG, BIT(0)),
1454*48ea7559SCosmin Tanislav 
1455*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,3-wire-rtd-excitation-swap",
1456*48ea7559SCosmin Tanislav 			     AD74115_RTD3W4W_CONFIG_REG, BIT(2)),
1457*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_TBL("adi,rtd-excitation-current-microamp",
1458*48ea7559SCosmin Tanislav 			    ad74115_rtd_excitation_current_ua_tbl,
1459*48ea7559SCosmin Tanislav 			    AD74115_RTD3W4W_CONFIG_REG, GENMASK(1, 0)),
1460*48ea7559SCosmin Tanislav 
1461*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,ext2-burnout-current-polarity-sourcing",
1462*48ea7559SCosmin Tanislav 			     AD74115_BURNOUT_CONFIG_REG, BIT(11)),
1463*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,ext1-burnout-current-polarity-sourcing",
1464*48ea7559SCosmin Tanislav 			     AD74115_BURNOUT_CONFIG_REG, BIT(6)),
1465*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,viout-burnout-current-polarity-sourcing",
1466*48ea7559SCosmin Tanislav 			     AD74115_BURNOUT_CONFIG_REG, BIT(1)),
1467*48ea7559SCosmin Tanislav 
1468*48ea7559SCosmin Tanislav 	AD74115_FW_PROP_BOOL("adi,charge-pump",
1469*48ea7559SCosmin Tanislav 			     AD74115_CHARGE_PUMP_REG, BIT(0)),
1470*48ea7559SCosmin Tanislav };
1471*48ea7559SCosmin Tanislav 
ad74115_apply_fw_prop(struct ad74115_state * st,const struct ad74115_fw_prop * prop,u32 * retval)1472*48ea7559SCosmin Tanislav static int ad74115_apply_fw_prop(struct ad74115_state *st,
1473*48ea7559SCosmin Tanislav 				 const struct ad74115_fw_prop *prop, u32 *retval)
1474*48ea7559SCosmin Tanislav {
1475*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1476*48ea7559SCosmin Tanislav 	u32 val = 0;
1477*48ea7559SCosmin Tanislav 	int ret;
1478*48ea7559SCosmin Tanislav 
1479*48ea7559SCosmin Tanislav 	if (prop->is_boolean) {
1480*48ea7559SCosmin Tanislav 		val = device_property_read_bool(dev, prop->name);
1481*48ea7559SCosmin Tanislav 	} else {
1482*48ea7559SCosmin Tanislav 		ret = device_property_read_u32(dev, prop->name, &val);
1483*48ea7559SCosmin Tanislav 		if (ret && prop->lookup_tbl)
1484*48ea7559SCosmin Tanislav 			val = prop->lookup_tbl[0];
1485*48ea7559SCosmin Tanislav 	}
1486*48ea7559SCosmin Tanislav 
1487*48ea7559SCosmin Tanislav 	*retval = val;
1488*48ea7559SCosmin Tanislav 
1489*48ea7559SCosmin Tanislav 	if (prop->negate)
1490*48ea7559SCosmin Tanislav 		val = !val;
1491*48ea7559SCosmin Tanislav 
1492*48ea7559SCosmin Tanislav 	if (prop->lookup_tbl)
1493*48ea7559SCosmin Tanislav 		ret = _ad74115_find_tbl_index(prop->lookup_tbl,
1494*48ea7559SCosmin Tanislav 					      prop->lookup_tbl_len, val, &val);
1495*48ea7559SCosmin Tanislav 	else if (prop->max && val > prop->max)
1496*48ea7559SCosmin Tanislav 		ret = -EINVAL;
1497*48ea7559SCosmin Tanislav 	else
1498*48ea7559SCosmin Tanislav 		ret = 0;
1499*48ea7559SCosmin Tanislav 
1500*48ea7559SCosmin Tanislav 	if (ret)
1501*48ea7559SCosmin Tanislav 		return dev_err_probe(dev, -EINVAL,
1502*48ea7559SCosmin Tanislav 				     "Invalid value %u for prop %s\n",
1503*48ea7559SCosmin Tanislav 				     val, prop->name);
1504*48ea7559SCosmin Tanislav 
1505*48ea7559SCosmin Tanislav 	WARN(!prop->mask, "Prop %s mask is empty\n", prop->name);
1506*48ea7559SCosmin Tanislav 
1507*48ea7559SCosmin Tanislav 	val = (val << __ffs(prop->mask)) & prop->mask;
1508*48ea7559SCosmin Tanislav 
1509*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, prop->reg, prop->mask, val);
1510*48ea7559SCosmin Tanislav }
1511*48ea7559SCosmin Tanislav 
ad74115_setup_adc_conv2_range(struct ad74115_state * st)1512*48ea7559SCosmin Tanislav static int ad74115_setup_adc_conv2_range(struct ad74115_state *st)
1513*48ea7559SCosmin Tanislav {
1514*48ea7559SCosmin Tanislav 	unsigned int tbl_len = ARRAY_SIZE(ad74115_adc_range_tbl);
1515*48ea7559SCosmin Tanislav 	const char *prop_name = "adi,conv2-range-microvolt";
1516*48ea7559SCosmin Tanislav 	s32 vals[2] = {
1517*48ea7559SCosmin Tanislav 		ad74115_adc_range_tbl[0][0],
1518*48ea7559SCosmin Tanislav 		ad74115_adc_range_tbl[0][1],
1519*48ea7559SCosmin Tanislav 	};
1520*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1521*48ea7559SCosmin Tanislav 	unsigned int i;
1522*48ea7559SCosmin Tanislav 
1523*48ea7559SCosmin Tanislav 	device_property_read_u32_array(dev, prop_name, vals, 2);
1524*48ea7559SCosmin Tanislav 
1525*48ea7559SCosmin Tanislav 	for (i = 0; i < tbl_len; i++)
1526*48ea7559SCosmin Tanislav 		if (vals[0] == ad74115_adc_range_tbl[i][0] &&
1527*48ea7559SCosmin Tanislav 		    vals[1] == ad74115_adc_range_tbl[i][1])
1528*48ea7559SCosmin Tanislav 			break;
1529*48ea7559SCosmin Tanislav 
1530*48ea7559SCosmin Tanislav 	if (i == tbl_len)
1531*48ea7559SCosmin Tanislav 		return dev_err_probe(dev, -EINVAL,
1532*48ea7559SCosmin Tanislav 				     "Invalid value %d, %d for prop %s\n",
1533*48ea7559SCosmin Tanislav 				     vals[0], vals[1], prop_name);
1534*48ea7559SCosmin Tanislav 
1535*48ea7559SCosmin Tanislav 	return regmap_update_bits(st->regmap, AD74115_ADC_CONFIG_REG,
1536*48ea7559SCosmin Tanislav 				  AD74115_ADC_CONFIG_CONV2_RANGE_MASK,
1537*48ea7559SCosmin Tanislav 				  FIELD_PREP(AD74115_ADC_CONFIG_CONV2_RANGE_MASK, i));
1538*48ea7559SCosmin Tanislav }
1539*48ea7559SCosmin Tanislav 
ad74115_setup_iio_channels(struct iio_dev * indio_dev)1540*48ea7559SCosmin Tanislav static int ad74115_setup_iio_channels(struct iio_dev *indio_dev)
1541*48ea7559SCosmin Tanislav {
1542*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
1543*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1544*48ea7559SCosmin Tanislav 	struct iio_chan_spec *channels;
1545*48ea7559SCosmin Tanislav 
1546*48ea7559SCosmin Tanislav 	channels = devm_kcalloc(dev, sizeof(*channels),
1547*48ea7559SCosmin Tanislav 				indio_dev->num_channels, GFP_KERNEL);
1548*48ea7559SCosmin Tanislav 	if (!channels)
1549*48ea7559SCosmin Tanislav 		return -ENOMEM;
1550*48ea7559SCosmin Tanislav 
1551*48ea7559SCosmin Tanislav 	indio_dev->channels = channels;
1552*48ea7559SCosmin Tanislav 
1553*48ea7559SCosmin Tanislav 	memcpy(channels, ad74115_channels_map[st->ch_func].channels,
1554*48ea7559SCosmin Tanislav 	       sizeof(*channels) * ad74115_channels_map[st->ch_func].num_channels);
1555*48ea7559SCosmin Tanislav 
1556*48ea7559SCosmin Tanislav 	if (channels[0].output && channels[0].channel == AD74115_DAC_CH_MAIN &&
1557*48ea7559SCosmin Tanislav 	    channels[0].type == IIO_VOLTAGE && !st->dac_hart_slew) {
1558*48ea7559SCosmin Tanislav 		channels[0].info_mask_separate |= BIT(IIO_CHAN_INFO_SAMP_FREQ);
1559*48ea7559SCosmin Tanislav 		channels[0].info_mask_separate_available |= BIT(IIO_CHAN_INFO_SAMP_FREQ);
1560*48ea7559SCosmin Tanislav 	}
1561*48ea7559SCosmin Tanislav 
1562*48ea7559SCosmin Tanislav 	return 0;
1563*48ea7559SCosmin Tanislav }
1564*48ea7559SCosmin Tanislav 
ad74115_setup_gpio_chip(struct ad74115_state * st)1565*48ea7559SCosmin Tanislav static int ad74115_setup_gpio_chip(struct ad74115_state *st)
1566*48ea7559SCosmin Tanislav {
1567*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1568*48ea7559SCosmin Tanislav 
1569*48ea7559SCosmin Tanislav 	if (!st->gpio_valid_mask)
1570*48ea7559SCosmin Tanislav 		return 0;
1571*48ea7559SCosmin Tanislav 
1572*48ea7559SCosmin Tanislav 	st->gc = (struct gpio_chip) {
1573*48ea7559SCosmin Tanislav 		.owner = THIS_MODULE,
1574*48ea7559SCosmin Tanislav 		.label = AD74115_NAME,
1575*48ea7559SCosmin Tanislav 		.base = -1,
1576*48ea7559SCosmin Tanislav 		.ngpio = AD74115_GPIO_NUM,
1577*48ea7559SCosmin Tanislav 		.parent = dev,
1578*48ea7559SCosmin Tanislav 		.can_sleep = true,
1579*48ea7559SCosmin Tanislav 		.init_valid_mask = ad74115_gpio_init_valid_mask,
1580*48ea7559SCosmin Tanislav 		.get_direction = ad74115_gpio_get_direction,
1581*48ea7559SCosmin Tanislav 		.direction_input = ad74115_gpio_direction_input,
1582*48ea7559SCosmin Tanislav 		.direction_output = ad74115_gpio_direction_output,
1583*48ea7559SCosmin Tanislav 		.get = ad74115_gpio_get,
1584*48ea7559SCosmin Tanislav 		.set = ad74115_gpio_set,
1585*48ea7559SCosmin Tanislav 	};
1586*48ea7559SCosmin Tanislav 
1587*48ea7559SCosmin Tanislav 	return devm_gpiochip_add_data(dev, &st->gc, st);
1588*48ea7559SCosmin Tanislav }
1589*48ea7559SCosmin Tanislav 
ad74115_setup_comp_gpio_chip(struct ad74115_state * st)1590*48ea7559SCosmin Tanislav static int ad74115_setup_comp_gpio_chip(struct ad74115_state *st)
1591*48ea7559SCosmin Tanislav {
1592*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1593*48ea7559SCosmin Tanislav 	u32 val;
1594*48ea7559SCosmin Tanislav 	int ret;
1595*48ea7559SCosmin Tanislav 
1596*48ea7559SCosmin Tanislav 	ret = regmap_read(st->regmap, AD74115_DIN_CONFIG1_REG, &val);
1597*48ea7559SCosmin Tanislav 	if (ret)
1598*48ea7559SCosmin Tanislav 		return ret;
1599*48ea7559SCosmin Tanislav 
1600*48ea7559SCosmin Tanislav 	if (!(val & AD74115_DIN_COMPARATOR_EN_MASK))
1601*48ea7559SCosmin Tanislav 		return 0;
1602*48ea7559SCosmin Tanislav 
1603*48ea7559SCosmin Tanislav 	st->comp_gc = (struct gpio_chip) {
1604*48ea7559SCosmin Tanislav 		.owner = THIS_MODULE,
1605*48ea7559SCosmin Tanislav 		.label = AD74115_NAME,
1606*48ea7559SCosmin Tanislav 		.base = -1,
1607*48ea7559SCosmin Tanislav 		.ngpio = 1,
1608*48ea7559SCosmin Tanislav 		.parent = dev,
1609*48ea7559SCosmin Tanislav 		.can_sleep = true,
1610*48ea7559SCosmin Tanislav 		.get_direction = ad74115_comp_gpio_get_direction,
1611*48ea7559SCosmin Tanislav 		.get = ad74115_comp_gpio_get,
1612*48ea7559SCosmin Tanislav 		.set_config = ad74115_comp_gpio_set_config,
1613*48ea7559SCosmin Tanislav 	};
1614*48ea7559SCosmin Tanislav 
1615*48ea7559SCosmin Tanislav 	return devm_gpiochip_add_data(dev, &st->comp_gc, st);
1616*48ea7559SCosmin Tanislav }
1617*48ea7559SCosmin Tanislav 
ad74115_setup(struct iio_dev * indio_dev)1618*48ea7559SCosmin Tanislav static int ad74115_setup(struct iio_dev *indio_dev)
1619*48ea7559SCosmin Tanislav {
1620*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
1621*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1622*48ea7559SCosmin Tanislav 	u32 val, din_range_high;
1623*48ea7559SCosmin Tanislav 	unsigned int i;
1624*48ea7559SCosmin Tanislav 	int ret;
1625*48ea7559SCosmin Tanislav 
1626*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_ch_func_fw_prop, &val);
1627*48ea7559SCosmin Tanislav 	if (ret)
1628*48ea7559SCosmin Tanislav 		return ret;
1629*48ea7559SCosmin Tanislav 
1630*48ea7559SCosmin Tanislav 	indio_dev->num_channels += ad74115_channels_map[val].num_channels;
1631*48ea7559SCosmin Tanislav 	st->ch_func = val;
1632*48ea7559SCosmin Tanislav 
1633*48ea7559SCosmin Tanislav 	ret = ad74115_setup_adc_conv2_range(st);
1634*48ea7559SCosmin Tanislav 	if (ret)
1635*48ea7559SCosmin Tanislav 		return ret;
1636*48ea7559SCosmin Tanislav 
1637*48ea7559SCosmin Tanislav 	val = device_property_read_bool(dev, "adi,dac-hart-slew");
1638*48ea7559SCosmin Tanislav 	if (val) {
1639*48ea7559SCosmin Tanislav 		st->dac_hart_slew = val;
1640*48ea7559SCosmin Tanislav 
1641*48ea7559SCosmin Tanislav 		ret = regmap_update_bits(st->regmap, AD74115_OUTPUT_CONFIG_REG,
1642*48ea7559SCosmin Tanislav 					 AD74115_OUTPUT_SLEW_EN_MASK,
1643*48ea7559SCosmin Tanislav 					 FIELD_PREP(AD74115_OUTPUT_SLEW_EN_MASK,
1644*48ea7559SCosmin Tanislav 						    AD74115_SLEW_MODE_HART));
1645*48ea7559SCosmin Tanislav 		if (ret)
1646*48ea7559SCosmin Tanislav 			return ret;
1647*48ea7559SCosmin Tanislav 	}
1648*48ea7559SCosmin Tanislav 
1649*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_din_range_fw_prop,
1650*48ea7559SCosmin Tanislav 				    &din_range_high);
1651*48ea7559SCosmin Tanislav 	if (ret)
1652*48ea7559SCosmin Tanislav 		return ret;
1653*48ea7559SCosmin Tanislav 
1654*48ea7559SCosmin Tanislav 	ret = device_property_read_u32(dev, "adi,digital-input-sink-microamp", &val);
1655*48ea7559SCosmin Tanislav 	if (!ret) {
1656*48ea7559SCosmin Tanislav 		if (din_range_high)
1657*48ea7559SCosmin Tanislav 			val = DIV_ROUND_CLOSEST(val, AD74115_DIN_SINK_LOW_STEP);
1658*48ea7559SCosmin Tanislav 		else
1659*48ea7559SCosmin Tanislav 			val = DIV_ROUND_CLOSEST(val, AD74115_DIN_SINK_HIGH_STEP);
1660*48ea7559SCosmin Tanislav 
1661*48ea7559SCosmin Tanislav 		if (val > AD74115_DIN_SINK_MAX)
1662*48ea7559SCosmin Tanislav 			val = AD74115_DIN_SINK_MAX;
1663*48ea7559SCosmin Tanislav 
1664*48ea7559SCosmin Tanislav 		ret = regmap_update_bits(st->regmap, AD74115_DIN_CONFIG1_REG,
1665*48ea7559SCosmin Tanislav 					 AD74115_DIN_SINK_MASK,
1666*48ea7559SCosmin Tanislav 					 FIELD_PREP(AD74115_DIN_SINK_MASK, val));
1667*48ea7559SCosmin Tanislav 		if (ret)
1668*48ea7559SCosmin Tanislav 			return ret;
1669*48ea7559SCosmin Tanislav 	}
1670*48ea7559SCosmin Tanislav 
1671*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_din_threshold_mode_fw_prop, &val);
1672*48ea7559SCosmin Tanislav 	if (ret)
1673*48ea7559SCosmin Tanislav 		return ret;
1674*48ea7559SCosmin Tanislav 
1675*48ea7559SCosmin Tanislav 	if (val == AD74115_DIN_THRESHOLD_MODE_AVDD) {
1676*48ea7559SCosmin Tanislav 		ret = regulator_get_voltage(st->avdd);
1677*48ea7559SCosmin Tanislav 		if (ret < 0)
1678*48ea7559SCosmin Tanislav 			return ret;
1679*48ea7559SCosmin Tanislav 
1680*48ea7559SCosmin Tanislav 		st->avdd_mv = ret / 1000;
1681*48ea7559SCosmin Tanislav 	}
1682*48ea7559SCosmin Tanislav 
1683*48ea7559SCosmin Tanislav 	st->din_threshold_mode = val;
1684*48ea7559SCosmin Tanislav 
1685*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_dac_bipolar_fw_prop, &val);
1686*48ea7559SCosmin Tanislav 	if (ret)
1687*48ea7559SCosmin Tanislav 		return ret;
1688*48ea7559SCosmin Tanislav 
1689*48ea7559SCosmin Tanislav 	st->dac_bipolar = val;
1690*48ea7559SCosmin Tanislav 
1691*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_rtd_mode_fw_prop, &val);
1692*48ea7559SCosmin Tanislav 	if (ret)
1693*48ea7559SCosmin Tanislav 		return ret;
1694*48ea7559SCosmin Tanislav 
1695*48ea7559SCosmin Tanislav 	st->rtd_mode_4_wire = val;
1696*48ea7559SCosmin Tanislav 
1697*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_ext2_burnout_current_fw_prop, &val);
1698*48ea7559SCosmin Tanislav 	if (ret)
1699*48ea7559SCosmin Tanislav 		return ret;
1700*48ea7559SCosmin Tanislav 
1701*48ea7559SCosmin Tanislav 	if (val) {
1702*48ea7559SCosmin Tanislav 		ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG,
1703*48ea7559SCosmin Tanislav 					 AD74115_BURNOUT_EXT2_EN_MASK,
1704*48ea7559SCosmin Tanislav 					 FIELD_PREP(AD74115_BURNOUT_EXT2_EN_MASK, 1));
1705*48ea7559SCosmin Tanislav 		if (ret)
1706*48ea7559SCosmin Tanislav 			return ret;
1707*48ea7559SCosmin Tanislav 	}
1708*48ea7559SCosmin Tanislav 
1709*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_ext1_burnout_current_fw_prop, &val);
1710*48ea7559SCosmin Tanislav 	if (ret)
1711*48ea7559SCosmin Tanislav 		return ret;
1712*48ea7559SCosmin Tanislav 
1713*48ea7559SCosmin Tanislav 	if (val) {
1714*48ea7559SCosmin Tanislav 		ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG,
1715*48ea7559SCosmin Tanislav 					 AD74115_BURNOUT_EXT1_EN_MASK,
1716*48ea7559SCosmin Tanislav 					 FIELD_PREP(AD74115_BURNOUT_EXT1_EN_MASK, 1));
1717*48ea7559SCosmin Tanislav 		if (ret)
1718*48ea7559SCosmin Tanislav 			return ret;
1719*48ea7559SCosmin Tanislav 	}
1720*48ea7559SCosmin Tanislav 
1721*48ea7559SCosmin Tanislav 	ret = ad74115_apply_fw_prop(st, &ad74115_viout_burnout_current_fw_prop, &val);
1722*48ea7559SCosmin Tanislav 	if (ret)
1723*48ea7559SCosmin Tanislav 		return ret;
1724*48ea7559SCosmin Tanislav 
1725*48ea7559SCosmin Tanislav 	if (val) {
1726*48ea7559SCosmin Tanislav 		ret = regmap_update_bits(st->regmap, AD74115_BURNOUT_CONFIG_REG,
1727*48ea7559SCosmin Tanislav 					 AD74115_BURNOUT_VIOUT_EN_MASK,
1728*48ea7559SCosmin Tanislav 					 FIELD_PREP(AD74115_BURNOUT_VIOUT_EN_MASK, 1));
1729*48ea7559SCosmin Tanislav 		if (ret)
1730*48ea7559SCosmin Tanislav 			return ret;
1731*48ea7559SCosmin Tanislav 	}
1732*48ea7559SCosmin Tanislav 
1733*48ea7559SCosmin Tanislav 	for (i = 0; i < AD74115_GPIO_NUM; i++) {
1734*48ea7559SCosmin Tanislav 		ret = ad74115_apply_fw_prop(st, &ad74115_gpio_mode_fw_props[i], &val);
1735*48ea7559SCosmin Tanislav 		if (ret)
1736*48ea7559SCosmin Tanislav 			return ret;
1737*48ea7559SCosmin Tanislav 
1738*48ea7559SCosmin Tanislav 		if (val == AD74115_GPIO_MODE_LOGIC)
1739*48ea7559SCosmin Tanislav 			st->gpio_valid_mask |= BIT(i);
1740*48ea7559SCosmin Tanislav 	}
1741*48ea7559SCosmin Tanislav 
1742*48ea7559SCosmin Tanislav 	for (i = 0; i < ARRAY_SIZE(ad74115_fw_props); i++) {
1743*48ea7559SCosmin Tanislav 		ret = ad74115_apply_fw_prop(st, &ad74115_fw_props[i], &val);
1744*48ea7559SCosmin Tanislav 		if (ret)
1745*48ea7559SCosmin Tanislav 			return ret;
1746*48ea7559SCosmin Tanislav 	}
1747*48ea7559SCosmin Tanislav 
1748*48ea7559SCosmin Tanislav 	ret = ad74115_setup_gpio_chip(st);
1749*48ea7559SCosmin Tanislav 	if (ret)
1750*48ea7559SCosmin Tanislav 		return ret;
1751*48ea7559SCosmin Tanislav 
1752*48ea7559SCosmin Tanislav 	ret = ad74115_setup_comp_gpio_chip(st);
1753*48ea7559SCosmin Tanislav 	if (ret)
1754*48ea7559SCosmin Tanislav 		return ret;
1755*48ea7559SCosmin Tanislav 
1756*48ea7559SCosmin Tanislav 	return ad74115_setup_iio_channels(indio_dev);
1757*48ea7559SCosmin Tanislav }
1758*48ea7559SCosmin Tanislav 
ad74115_reset(struct ad74115_state * st)1759*48ea7559SCosmin Tanislav static int ad74115_reset(struct ad74115_state *st)
1760*48ea7559SCosmin Tanislav {
1761*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1762*48ea7559SCosmin Tanislav 	struct gpio_desc *reset_gpio;
1763*48ea7559SCosmin Tanislav 	int ret;
1764*48ea7559SCosmin Tanislav 
1765*48ea7559SCosmin Tanislav 	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
1766*48ea7559SCosmin Tanislav 	if (IS_ERR(reset_gpio))
1767*48ea7559SCosmin Tanislav 		return dev_err_probe(dev, PTR_ERR(reset_gpio),
1768*48ea7559SCosmin Tanislav 				     "Failed to find reset GPIO\n");
1769*48ea7559SCosmin Tanislav 
1770*48ea7559SCosmin Tanislav 	if (reset_gpio) {
1771*48ea7559SCosmin Tanislav 		fsleep(100);
1772*48ea7559SCosmin Tanislav 
1773*48ea7559SCosmin Tanislav 		gpiod_set_value_cansleep(reset_gpio, 0);
1774*48ea7559SCosmin Tanislav 	} else {
1775*48ea7559SCosmin Tanislav 		ret = regmap_write(st->regmap, AD74115_CMD_KEY_REG,
1776*48ea7559SCosmin Tanislav 				   AD74115_CMD_KEY_RESET1);
1777*48ea7559SCosmin Tanislav 		if (ret)
1778*48ea7559SCosmin Tanislav 			return ret;
1779*48ea7559SCosmin Tanislav 
1780*48ea7559SCosmin Tanislav 		ret = regmap_write(st->regmap, AD74115_CMD_KEY_REG,
1781*48ea7559SCosmin Tanislav 				   AD74115_CMD_KEY_RESET2);
1782*48ea7559SCosmin Tanislav 		if (ret)
1783*48ea7559SCosmin Tanislav 			return ret;
1784*48ea7559SCosmin Tanislav 	}
1785*48ea7559SCosmin Tanislav 
1786*48ea7559SCosmin Tanislav 	fsleep(1000);
1787*48ea7559SCosmin Tanislav 
1788*48ea7559SCosmin Tanislav 	return 0;
1789*48ea7559SCosmin Tanislav }
1790*48ea7559SCosmin Tanislav 
ad74115_regulator_disable(void * data)1791*48ea7559SCosmin Tanislav static void ad74115_regulator_disable(void *data)
1792*48ea7559SCosmin Tanislav {
1793*48ea7559SCosmin Tanislav 	regulator_disable(data);
1794*48ea7559SCosmin Tanislav }
1795*48ea7559SCosmin Tanislav 
ad74115_setup_trigger(struct iio_dev * indio_dev)1796*48ea7559SCosmin Tanislav static int ad74115_setup_trigger(struct iio_dev *indio_dev)
1797*48ea7559SCosmin Tanislav {
1798*48ea7559SCosmin Tanislav 	struct ad74115_state *st = iio_priv(indio_dev);
1799*48ea7559SCosmin Tanislav 	struct device *dev = &st->spi->dev;
1800*48ea7559SCosmin Tanislav 	int ret;
1801*48ea7559SCosmin Tanislav 
1802*48ea7559SCosmin Tanislav 	st->irq = fwnode_irq_get_byname(dev_fwnode(dev), "adc_rdy");
1803*48ea7559SCosmin Tanislav 
1804*48ea7559SCosmin Tanislav 	if (st->irq == -EPROBE_DEFER)
1805*48ea7559SCosmin Tanislav 		return -EPROBE_DEFER;
1806*48ea7559SCosmin Tanislav 
1807*48ea7559SCosmin Tanislav 	if (st->irq < 0) {
1808*48ea7559SCosmin Tanislav 		st->irq = 0;
1809*48ea7559SCosmin Tanislav 		return 0;
1810*48ea7559SCosmin Tanislav 	}
1811*48ea7559SCosmin Tanislav 
1812*48ea7559SCosmin Tanislav 	ret = devm_request_irq(dev, st->irq, ad74115_adc_data_interrupt,
1813*48ea7559SCosmin Tanislav 			       0, AD74115_NAME, indio_dev);
1814*48ea7559SCosmin Tanislav 	if (ret)
1815*48ea7559SCosmin Tanislav 		return ret;
1816*48ea7559SCosmin Tanislav 
1817*48ea7559SCosmin Tanislav 	st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", AD74115_NAME,
1818*48ea7559SCosmin Tanislav 					  iio_device_id(indio_dev));
1819*48ea7559SCosmin Tanislav 	if (!st->trig)
1820*48ea7559SCosmin Tanislav 		return -ENOMEM;
1821*48ea7559SCosmin Tanislav 
1822*48ea7559SCosmin Tanislav 	st->trig->ops = &ad74115_trigger_ops;
1823*48ea7559SCosmin Tanislav 	iio_trigger_set_drvdata(st->trig, st);
1824*48ea7559SCosmin Tanislav 
1825*48ea7559SCosmin Tanislav 	ret = devm_iio_trigger_register(dev, st->trig);
1826*48ea7559SCosmin Tanislav 	if (ret)
1827*48ea7559SCosmin Tanislav 		return ret;
1828*48ea7559SCosmin Tanislav 
1829*48ea7559SCosmin Tanislav 	indio_dev->trig = iio_trigger_get(st->trig);
1830*48ea7559SCosmin Tanislav 
1831*48ea7559SCosmin Tanislav 	return 0;
1832*48ea7559SCosmin Tanislav }
1833*48ea7559SCosmin Tanislav 
ad74115_probe(struct spi_device * spi)1834*48ea7559SCosmin Tanislav static int ad74115_probe(struct spi_device *spi)
1835*48ea7559SCosmin Tanislav {
1836*48ea7559SCosmin Tanislav 	static const char * const regulator_names[] = {
1837*48ea7559SCosmin Tanislav 		"avcc", "dvcc", "dovdd", "refin",
1838*48ea7559SCosmin Tanislav 	};
1839*48ea7559SCosmin Tanislav 	struct device *dev = &spi->dev;
1840*48ea7559SCosmin Tanislav 	struct ad74115_state *st;
1841*48ea7559SCosmin Tanislav 	struct iio_dev *indio_dev;
1842*48ea7559SCosmin Tanislav 	int ret;
1843*48ea7559SCosmin Tanislav 
1844*48ea7559SCosmin Tanislav 	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
1845*48ea7559SCosmin Tanislav 	if (!indio_dev)
1846*48ea7559SCosmin Tanislav 		return -ENOMEM;
1847*48ea7559SCosmin Tanislav 
1848*48ea7559SCosmin Tanislav 	st = iio_priv(indio_dev);
1849*48ea7559SCosmin Tanislav 
1850*48ea7559SCosmin Tanislav 	st->spi = spi;
1851*48ea7559SCosmin Tanislav 	mutex_init(&st->lock);
1852*48ea7559SCosmin Tanislav 	init_completion(&st->adc_data_completion);
1853*48ea7559SCosmin Tanislav 
1854*48ea7559SCosmin Tanislav 	indio_dev->name = AD74115_NAME;
1855*48ea7559SCosmin Tanislav 	indio_dev->modes = INDIO_DIRECT_MODE;
1856*48ea7559SCosmin Tanislav 	indio_dev->info = &ad74115_info;
1857*48ea7559SCosmin Tanislav 
1858*48ea7559SCosmin Tanislav 	st->avdd = devm_regulator_get(dev, "avdd");
1859*48ea7559SCosmin Tanislav 	if (IS_ERR(st->avdd))
1860*48ea7559SCosmin Tanislav 		return PTR_ERR(st->avdd);
1861*48ea7559SCosmin Tanislav 
1862*48ea7559SCosmin Tanislav 	ret = regulator_enable(st->avdd);
1863*48ea7559SCosmin Tanislav 	if (ret) {
1864*48ea7559SCosmin Tanislav 		dev_err(dev, "Failed to enable avdd regulator\n");
1865*48ea7559SCosmin Tanislav 		return ret;
1866*48ea7559SCosmin Tanislav 	}
1867*48ea7559SCosmin Tanislav 
1868*48ea7559SCosmin Tanislav 	ret = devm_add_action_or_reset(dev, ad74115_regulator_disable, st->avdd);
1869*48ea7559SCosmin Tanislav 	if (ret)
1870*48ea7559SCosmin Tanislav 		return ret;
1871*48ea7559SCosmin Tanislav 
1872*48ea7559SCosmin Tanislav 	ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
1873*48ea7559SCosmin Tanislav 					     regulator_names);
1874*48ea7559SCosmin Tanislav 	if (ret)
1875*48ea7559SCosmin Tanislav 		return ret;
1876*48ea7559SCosmin Tanislav 
1877*48ea7559SCosmin Tanislav 	st->regmap = devm_regmap_init(dev, NULL, st, &ad74115_regmap_config);
1878*48ea7559SCosmin Tanislav 	if (IS_ERR(st->regmap))
1879*48ea7559SCosmin Tanislav 		return PTR_ERR(st->regmap);
1880*48ea7559SCosmin Tanislav 
1881*48ea7559SCosmin Tanislav 	ret = ad74115_reset(st);
1882*48ea7559SCosmin Tanislav 	if (ret)
1883*48ea7559SCosmin Tanislav 		return ret;
1884*48ea7559SCosmin Tanislav 
1885*48ea7559SCosmin Tanislav 	ret = ad74115_setup(indio_dev);
1886*48ea7559SCosmin Tanislav 	if (ret)
1887*48ea7559SCosmin Tanislav 		return ret;
1888*48ea7559SCosmin Tanislav 
1889*48ea7559SCosmin Tanislav 	ret = ad74115_setup_trigger(indio_dev);
1890*48ea7559SCosmin Tanislav 	if (ret)
1891*48ea7559SCosmin Tanislav 		return ret;
1892*48ea7559SCosmin Tanislav 
1893*48ea7559SCosmin Tanislav 	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
1894*48ea7559SCosmin Tanislav 					      ad74115_trigger_handler,
1895*48ea7559SCosmin Tanislav 					      &ad74115_buffer_ops);
1896*48ea7559SCosmin Tanislav 	if (ret)
1897*48ea7559SCosmin Tanislav 		return ret;
1898*48ea7559SCosmin Tanislav 
1899*48ea7559SCosmin Tanislav 	return devm_iio_device_register(dev, indio_dev);
1900*48ea7559SCosmin Tanislav }
1901*48ea7559SCosmin Tanislav 
ad74115_unregister_driver(struct spi_driver * spi)1902*48ea7559SCosmin Tanislav static int ad74115_unregister_driver(struct spi_driver *spi)
1903*48ea7559SCosmin Tanislav {
1904*48ea7559SCosmin Tanislav 	spi_unregister_driver(spi);
1905*48ea7559SCosmin Tanislav 
1906*48ea7559SCosmin Tanislav 	return 0;
1907*48ea7559SCosmin Tanislav }
1908*48ea7559SCosmin Tanislav 
ad74115_register_driver(struct spi_driver * spi)1909*48ea7559SCosmin Tanislav static int __init ad74115_register_driver(struct spi_driver *spi)
1910*48ea7559SCosmin Tanislav {
1911*48ea7559SCosmin Tanislav 	crc8_populate_msb(ad74115_crc8_table, AD74115_CRC_POLYNOMIAL);
1912*48ea7559SCosmin Tanislav 
1913*48ea7559SCosmin Tanislav 	return spi_register_driver(spi);
1914*48ea7559SCosmin Tanislav }
1915*48ea7559SCosmin Tanislav 
1916*48ea7559SCosmin Tanislav static const struct spi_device_id ad74115_spi_id[] = {
1917*48ea7559SCosmin Tanislav 	{ "ad74115h" },
1918*48ea7559SCosmin Tanislav 	{ }
1919*48ea7559SCosmin Tanislav };
1920*48ea7559SCosmin Tanislav 
1921*48ea7559SCosmin Tanislav MODULE_DEVICE_TABLE(spi, ad74115_spi_id);
1922*48ea7559SCosmin Tanislav 
1923*48ea7559SCosmin Tanislav static const struct of_device_id ad74115_dt_id[] = {
1924*48ea7559SCosmin Tanislav 	{ .compatible = "adi,ad74115h" },
1925*48ea7559SCosmin Tanislav 	{ }
1926*48ea7559SCosmin Tanislav };
1927*48ea7559SCosmin Tanislav MODULE_DEVICE_TABLE(of, ad74115_dt_id);
1928*48ea7559SCosmin Tanislav 
1929*48ea7559SCosmin Tanislav static struct spi_driver ad74115_driver = {
1930*48ea7559SCosmin Tanislav 	.driver = {
1931*48ea7559SCosmin Tanislav 		   .name = "ad74115",
1932*48ea7559SCosmin Tanislav 		   .of_match_table = ad74115_dt_id,
1933*48ea7559SCosmin Tanislav 	},
1934*48ea7559SCosmin Tanislav 	.probe = ad74115_probe,
1935*48ea7559SCosmin Tanislav 	.id_table = ad74115_spi_id,
1936*48ea7559SCosmin Tanislav };
1937*48ea7559SCosmin Tanislav 
1938*48ea7559SCosmin Tanislav module_driver(ad74115_driver,
1939*48ea7559SCosmin Tanislav 	      ad74115_register_driver, ad74115_unregister_driver);
1940*48ea7559SCosmin Tanislav 
1941*48ea7559SCosmin Tanislav MODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
1942*48ea7559SCosmin Tanislav MODULE_DESCRIPTION("Analog Devices AD74115 ADDAC");
1943*48ea7559SCosmin Tanislav MODULE_LICENSE("GPL");
1944