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