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