1a44ef7c4SIbrahim Tilki // SPDX-License-Identifier: GPL-2.0-only
2a44ef7c4SIbrahim Tilki /*
3a44ef7c4SIbrahim Tilki * MAX11410 SPI ADC driver
4a44ef7c4SIbrahim Tilki *
5a44ef7c4SIbrahim Tilki * Copyright 2022 Analog Devices Inc.
6a44ef7c4SIbrahim Tilki */
7a44ef7c4SIbrahim Tilki #include <linux/bitfield.h>
8a44ef7c4SIbrahim Tilki #include <linux/delay.h>
9a44ef7c4SIbrahim Tilki #include <linux/device.h>
10a44ef7c4SIbrahim Tilki #include <linux/err.h>
11a44ef7c4SIbrahim Tilki #include <linux/interrupt.h>
12a44ef7c4SIbrahim Tilki #include <linux/kernel.h>
13a44ef7c4SIbrahim Tilki #include <linux/module.h>
14a44ef7c4SIbrahim Tilki #include <linux/regmap.h>
15a44ef7c4SIbrahim Tilki #include <linux/regulator/consumer.h>
16a44ef7c4SIbrahim Tilki #include <linux/spi/spi.h>
17a44ef7c4SIbrahim Tilki
18591a6bc7SAndy Shevchenko #include <asm/unaligned.h>
19591a6bc7SAndy Shevchenko
20a44ef7c4SIbrahim Tilki #include <linux/iio/buffer.h>
21a44ef7c4SIbrahim Tilki #include <linux/iio/sysfs.h>
22a44ef7c4SIbrahim Tilki #include <linux/iio/trigger.h>
23a44ef7c4SIbrahim Tilki #include <linux/iio/trigger_consumer.h>
24a44ef7c4SIbrahim Tilki #include <linux/iio/triggered_buffer.h>
25a44ef7c4SIbrahim Tilki
26a44ef7c4SIbrahim Tilki #define MAX11410_REG_CONV_START 0x01
27a44ef7c4SIbrahim Tilki #define MAX11410_CONV_TYPE_SINGLE 0x00
28a44ef7c4SIbrahim Tilki #define MAX11410_CONV_TYPE_CONTINUOUS 0x01
29a44ef7c4SIbrahim Tilki #define MAX11410_REG_CAL_START 0x03
30a44ef7c4SIbrahim Tilki #define MAX11410_CAL_START_SELF 0x00
31a44ef7c4SIbrahim Tilki #define MAX11410_CAL_START_PGA 0x01
32a44ef7c4SIbrahim Tilki #define MAX11410_REG_GPIO_CTRL(ch) ((ch) ? 0x05 : 0x04)
33a44ef7c4SIbrahim Tilki #define MAX11410_GPIO_INTRB 0xC1
34a44ef7c4SIbrahim Tilki #define MAX11410_REG_FILTER 0x08
35a44ef7c4SIbrahim Tilki #define MAX11410_FILTER_RATE_MASK GENMASK(3, 0)
36a44ef7c4SIbrahim Tilki #define MAX11410_FILTER_RATE_MAX 0x0F
37a44ef7c4SIbrahim Tilki #define MAX11410_FILTER_LINEF_MASK GENMASK(5, 4)
38a44ef7c4SIbrahim Tilki #define MAX11410_FILTER_50HZ BIT(5)
39a44ef7c4SIbrahim Tilki #define MAX11410_FILTER_60HZ BIT(4)
40a44ef7c4SIbrahim Tilki #define MAX11410_REG_CTRL 0x09
41a44ef7c4SIbrahim Tilki #define MAX11410_CTRL_REFSEL_MASK GENMASK(2, 0)
42a44ef7c4SIbrahim Tilki #define MAX11410_CTRL_VREFN_BUF_BIT BIT(3)
43a44ef7c4SIbrahim Tilki #define MAX11410_CTRL_VREFP_BUF_BIT BIT(4)
44a44ef7c4SIbrahim Tilki #define MAX11410_CTRL_FORMAT_BIT BIT(5)
45a44ef7c4SIbrahim Tilki #define MAX11410_CTRL_UNIPOLAR_BIT BIT(6)
46a44ef7c4SIbrahim Tilki #define MAX11410_REG_MUX_CTRL0 0x0B
47a44ef7c4SIbrahim Tilki #define MAX11410_REG_PGA 0x0E
48a44ef7c4SIbrahim Tilki #define MAX11410_PGA_GAIN_MASK GENMASK(2, 0)
49a44ef7c4SIbrahim Tilki #define MAX11410_PGA_SIG_PATH_MASK GENMASK(5, 4)
50a44ef7c4SIbrahim Tilki #define MAX11410_PGA_SIG_PATH_BUFFERED 0x00
51a44ef7c4SIbrahim Tilki #define MAX11410_PGA_SIG_PATH_BYPASS 0x01
52a44ef7c4SIbrahim Tilki #define MAX11410_PGA_SIG_PATH_PGA 0x02
53a44ef7c4SIbrahim Tilki #define MAX11410_REG_DATA0 0x30
54a44ef7c4SIbrahim Tilki #define MAX11410_REG_STATUS 0x38
55a44ef7c4SIbrahim Tilki #define MAX11410_STATUS_CONV_READY_BIT BIT(0)
56a44ef7c4SIbrahim Tilki #define MAX11410_STATUS_CAL_READY_BIT BIT(2)
57a44ef7c4SIbrahim Tilki
58a44ef7c4SIbrahim Tilki #define MAX11410_REFSEL_AVDD_AGND 0x03
59a44ef7c4SIbrahim Tilki #define MAX11410_REFSEL_MAX 0x06
60a44ef7c4SIbrahim Tilki #define MAX11410_SIG_PATH_MAX 0x02
61a44ef7c4SIbrahim Tilki #define MAX11410_CHANNEL_INDEX_MAX 0x0A
62a44ef7c4SIbrahim Tilki #define MAX11410_AINP_AVDD 0x0A
63a44ef7c4SIbrahim Tilki #define MAX11410_AINN_GND 0x0A
64a44ef7c4SIbrahim Tilki
65a44ef7c4SIbrahim Tilki #define MAX11410_CONVERSION_TIMEOUT_MS 2000
66a44ef7c4SIbrahim Tilki #define MAX11410_CALIB_TIMEOUT_MS 2000
67a44ef7c4SIbrahim Tilki
68a44ef7c4SIbrahim Tilki #define MAX11410_SCALE_AVAIL_SIZE 8
69a44ef7c4SIbrahim Tilki
70a44ef7c4SIbrahim Tilki enum max11410_filter {
71a44ef7c4SIbrahim Tilki MAX11410_FILTER_FIR5060,
72a44ef7c4SIbrahim Tilki MAX11410_FILTER_FIR50,
73a44ef7c4SIbrahim Tilki MAX11410_FILTER_FIR60,
74a44ef7c4SIbrahim Tilki MAX11410_FILTER_SINC4,
75a44ef7c4SIbrahim Tilki };
76a44ef7c4SIbrahim Tilki
77a44ef7c4SIbrahim Tilki static const u8 max11410_sampling_len[] = {
78a44ef7c4SIbrahim Tilki [MAX11410_FILTER_FIR5060] = 5,
79a44ef7c4SIbrahim Tilki [MAX11410_FILTER_FIR50] = 6,
80a44ef7c4SIbrahim Tilki [MAX11410_FILTER_FIR60] = 6,
81a44ef7c4SIbrahim Tilki [MAX11410_FILTER_SINC4] = 10,
82a44ef7c4SIbrahim Tilki };
83a44ef7c4SIbrahim Tilki
84a44ef7c4SIbrahim Tilki static const int max11410_sampling_rates[4][10][2] = {
85a44ef7c4SIbrahim Tilki [MAX11410_FILTER_FIR5060] = {
86a44ef7c4SIbrahim Tilki { 1, 100000 },
87a44ef7c4SIbrahim Tilki { 2, 100000 },
88a44ef7c4SIbrahim Tilki { 4, 200000 },
89a44ef7c4SIbrahim Tilki { 8, 400000 },
90a44ef7c4SIbrahim Tilki { 16, 800000 }
91a44ef7c4SIbrahim Tilki },
92a44ef7c4SIbrahim Tilki [MAX11410_FILTER_FIR50] = {
93a44ef7c4SIbrahim Tilki { 1, 300000 },
94a44ef7c4SIbrahim Tilki { 2, 700000 },
95a44ef7c4SIbrahim Tilki { 5, 300000 },
96a44ef7c4SIbrahim Tilki { 10, 700000 },
97a44ef7c4SIbrahim Tilki { 21, 300000 },
98a44ef7c4SIbrahim Tilki { 40 }
99a44ef7c4SIbrahim Tilki },
100a44ef7c4SIbrahim Tilki [MAX11410_FILTER_FIR60] = {
101a44ef7c4SIbrahim Tilki { 1, 300000 },
102a44ef7c4SIbrahim Tilki { 2, 700000 },
103a44ef7c4SIbrahim Tilki { 5, 300000 },
104a44ef7c4SIbrahim Tilki { 10, 700000 },
105a44ef7c4SIbrahim Tilki { 21, 300000 },
106a44ef7c4SIbrahim Tilki { 40 }
107a44ef7c4SIbrahim Tilki },
108a44ef7c4SIbrahim Tilki [MAX11410_FILTER_SINC4] = {
109a44ef7c4SIbrahim Tilki { 4 },
110a44ef7c4SIbrahim Tilki { 10 },
111a44ef7c4SIbrahim Tilki { 20 },
112a44ef7c4SIbrahim Tilki { 40 },
113a44ef7c4SIbrahim Tilki { 60 },
114a44ef7c4SIbrahim Tilki { 120 },
115a44ef7c4SIbrahim Tilki { 240 },
116a44ef7c4SIbrahim Tilki { 480 },
117a44ef7c4SIbrahim Tilki { 960 },
118a44ef7c4SIbrahim Tilki { 1920 }
119a44ef7c4SIbrahim Tilki }
120a44ef7c4SIbrahim Tilki };
121a44ef7c4SIbrahim Tilki
122a44ef7c4SIbrahim Tilki struct max11410_channel_config {
123a44ef7c4SIbrahim Tilki u32 settling_time_us;
124a44ef7c4SIbrahim Tilki u32 *scale_avail;
125a44ef7c4SIbrahim Tilki u8 refsel;
126a44ef7c4SIbrahim Tilki u8 sig_path;
127a44ef7c4SIbrahim Tilki u8 gain;
128a44ef7c4SIbrahim Tilki bool bipolar;
129a44ef7c4SIbrahim Tilki bool buffered_vrefp;
130a44ef7c4SIbrahim Tilki bool buffered_vrefn;
131a44ef7c4SIbrahim Tilki };
132a44ef7c4SIbrahim Tilki
133a44ef7c4SIbrahim Tilki struct max11410_state {
134a44ef7c4SIbrahim Tilki struct spi_device *spi_dev;
135a44ef7c4SIbrahim Tilki struct iio_trigger *trig;
136a44ef7c4SIbrahim Tilki struct completion completion;
137a44ef7c4SIbrahim Tilki struct mutex lock; /* Prevent changing channel config during sampling */
138a44ef7c4SIbrahim Tilki struct regmap *regmap;
139a44ef7c4SIbrahim Tilki struct regulator *avdd;
140a44ef7c4SIbrahim Tilki struct regulator *vrefp[3];
141a44ef7c4SIbrahim Tilki struct regulator *vrefn[3];
142a44ef7c4SIbrahim Tilki struct max11410_channel_config *channels;
143a44ef7c4SIbrahim Tilki int irq;
144a44ef7c4SIbrahim Tilki struct {
145a44ef7c4SIbrahim Tilki u32 data __aligned(IIO_DMA_MINALIGN);
146a44ef7c4SIbrahim Tilki s64 ts __aligned(8);
147a44ef7c4SIbrahim Tilki } scan;
148a44ef7c4SIbrahim Tilki };
149a44ef7c4SIbrahim Tilki
150a44ef7c4SIbrahim Tilki static const struct iio_chan_spec chanspec_template = {
151a44ef7c4SIbrahim Tilki .type = IIO_VOLTAGE,
152a44ef7c4SIbrahim Tilki .indexed = 1,
153a44ef7c4SIbrahim Tilki .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
154a44ef7c4SIbrahim Tilki BIT(IIO_CHAN_INFO_SCALE) |
155a44ef7c4SIbrahim Tilki BIT(IIO_CHAN_INFO_OFFSET),
156a44ef7c4SIbrahim Tilki .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
157a44ef7c4SIbrahim Tilki .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
158a44ef7c4SIbrahim Tilki .scan_type = {
159a44ef7c4SIbrahim Tilki .sign = 's',
160a44ef7c4SIbrahim Tilki .realbits = 24,
161a44ef7c4SIbrahim Tilki .storagebits = 32,
162a44ef7c4SIbrahim Tilki .endianness = IIO_LE,
163a44ef7c4SIbrahim Tilki },
164a44ef7c4SIbrahim Tilki };
165a44ef7c4SIbrahim Tilki
max11410_reg_size(unsigned int reg)166a44ef7c4SIbrahim Tilki static unsigned int max11410_reg_size(unsigned int reg)
167a44ef7c4SIbrahim Tilki {
168a44ef7c4SIbrahim Tilki /* Registers from 0x00 to 0x10 are 1 byte, the rest are 3 bytes long. */
169a44ef7c4SIbrahim Tilki return reg <= 0x10 ? 1 : 3;
170a44ef7c4SIbrahim Tilki }
171a44ef7c4SIbrahim Tilki
max11410_write_reg(struct max11410_state * st,unsigned int reg,unsigned int val)172a44ef7c4SIbrahim Tilki static int max11410_write_reg(struct max11410_state *st, unsigned int reg,
173a44ef7c4SIbrahim Tilki unsigned int val)
174a44ef7c4SIbrahim Tilki {
175a44ef7c4SIbrahim Tilki /* This driver only needs to write 8-bit registers */
176a44ef7c4SIbrahim Tilki if (max11410_reg_size(reg) != 1)
177a44ef7c4SIbrahim Tilki return -EINVAL;
178a44ef7c4SIbrahim Tilki
179a44ef7c4SIbrahim Tilki return regmap_write(st->regmap, reg, val);
180a44ef7c4SIbrahim Tilki }
181a44ef7c4SIbrahim Tilki
max11410_read_reg(struct max11410_state * st,unsigned int reg,int * val)182a44ef7c4SIbrahim Tilki static int max11410_read_reg(struct max11410_state *st, unsigned int reg,
183a44ef7c4SIbrahim Tilki int *val)
184a44ef7c4SIbrahim Tilki {
185a44ef7c4SIbrahim Tilki int ret;
186a44ef7c4SIbrahim Tilki
187a44ef7c4SIbrahim Tilki if (max11410_reg_size(reg) == 3) {
188a44ef7c4SIbrahim Tilki ret = regmap_bulk_read(st->regmap, reg, &st->scan.data, 3);
189a44ef7c4SIbrahim Tilki if (ret)
190a44ef7c4SIbrahim Tilki return ret;
191a44ef7c4SIbrahim Tilki
192a44ef7c4SIbrahim Tilki *val = get_unaligned_be24(&st->scan.data);
193a44ef7c4SIbrahim Tilki return 0;
194a44ef7c4SIbrahim Tilki }
195a44ef7c4SIbrahim Tilki
196a44ef7c4SIbrahim Tilki return regmap_read(st->regmap, reg, val);
197a44ef7c4SIbrahim Tilki }
198a44ef7c4SIbrahim Tilki
max11410_get_vrefp(struct max11410_state * st,u8 refsel)199a44ef7c4SIbrahim Tilki static struct regulator *max11410_get_vrefp(struct max11410_state *st,
200a44ef7c4SIbrahim Tilki u8 refsel)
201a44ef7c4SIbrahim Tilki {
202a44ef7c4SIbrahim Tilki refsel = refsel % 4;
203a44ef7c4SIbrahim Tilki if (refsel == 3)
204a44ef7c4SIbrahim Tilki return st->avdd;
205a44ef7c4SIbrahim Tilki
206a44ef7c4SIbrahim Tilki return st->vrefp[refsel];
207a44ef7c4SIbrahim Tilki }
208a44ef7c4SIbrahim Tilki
max11410_get_vrefn(struct max11410_state * st,u8 refsel)209a44ef7c4SIbrahim Tilki static struct regulator *max11410_get_vrefn(struct max11410_state *st,
210a44ef7c4SIbrahim Tilki u8 refsel)
211a44ef7c4SIbrahim Tilki {
212a44ef7c4SIbrahim Tilki if (refsel > 2)
213a44ef7c4SIbrahim Tilki return NULL;
214a44ef7c4SIbrahim Tilki
215a44ef7c4SIbrahim Tilki return st->vrefn[refsel];
216a44ef7c4SIbrahim Tilki }
217a44ef7c4SIbrahim Tilki
218a44ef7c4SIbrahim Tilki static const struct regmap_config regmap_config = {
219a44ef7c4SIbrahim Tilki .reg_bits = 8,
220a44ef7c4SIbrahim Tilki .val_bits = 8,
221a44ef7c4SIbrahim Tilki .max_register = 0x39,
222a44ef7c4SIbrahim Tilki };
223a44ef7c4SIbrahim Tilki
max11410_notch_en_show(struct device * dev,struct device_attribute * devattr,char * buf)224a44ef7c4SIbrahim Tilki static ssize_t max11410_notch_en_show(struct device *dev,
225a44ef7c4SIbrahim Tilki struct device_attribute *devattr,
226a44ef7c4SIbrahim Tilki char *buf)
227a44ef7c4SIbrahim Tilki {
228a44ef7c4SIbrahim Tilki struct iio_dev *indio_dev = dev_get_drvdata(dev);
229a44ef7c4SIbrahim Tilki struct max11410_state *state = iio_priv(indio_dev);
230a44ef7c4SIbrahim Tilki struct iio_dev_attr *iio_attr = to_iio_dev_attr(devattr);
231a44ef7c4SIbrahim Tilki unsigned int val;
232a44ef7c4SIbrahim Tilki int ret;
233a44ef7c4SIbrahim Tilki
234a44ef7c4SIbrahim Tilki ret = max11410_read_reg(state, MAX11410_REG_FILTER, &val);
235a44ef7c4SIbrahim Tilki if (ret)
236a44ef7c4SIbrahim Tilki return ret;
237a44ef7c4SIbrahim Tilki
238a44ef7c4SIbrahim Tilki switch (iio_attr->address) {
239a44ef7c4SIbrahim Tilki case 0:
240a44ef7c4SIbrahim Tilki val = !FIELD_GET(MAX11410_FILTER_50HZ, val);
241a44ef7c4SIbrahim Tilki break;
242a44ef7c4SIbrahim Tilki case 1:
243a44ef7c4SIbrahim Tilki val = !FIELD_GET(MAX11410_FILTER_60HZ, val);
244a44ef7c4SIbrahim Tilki break;
245a44ef7c4SIbrahim Tilki case 2:
246a44ef7c4SIbrahim Tilki val = FIELD_GET(MAX11410_FILTER_LINEF_MASK, val) == 3;
247a44ef7c4SIbrahim Tilki break;
248a44ef7c4SIbrahim Tilki default:
249a44ef7c4SIbrahim Tilki return -EINVAL;
250a44ef7c4SIbrahim Tilki }
251a44ef7c4SIbrahim Tilki
252a44ef7c4SIbrahim Tilki return sysfs_emit(buf, "%d\n", val);
253a44ef7c4SIbrahim Tilki }
254a44ef7c4SIbrahim Tilki
max11410_notch_en_store(struct device * dev,struct device_attribute * devattr,const char * buf,size_t count)255a44ef7c4SIbrahim Tilki static ssize_t max11410_notch_en_store(struct device *dev,
256a44ef7c4SIbrahim Tilki struct device_attribute *devattr,
257a44ef7c4SIbrahim Tilki const char *buf, size_t count)
258a44ef7c4SIbrahim Tilki {
259a44ef7c4SIbrahim Tilki struct iio_dev_attr *iio_attr = to_iio_dev_attr(devattr);
260a44ef7c4SIbrahim Tilki struct iio_dev *indio_dev = dev_get_drvdata(dev);
261a44ef7c4SIbrahim Tilki struct max11410_state *state = iio_priv(indio_dev);
262a44ef7c4SIbrahim Tilki unsigned int filter_bits;
263a44ef7c4SIbrahim Tilki bool enable;
264a44ef7c4SIbrahim Tilki int ret;
265a44ef7c4SIbrahim Tilki
266a44ef7c4SIbrahim Tilki ret = kstrtobool(buf, &enable);
267a44ef7c4SIbrahim Tilki if (ret)
268a44ef7c4SIbrahim Tilki return ret;
269a44ef7c4SIbrahim Tilki
270a44ef7c4SIbrahim Tilki switch (iio_attr->address) {
271a44ef7c4SIbrahim Tilki case 0:
272a44ef7c4SIbrahim Tilki filter_bits = MAX11410_FILTER_50HZ;
273a44ef7c4SIbrahim Tilki break;
274a44ef7c4SIbrahim Tilki case 1:
275a44ef7c4SIbrahim Tilki filter_bits = MAX11410_FILTER_60HZ;
276a44ef7c4SIbrahim Tilki break;
277a44ef7c4SIbrahim Tilki case 2:
278a44ef7c4SIbrahim Tilki default:
279a44ef7c4SIbrahim Tilki filter_bits = MAX11410_FILTER_50HZ | MAX11410_FILTER_60HZ;
280a44ef7c4SIbrahim Tilki enable = !enable;
281a44ef7c4SIbrahim Tilki break;
282a44ef7c4SIbrahim Tilki }
283a44ef7c4SIbrahim Tilki
284a44ef7c4SIbrahim Tilki if (enable)
285a44ef7c4SIbrahim Tilki ret = regmap_clear_bits(state->regmap, MAX11410_REG_FILTER,
286a44ef7c4SIbrahim Tilki filter_bits);
287a44ef7c4SIbrahim Tilki else
288a44ef7c4SIbrahim Tilki ret = regmap_set_bits(state->regmap, MAX11410_REG_FILTER,
289a44ef7c4SIbrahim Tilki filter_bits);
290a44ef7c4SIbrahim Tilki
291a44ef7c4SIbrahim Tilki if (ret)
292a44ef7c4SIbrahim Tilki return ret;
293a44ef7c4SIbrahim Tilki
294a44ef7c4SIbrahim Tilki return count;
295a44ef7c4SIbrahim Tilki }
296a44ef7c4SIbrahim Tilki
in_voltage_filter2_notch_center_show(struct device * dev,struct device_attribute * devattr,char * buf)297a44ef7c4SIbrahim Tilki static ssize_t in_voltage_filter2_notch_center_show(struct device *dev,
298a44ef7c4SIbrahim Tilki struct device_attribute *devattr,
299a44ef7c4SIbrahim Tilki char *buf)
300a44ef7c4SIbrahim Tilki {
301a44ef7c4SIbrahim Tilki struct iio_dev *indio_dev = dev_get_drvdata(dev);
302a44ef7c4SIbrahim Tilki struct max11410_state *state = iio_priv(indio_dev);
303a44ef7c4SIbrahim Tilki int ret, reg, rate, filter;
304a44ef7c4SIbrahim Tilki
305a44ef7c4SIbrahim Tilki ret = regmap_read(state->regmap, MAX11410_REG_FILTER, ®);
306a44ef7c4SIbrahim Tilki if (ret)
307a44ef7c4SIbrahim Tilki return ret;
308a44ef7c4SIbrahim Tilki
309a44ef7c4SIbrahim Tilki rate = FIELD_GET(MAX11410_FILTER_RATE_MASK, reg);
310a44ef7c4SIbrahim Tilki rate = clamp_val(rate, 0,
311a44ef7c4SIbrahim Tilki max11410_sampling_len[MAX11410_FILTER_SINC4] - 1);
312a44ef7c4SIbrahim Tilki filter = max11410_sampling_rates[MAX11410_FILTER_SINC4][rate][0];
313a44ef7c4SIbrahim Tilki
314a44ef7c4SIbrahim Tilki return sysfs_emit(buf, "%d\n", filter);
315a44ef7c4SIbrahim Tilki }
316a44ef7c4SIbrahim Tilki
317a44ef7c4SIbrahim Tilki static IIO_CONST_ATTR(in_voltage_filter0_notch_center, "50");
318a44ef7c4SIbrahim Tilki static IIO_CONST_ATTR(in_voltage_filter1_notch_center, "60");
319a44ef7c4SIbrahim Tilki static IIO_DEVICE_ATTR_RO(in_voltage_filter2_notch_center, 2);
320a44ef7c4SIbrahim Tilki
321a44ef7c4SIbrahim Tilki static IIO_DEVICE_ATTR(in_voltage_filter0_notch_en, 0644,
322a44ef7c4SIbrahim Tilki max11410_notch_en_show, max11410_notch_en_store, 0);
323a44ef7c4SIbrahim Tilki static IIO_DEVICE_ATTR(in_voltage_filter1_notch_en, 0644,
324a44ef7c4SIbrahim Tilki max11410_notch_en_show, max11410_notch_en_store, 1);
325a44ef7c4SIbrahim Tilki static IIO_DEVICE_ATTR(in_voltage_filter2_notch_en, 0644,
326a44ef7c4SIbrahim Tilki max11410_notch_en_show, max11410_notch_en_store, 2);
327a44ef7c4SIbrahim Tilki
328a44ef7c4SIbrahim Tilki static struct attribute *max11410_attributes[] = {
329a44ef7c4SIbrahim Tilki &iio_const_attr_in_voltage_filter0_notch_center.dev_attr.attr,
330a44ef7c4SIbrahim Tilki &iio_const_attr_in_voltage_filter1_notch_center.dev_attr.attr,
331a44ef7c4SIbrahim Tilki &iio_dev_attr_in_voltage_filter2_notch_center.dev_attr.attr,
332a44ef7c4SIbrahim Tilki &iio_dev_attr_in_voltage_filter0_notch_en.dev_attr.attr,
333a44ef7c4SIbrahim Tilki &iio_dev_attr_in_voltage_filter1_notch_en.dev_attr.attr,
334a44ef7c4SIbrahim Tilki &iio_dev_attr_in_voltage_filter2_notch_en.dev_attr.attr,
335a44ef7c4SIbrahim Tilki NULL
336a44ef7c4SIbrahim Tilki };
337a44ef7c4SIbrahim Tilki
338a44ef7c4SIbrahim Tilki static const struct attribute_group max11410_attribute_group = {
339a44ef7c4SIbrahim Tilki .attrs = max11410_attributes,
340a44ef7c4SIbrahim Tilki };
341a44ef7c4SIbrahim Tilki
max11410_set_input_mux(struct max11410_state * st,u8 ainp,u8 ainn)342a44ef7c4SIbrahim Tilki static int max11410_set_input_mux(struct max11410_state *st, u8 ainp, u8 ainn)
343a44ef7c4SIbrahim Tilki {
344a44ef7c4SIbrahim Tilki if (ainp > MAX11410_CHANNEL_INDEX_MAX ||
345a44ef7c4SIbrahim Tilki ainn > MAX11410_CHANNEL_INDEX_MAX)
346a44ef7c4SIbrahim Tilki return -EINVAL;
347a44ef7c4SIbrahim Tilki
348a44ef7c4SIbrahim Tilki return max11410_write_reg(st, MAX11410_REG_MUX_CTRL0,
349a44ef7c4SIbrahim Tilki (ainp << 4) | ainn);
350a44ef7c4SIbrahim Tilki }
351a44ef7c4SIbrahim Tilki
max11410_configure_channel(struct max11410_state * st,struct iio_chan_spec const * chan)352a44ef7c4SIbrahim Tilki static int max11410_configure_channel(struct max11410_state *st,
353a44ef7c4SIbrahim Tilki struct iio_chan_spec const *chan)
354a44ef7c4SIbrahim Tilki {
355a44ef7c4SIbrahim Tilki struct max11410_channel_config cfg = st->channels[chan->address];
356a44ef7c4SIbrahim Tilki unsigned int regval;
357a44ef7c4SIbrahim Tilki int ret;
358a44ef7c4SIbrahim Tilki
359a44ef7c4SIbrahim Tilki if (chan->differential)
360a44ef7c4SIbrahim Tilki ret = max11410_set_input_mux(st, chan->channel, chan->channel2);
361a44ef7c4SIbrahim Tilki else
362a44ef7c4SIbrahim Tilki ret = max11410_set_input_mux(st, chan->channel,
363a44ef7c4SIbrahim Tilki MAX11410_AINN_GND);
364a44ef7c4SIbrahim Tilki
365a44ef7c4SIbrahim Tilki if (ret)
366a44ef7c4SIbrahim Tilki return ret;
367a44ef7c4SIbrahim Tilki
368a44ef7c4SIbrahim Tilki regval = FIELD_PREP(MAX11410_CTRL_VREFP_BUF_BIT, cfg.buffered_vrefp) |
369a44ef7c4SIbrahim Tilki FIELD_PREP(MAX11410_CTRL_VREFN_BUF_BIT, cfg.buffered_vrefn) |
370a44ef7c4SIbrahim Tilki FIELD_PREP(MAX11410_CTRL_REFSEL_MASK, cfg.refsel) |
371a44ef7c4SIbrahim Tilki FIELD_PREP(MAX11410_CTRL_UNIPOLAR_BIT, cfg.bipolar ? 0 : 1);
372a44ef7c4SIbrahim Tilki ret = regmap_update_bits(st->regmap, MAX11410_REG_CTRL,
373a44ef7c4SIbrahim Tilki MAX11410_CTRL_REFSEL_MASK |
37499b43a15SIbrahim Tilki MAX11410_CTRL_VREFP_BUF_BIT |
375a44ef7c4SIbrahim Tilki MAX11410_CTRL_VREFN_BUF_BIT |
376a44ef7c4SIbrahim Tilki MAX11410_CTRL_UNIPOLAR_BIT, regval);
377a44ef7c4SIbrahim Tilki if (ret)
378a44ef7c4SIbrahim Tilki return ret;
379a44ef7c4SIbrahim Tilki
380a44ef7c4SIbrahim Tilki regval = FIELD_PREP(MAX11410_PGA_SIG_PATH_MASK, cfg.sig_path) |
381a44ef7c4SIbrahim Tilki FIELD_PREP(MAX11410_PGA_GAIN_MASK, cfg.gain);
382a44ef7c4SIbrahim Tilki ret = regmap_write(st->regmap, MAX11410_REG_PGA, regval);
383a44ef7c4SIbrahim Tilki if (ret)
384a44ef7c4SIbrahim Tilki return ret;
385a44ef7c4SIbrahim Tilki
386a44ef7c4SIbrahim Tilki if (cfg.settling_time_us)
387a44ef7c4SIbrahim Tilki fsleep(cfg.settling_time_us);
388a44ef7c4SIbrahim Tilki
389a44ef7c4SIbrahim Tilki return 0;
390a44ef7c4SIbrahim Tilki }
391a44ef7c4SIbrahim Tilki
max11410_sample(struct max11410_state * st,int * sample_raw,struct iio_chan_spec const * chan)392a44ef7c4SIbrahim Tilki static int max11410_sample(struct max11410_state *st, int *sample_raw,
393a44ef7c4SIbrahim Tilki struct iio_chan_spec const *chan)
394a44ef7c4SIbrahim Tilki {
395a44ef7c4SIbrahim Tilki int val, ret;
396a44ef7c4SIbrahim Tilki
397a44ef7c4SIbrahim Tilki ret = max11410_configure_channel(st, chan);
398a44ef7c4SIbrahim Tilki if (ret)
399a44ef7c4SIbrahim Tilki return ret;
400a44ef7c4SIbrahim Tilki
401a44ef7c4SIbrahim Tilki if (st->irq > 0)
402a44ef7c4SIbrahim Tilki reinit_completion(&st->completion);
403a44ef7c4SIbrahim Tilki
404a44ef7c4SIbrahim Tilki /* Start Conversion */
405a44ef7c4SIbrahim Tilki ret = max11410_write_reg(st, MAX11410_REG_CONV_START,
406a44ef7c4SIbrahim Tilki MAX11410_CONV_TYPE_SINGLE);
407a44ef7c4SIbrahim Tilki if (ret)
408a44ef7c4SIbrahim Tilki return ret;
409a44ef7c4SIbrahim Tilki
410a44ef7c4SIbrahim Tilki if (st->irq > 0) {
411a44ef7c4SIbrahim Tilki /* Wait for an interrupt. */
412a44ef7c4SIbrahim Tilki ret = wait_for_completion_timeout(&st->completion,
413a44ef7c4SIbrahim Tilki msecs_to_jiffies(MAX11410_CONVERSION_TIMEOUT_MS));
414a44ef7c4SIbrahim Tilki if (!ret)
415a44ef7c4SIbrahim Tilki return -ETIMEDOUT;
416a44ef7c4SIbrahim Tilki } else {
417*7b3825e9SNuno Sá int ret2;
418*7b3825e9SNuno Sá
419a44ef7c4SIbrahim Tilki /* Wait for status register Conversion Ready flag */
420*7b3825e9SNuno Sá ret = read_poll_timeout(max11410_read_reg, ret2,
421*7b3825e9SNuno Sá ret2 || (val & MAX11410_STATUS_CONV_READY_BIT),
422a44ef7c4SIbrahim Tilki 5000, MAX11410_CONVERSION_TIMEOUT_MS * 1000,
423a44ef7c4SIbrahim Tilki true, st, MAX11410_REG_STATUS, &val);
424a44ef7c4SIbrahim Tilki if (ret)
425a44ef7c4SIbrahim Tilki return ret;
426*7b3825e9SNuno Sá if (ret2)
427*7b3825e9SNuno Sá return ret2;
428a44ef7c4SIbrahim Tilki }
429a44ef7c4SIbrahim Tilki
430a44ef7c4SIbrahim Tilki /* Read ADC Data */
431a44ef7c4SIbrahim Tilki return max11410_read_reg(st, MAX11410_REG_DATA0, sample_raw);
432a44ef7c4SIbrahim Tilki }
433a44ef7c4SIbrahim Tilki
max11410_get_scale(struct max11410_state * state,struct max11410_channel_config cfg)434a44ef7c4SIbrahim Tilki static int max11410_get_scale(struct max11410_state *state,
435a44ef7c4SIbrahim Tilki struct max11410_channel_config cfg)
436a44ef7c4SIbrahim Tilki {
437a44ef7c4SIbrahim Tilki struct regulator *vrefp, *vrefn;
438a44ef7c4SIbrahim Tilki int scale;
439a44ef7c4SIbrahim Tilki
440a44ef7c4SIbrahim Tilki vrefp = max11410_get_vrefp(state, cfg.refsel);
441a44ef7c4SIbrahim Tilki
442a44ef7c4SIbrahim Tilki scale = regulator_get_voltage(vrefp) / 1000;
443a44ef7c4SIbrahim Tilki vrefn = max11410_get_vrefn(state, cfg.refsel);
444a44ef7c4SIbrahim Tilki if (vrefn)
445a44ef7c4SIbrahim Tilki scale -= regulator_get_voltage(vrefn) / 1000;
446a44ef7c4SIbrahim Tilki
447a44ef7c4SIbrahim Tilki if (cfg.bipolar)
448a44ef7c4SIbrahim Tilki scale *= 2;
449a44ef7c4SIbrahim Tilki
450a44ef7c4SIbrahim Tilki return scale >> cfg.gain;
451a44ef7c4SIbrahim Tilki }
452a44ef7c4SIbrahim Tilki
max11410_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)453a44ef7c4SIbrahim Tilki static int max11410_read_raw(struct iio_dev *indio_dev,
454a44ef7c4SIbrahim Tilki struct iio_chan_spec const *chan,
455a44ef7c4SIbrahim Tilki int *val, int *val2, long info)
456a44ef7c4SIbrahim Tilki {
457a44ef7c4SIbrahim Tilki struct max11410_state *state = iio_priv(indio_dev);
458a44ef7c4SIbrahim Tilki struct max11410_channel_config cfg = state->channels[chan->address];
459a44ef7c4SIbrahim Tilki int ret, reg_val, filter, rate;
460a44ef7c4SIbrahim Tilki
461a44ef7c4SIbrahim Tilki switch (info) {
462a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_SCALE:
463a44ef7c4SIbrahim Tilki *val = max11410_get_scale(state, cfg);
464a44ef7c4SIbrahim Tilki *val2 = chan->scan_type.realbits;
465a44ef7c4SIbrahim Tilki return IIO_VAL_FRACTIONAL_LOG2;
466a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_OFFSET:
467a44ef7c4SIbrahim Tilki if (cfg.bipolar)
468a44ef7c4SIbrahim Tilki *val = -BIT(chan->scan_type.realbits - 1);
469a44ef7c4SIbrahim Tilki else
470a44ef7c4SIbrahim Tilki *val = 0;
471a44ef7c4SIbrahim Tilki
472a44ef7c4SIbrahim Tilki return IIO_VAL_INT;
473a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_RAW:
474a44ef7c4SIbrahim Tilki ret = iio_device_claim_direct_mode(indio_dev);
475a44ef7c4SIbrahim Tilki if (ret)
476a44ef7c4SIbrahim Tilki return ret;
477a44ef7c4SIbrahim Tilki
478a44ef7c4SIbrahim Tilki mutex_lock(&state->lock);
479a44ef7c4SIbrahim Tilki
480a44ef7c4SIbrahim Tilki ret = max11410_sample(state, ®_val, chan);
481a44ef7c4SIbrahim Tilki
482a44ef7c4SIbrahim Tilki mutex_unlock(&state->lock);
483a44ef7c4SIbrahim Tilki
484a44ef7c4SIbrahim Tilki iio_device_release_direct_mode(indio_dev);
485a44ef7c4SIbrahim Tilki
486a44ef7c4SIbrahim Tilki if (ret)
487a44ef7c4SIbrahim Tilki return ret;
488a44ef7c4SIbrahim Tilki
489a44ef7c4SIbrahim Tilki *val = reg_val;
490a44ef7c4SIbrahim Tilki
491a44ef7c4SIbrahim Tilki return IIO_VAL_INT;
492a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_SAMP_FREQ:
493a44ef7c4SIbrahim Tilki ret = regmap_read(state->regmap, MAX11410_REG_FILTER, ®_val);
494a44ef7c4SIbrahim Tilki if (ret)
495a44ef7c4SIbrahim Tilki return ret;
496a44ef7c4SIbrahim Tilki
497a44ef7c4SIbrahim Tilki filter = FIELD_GET(MAX11410_FILTER_LINEF_MASK, reg_val);
498a44ef7c4SIbrahim Tilki rate = reg_val & MAX11410_FILTER_RATE_MASK;
499a44ef7c4SIbrahim Tilki if (rate >= max11410_sampling_len[filter])
500a44ef7c4SIbrahim Tilki rate = max11410_sampling_len[filter] - 1;
501a44ef7c4SIbrahim Tilki
502a44ef7c4SIbrahim Tilki *val = max11410_sampling_rates[filter][rate][0];
503a44ef7c4SIbrahim Tilki *val2 = max11410_sampling_rates[filter][rate][1];
504a44ef7c4SIbrahim Tilki
505a44ef7c4SIbrahim Tilki return IIO_VAL_INT_PLUS_MICRO;
506a44ef7c4SIbrahim Tilki }
507a44ef7c4SIbrahim Tilki return -EINVAL;
508a44ef7c4SIbrahim Tilki }
509a44ef7c4SIbrahim Tilki
max11410_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)510a44ef7c4SIbrahim Tilki static int max11410_write_raw(struct iio_dev *indio_dev,
511a44ef7c4SIbrahim Tilki struct iio_chan_spec const *chan,
512a44ef7c4SIbrahim Tilki int val, int val2, long mask)
513a44ef7c4SIbrahim Tilki {
514a44ef7c4SIbrahim Tilki struct max11410_state *st = iio_priv(indio_dev);
515a44ef7c4SIbrahim Tilki int i, ret, reg_val, filter, gain;
516a44ef7c4SIbrahim Tilki u32 *scale_avail;
517a44ef7c4SIbrahim Tilki
518a44ef7c4SIbrahim Tilki switch (mask) {
519a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_SCALE:
520a44ef7c4SIbrahim Tilki scale_avail = st->channels[chan->address].scale_avail;
521a44ef7c4SIbrahim Tilki if (!scale_avail)
522a44ef7c4SIbrahim Tilki return -EOPNOTSUPP;
523a44ef7c4SIbrahim Tilki
524a44ef7c4SIbrahim Tilki /* Accept values in range 0.000001 <= scale < 1.000000 */
525a44ef7c4SIbrahim Tilki if (val != 0 || val2 == 0)
526a44ef7c4SIbrahim Tilki return -EINVAL;
527a44ef7c4SIbrahim Tilki
528a44ef7c4SIbrahim Tilki ret = iio_device_claim_direct_mode(indio_dev);
529a44ef7c4SIbrahim Tilki if (ret)
530a44ef7c4SIbrahim Tilki return ret;
531a44ef7c4SIbrahim Tilki
532a44ef7c4SIbrahim Tilki /* Convert from INT_PLUS_MICRO to FRACTIONAL_LOG2 */
533a44ef7c4SIbrahim Tilki val2 = val2 * DIV_ROUND_CLOSEST(BIT(24), 1000000);
534a44ef7c4SIbrahim Tilki val2 = DIV_ROUND_CLOSEST(scale_avail[0], val2);
535a44ef7c4SIbrahim Tilki gain = order_base_2(val2);
536a44ef7c4SIbrahim Tilki
537a44ef7c4SIbrahim Tilki st->channels[chan->address].gain = clamp_val(gain, 0, 7);
538a44ef7c4SIbrahim Tilki
539a44ef7c4SIbrahim Tilki iio_device_release_direct_mode(indio_dev);
540a44ef7c4SIbrahim Tilki
541a44ef7c4SIbrahim Tilki return 0;
542a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_SAMP_FREQ:
543a44ef7c4SIbrahim Tilki ret = iio_device_claim_direct_mode(indio_dev);
544a44ef7c4SIbrahim Tilki if (ret)
545a44ef7c4SIbrahim Tilki return ret;
546a44ef7c4SIbrahim Tilki
547a44ef7c4SIbrahim Tilki mutex_lock(&st->lock);
548a44ef7c4SIbrahim Tilki
549a44ef7c4SIbrahim Tilki ret = regmap_read(st->regmap, MAX11410_REG_FILTER, ®_val);
550a44ef7c4SIbrahim Tilki if (ret)
551a44ef7c4SIbrahim Tilki goto out;
552a44ef7c4SIbrahim Tilki
553a44ef7c4SIbrahim Tilki filter = FIELD_GET(MAX11410_FILTER_LINEF_MASK, reg_val);
554a44ef7c4SIbrahim Tilki
555a44ef7c4SIbrahim Tilki for (i = 0; i < max11410_sampling_len[filter]; ++i) {
556a44ef7c4SIbrahim Tilki if (val == max11410_sampling_rates[filter][i][0] &&
557a44ef7c4SIbrahim Tilki val2 == max11410_sampling_rates[filter][i][1])
558a44ef7c4SIbrahim Tilki break;
559a44ef7c4SIbrahim Tilki }
560a44ef7c4SIbrahim Tilki if (i == max11410_sampling_len[filter]) {
561a44ef7c4SIbrahim Tilki ret = -EINVAL;
562a44ef7c4SIbrahim Tilki goto out;
563a44ef7c4SIbrahim Tilki }
564a44ef7c4SIbrahim Tilki
565a44ef7c4SIbrahim Tilki ret = regmap_write_bits(st->regmap, MAX11410_REG_FILTER,
566a44ef7c4SIbrahim Tilki MAX11410_FILTER_RATE_MASK, i);
567a44ef7c4SIbrahim Tilki
568a44ef7c4SIbrahim Tilki out:
569a44ef7c4SIbrahim Tilki mutex_unlock(&st->lock);
570a44ef7c4SIbrahim Tilki iio_device_release_direct_mode(indio_dev);
571a44ef7c4SIbrahim Tilki
572a44ef7c4SIbrahim Tilki return ret;
573a44ef7c4SIbrahim Tilki default:
574a44ef7c4SIbrahim Tilki return -EINVAL;
575a44ef7c4SIbrahim Tilki }
576a44ef7c4SIbrahim Tilki }
577a44ef7c4SIbrahim Tilki
max11410_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long info)578a44ef7c4SIbrahim Tilki static int max11410_read_avail(struct iio_dev *indio_dev,
579a44ef7c4SIbrahim Tilki struct iio_chan_spec const *chan,
580a44ef7c4SIbrahim Tilki const int **vals, int *type, int *length,
581a44ef7c4SIbrahim Tilki long info)
582a44ef7c4SIbrahim Tilki {
583a44ef7c4SIbrahim Tilki struct max11410_state *st = iio_priv(indio_dev);
584a44ef7c4SIbrahim Tilki struct max11410_channel_config cfg;
585a44ef7c4SIbrahim Tilki int ret, reg_val, filter;
586a44ef7c4SIbrahim Tilki
587a44ef7c4SIbrahim Tilki switch (info) {
588a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_SAMP_FREQ:
589a44ef7c4SIbrahim Tilki ret = regmap_read(st->regmap, MAX11410_REG_FILTER, ®_val);
590a44ef7c4SIbrahim Tilki if (ret)
591a44ef7c4SIbrahim Tilki return ret;
592a44ef7c4SIbrahim Tilki
593a44ef7c4SIbrahim Tilki filter = FIELD_GET(MAX11410_FILTER_LINEF_MASK, reg_val);
594a44ef7c4SIbrahim Tilki
595a44ef7c4SIbrahim Tilki *vals = (const int *)max11410_sampling_rates[filter];
596a44ef7c4SIbrahim Tilki *length = max11410_sampling_len[filter] * 2;
597a44ef7c4SIbrahim Tilki *type = IIO_VAL_INT_PLUS_MICRO;
598a44ef7c4SIbrahim Tilki
599a44ef7c4SIbrahim Tilki return IIO_AVAIL_LIST;
600a44ef7c4SIbrahim Tilki case IIO_CHAN_INFO_SCALE:
601a44ef7c4SIbrahim Tilki cfg = st->channels[chan->address];
602a44ef7c4SIbrahim Tilki
603a44ef7c4SIbrahim Tilki if (!cfg.scale_avail)
604a44ef7c4SIbrahim Tilki return -EINVAL;
605a44ef7c4SIbrahim Tilki
606a44ef7c4SIbrahim Tilki *vals = cfg.scale_avail;
607a44ef7c4SIbrahim Tilki *length = MAX11410_SCALE_AVAIL_SIZE * 2;
608a44ef7c4SIbrahim Tilki *type = IIO_VAL_FRACTIONAL_LOG2;
609a44ef7c4SIbrahim Tilki
610a44ef7c4SIbrahim Tilki return IIO_AVAIL_LIST;
611a44ef7c4SIbrahim Tilki }
612a44ef7c4SIbrahim Tilki return -EINVAL;
613a44ef7c4SIbrahim Tilki }
614a44ef7c4SIbrahim Tilki
615a44ef7c4SIbrahim Tilki static const struct iio_info max11410_info = {
616a44ef7c4SIbrahim Tilki .read_raw = max11410_read_raw,
617a44ef7c4SIbrahim Tilki .write_raw = max11410_write_raw,
618a44ef7c4SIbrahim Tilki .read_avail = max11410_read_avail,
619a44ef7c4SIbrahim Tilki .attrs = &max11410_attribute_group,
620a44ef7c4SIbrahim Tilki };
621a44ef7c4SIbrahim Tilki
max11410_trigger_handler(int irq,void * p)622a44ef7c4SIbrahim Tilki static irqreturn_t max11410_trigger_handler(int irq, void *p)
623a44ef7c4SIbrahim Tilki {
624a44ef7c4SIbrahim Tilki struct iio_poll_func *pf = p;
625a44ef7c4SIbrahim Tilki struct iio_dev *indio_dev = pf->indio_dev;
626a44ef7c4SIbrahim Tilki struct max11410_state *st = iio_priv(indio_dev);
627a44ef7c4SIbrahim Tilki int ret;
628a44ef7c4SIbrahim Tilki
629a44ef7c4SIbrahim Tilki ret = max11410_read_reg(st, MAX11410_REG_DATA0, &st->scan.data);
630a44ef7c4SIbrahim Tilki if (ret) {
631a44ef7c4SIbrahim Tilki dev_err(&indio_dev->dev, "cannot read data\n");
632a44ef7c4SIbrahim Tilki goto out;
633a44ef7c4SIbrahim Tilki }
634a44ef7c4SIbrahim Tilki
635a44ef7c4SIbrahim Tilki iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
636a44ef7c4SIbrahim Tilki iio_get_time_ns(indio_dev));
637a44ef7c4SIbrahim Tilki
638a44ef7c4SIbrahim Tilki out:
639a44ef7c4SIbrahim Tilki iio_trigger_notify_done(indio_dev->trig);
640a44ef7c4SIbrahim Tilki
641a44ef7c4SIbrahim Tilki return IRQ_HANDLED;
642a44ef7c4SIbrahim Tilki }
643a44ef7c4SIbrahim Tilki
max11410_buffer_postenable(struct iio_dev * indio_dev)644a44ef7c4SIbrahim Tilki static int max11410_buffer_postenable(struct iio_dev *indio_dev)
645a44ef7c4SIbrahim Tilki {
646a44ef7c4SIbrahim Tilki struct max11410_state *st = iio_priv(indio_dev);
647a44ef7c4SIbrahim Tilki int scan_ch, ret;
648a44ef7c4SIbrahim Tilki
649a44ef7c4SIbrahim Tilki scan_ch = ffs(*indio_dev->active_scan_mask) - 1;
650a44ef7c4SIbrahim Tilki
651a44ef7c4SIbrahim Tilki ret = max11410_configure_channel(st, &indio_dev->channels[scan_ch]);
652a44ef7c4SIbrahim Tilki if (ret)
653a44ef7c4SIbrahim Tilki return ret;
654a44ef7c4SIbrahim Tilki
655a44ef7c4SIbrahim Tilki /* Start continuous conversion. */
656a44ef7c4SIbrahim Tilki return max11410_write_reg(st, MAX11410_REG_CONV_START,
657a44ef7c4SIbrahim Tilki MAX11410_CONV_TYPE_CONTINUOUS);
658a44ef7c4SIbrahim Tilki }
659a44ef7c4SIbrahim Tilki
max11410_buffer_predisable(struct iio_dev * indio_dev)660a44ef7c4SIbrahim Tilki static int max11410_buffer_predisable(struct iio_dev *indio_dev)
661a44ef7c4SIbrahim Tilki {
662a44ef7c4SIbrahim Tilki struct max11410_state *st = iio_priv(indio_dev);
663a44ef7c4SIbrahim Tilki
664a44ef7c4SIbrahim Tilki /* Stop continuous conversion. */
665a44ef7c4SIbrahim Tilki return max11410_write_reg(st, MAX11410_REG_CONV_START,
666a44ef7c4SIbrahim Tilki MAX11410_CONV_TYPE_SINGLE);
667a44ef7c4SIbrahim Tilki }
668a44ef7c4SIbrahim Tilki
669a44ef7c4SIbrahim Tilki static const struct iio_buffer_setup_ops max11410_buffer_ops = {
670a44ef7c4SIbrahim Tilki .postenable = &max11410_buffer_postenable,
671a44ef7c4SIbrahim Tilki .predisable = &max11410_buffer_predisable,
672a44ef7c4SIbrahim Tilki .validate_scan_mask = &iio_validate_scan_mask_onehot,
673a44ef7c4SIbrahim Tilki };
674a44ef7c4SIbrahim Tilki
675a44ef7c4SIbrahim Tilki static const struct iio_trigger_ops max11410_trigger_ops = {
676a44ef7c4SIbrahim Tilki .validate_device = iio_trigger_validate_own_device,
677a44ef7c4SIbrahim Tilki };
678a44ef7c4SIbrahim Tilki
max11410_interrupt(int irq,void * dev_id)679a44ef7c4SIbrahim Tilki static irqreturn_t max11410_interrupt(int irq, void *dev_id)
680a44ef7c4SIbrahim Tilki {
681a44ef7c4SIbrahim Tilki struct iio_dev *indio_dev = dev_id;
682a44ef7c4SIbrahim Tilki struct max11410_state *st = iio_priv(indio_dev);
683a44ef7c4SIbrahim Tilki
684a44ef7c4SIbrahim Tilki if (iio_buffer_enabled(indio_dev))
685f700e55eSMehdi Djait iio_trigger_poll_nested(st->trig);
686a44ef7c4SIbrahim Tilki else
687a44ef7c4SIbrahim Tilki complete(&st->completion);
688a44ef7c4SIbrahim Tilki
689a44ef7c4SIbrahim Tilki return IRQ_HANDLED;
690a44ef7c4SIbrahim Tilki };
691a44ef7c4SIbrahim Tilki
max11410_parse_channels(struct max11410_state * st,struct iio_dev * indio_dev)692a44ef7c4SIbrahim Tilki static int max11410_parse_channels(struct max11410_state *st,
693a44ef7c4SIbrahim Tilki struct iio_dev *indio_dev)
694a44ef7c4SIbrahim Tilki {
695a44ef7c4SIbrahim Tilki struct iio_chan_spec chanspec = chanspec_template;
696a44ef7c4SIbrahim Tilki struct device *dev = &st->spi_dev->dev;
697a44ef7c4SIbrahim Tilki struct max11410_channel_config *cfg;
698a44ef7c4SIbrahim Tilki struct iio_chan_spec *channels;
699a44ef7c4SIbrahim Tilki struct fwnode_handle *child;
700a44ef7c4SIbrahim Tilki u32 reference, sig_path;
701a44ef7c4SIbrahim Tilki const char *node_name;
702a44ef7c4SIbrahim Tilki u32 inputs[2], scale;
703a44ef7c4SIbrahim Tilki unsigned int num_ch;
704a44ef7c4SIbrahim Tilki int chan_idx = 0;
705a44ef7c4SIbrahim Tilki int ret, i;
706a44ef7c4SIbrahim Tilki
707a44ef7c4SIbrahim Tilki num_ch = device_get_child_node_count(dev);
708a44ef7c4SIbrahim Tilki if (num_ch == 0)
709a44ef7c4SIbrahim Tilki return dev_err_probe(&indio_dev->dev, -ENODEV,
710a44ef7c4SIbrahim Tilki "FW has no channels defined\n");
711a44ef7c4SIbrahim Tilki
712a44ef7c4SIbrahim Tilki /* Reserve space for soft timestamp channel */
713a44ef7c4SIbrahim Tilki num_ch++;
714a44ef7c4SIbrahim Tilki channels = devm_kcalloc(dev, num_ch, sizeof(*channels), GFP_KERNEL);
715a44ef7c4SIbrahim Tilki if (!channels)
716a44ef7c4SIbrahim Tilki return -ENOMEM;
717a44ef7c4SIbrahim Tilki
718a44ef7c4SIbrahim Tilki st->channels = devm_kcalloc(dev, num_ch, sizeof(*st->channels),
719a44ef7c4SIbrahim Tilki GFP_KERNEL);
720a44ef7c4SIbrahim Tilki if (!st->channels)
721a44ef7c4SIbrahim Tilki return -ENOMEM;
722a44ef7c4SIbrahim Tilki
723a44ef7c4SIbrahim Tilki device_for_each_child_node(dev, child) {
724a44ef7c4SIbrahim Tilki node_name = fwnode_get_name(child);
725a44ef7c4SIbrahim Tilki if (fwnode_property_present(child, "diff-channels")) {
726a44ef7c4SIbrahim Tilki ret = fwnode_property_read_u32_array(child,
727a44ef7c4SIbrahim Tilki "diff-channels",
728a44ef7c4SIbrahim Tilki inputs,
729a44ef7c4SIbrahim Tilki ARRAY_SIZE(inputs));
730a44ef7c4SIbrahim Tilki
731a44ef7c4SIbrahim Tilki chanspec.differential = 1;
732a44ef7c4SIbrahim Tilki } else {
733a44ef7c4SIbrahim Tilki ret = fwnode_property_read_u32(child, "reg", &inputs[0]);
734a44ef7c4SIbrahim Tilki
735a44ef7c4SIbrahim Tilki inputs[1] = 0;
736a44ef7c4SIbrahim Tilki chanspec.differential = 0;
737a44ef7c4SIbrahim Tilki }
738a44ef7c4SIbrahim Tilki if (ret) {
739a44ef7c4SIbrahim Tilki fwnode_handle_put(child);
740a44ef7c4SIbrahim Tilki return ret;
741a44ef7c4SIbrahim Tilki }
742a44ef7c4SIbrahim Tilki
743a44ef7c4SIbrahim Tilki if (inputs[0] > MAX11410_CHANNEL_INDEX_MAX ||
744a44ef7c4SIbrahim Tilki inputs[1] > MAX11410_CHANNEL_INDEX_MAX) {
745a44ef7c4SIbrahim Tilki fwnode_handle_put(child);
746a44ef7c4SIbrahim Tilki return dev_err_probe(&indio_dev->dev, -EINVAL,
747a44ef7c4SIbrahim Tilki "Invalid channel index for %s, should be less than %d\n",
748a44ef7c4SIbrahim Tilki node_name,
749a44ef7c4SIbrahim Tilki MAX11410_CHANNEL_INDEX_MAX + 1);
750a44ef7c4SIbrahim Tilki }
751a44ef7c4SIbrahim Tilki
752a44ef7c4SIbrahim Tilki cfg = &st->channels[chan_idx];
753a44ef7c4SIbrahim Tilki
754a44ef7c4SIbrahim Tilki reference = MAX11410_REFSEL_AVDD_AGND;
755a44ef7c4SIbrahim Tilki fwnode_property_read_u32(child, "adi,reference", &reference);
756a44ef7c4SIbrahim Tilki if (reference > MAX11410_REFSEL_MAX) {
757a44ef7c4SIbrahim Tilki fwnode_handle_put(child);
758a44ef7c4SIbrahim Tilki return dev_err_probe(&indio_dev->dev, -EINVAL,
759a44ef7c4SIbrahim Tilki "Invalid adi,reference value for %s, should be less than %d.\n",
760a44ef7c4SIbrahim Tilki node_name, MAX11410_REFSEL_MAX + 1);
761a44ef7c4SIbrahim Tilki }
762a44ef7c4SIbrahim Tilki
763a44ef7c4SIbrahim Tilki if (!max11410_get_vrefp(st, reference) ||
764a44ef7c4SIbrahim Tilki (!max11410_get_vrefn(st, reference) && reference <= 2)) {
765a44ef7c4SIbrahim Tilki fwnode_handle_put(child);
766a44ef7c4SIbrahim Tilki return dev_err_probe(&indio_dev->dev, -EINVAL,
767a44ef7c4SIbrahim Tilki "Invalid VREF configuration for %s, either specify corresponding VREF regulators or change adi,reference property.\n",
768a44ef7c4SIbrahim Tilki node_name);
769a44ef7c4SIbrahim Tilki }
770a44ef7c4SIbrahim Tilki
771a44ef7c4SIbrahim Tilki sig_path = MAX11410_PGA_SIG_PATH_BUFFERED;
772a44ef7c4SIbrahim Tilki fwnode_property_read_u32(child, "adi,input-mode", &sig_path);
773a44ef7c4SIbrahim Tilki if (sig_path > MAX11410_SIG_PATH_MAX) {
774a44ef7c4SIbrahim Tilki fwnode_handle_put(child);
775a44ef7c4SIbrahim Tilki return dev_err_probe(&indio_dev->dev, -EINVAL,
776a44ef7c4SIbrahim Tilki "Invalid adi,input-mode value for %s, should be less than %d.\n",
777a44ef7c4SIbrahim Tilki node_name, MAX11410_SIG_PATH_MAX + 1);
778a44ef7c4SIbrahim Tilki }
779a44ef7c4SIbrahim Tilki
780a44ef7c4SIbrahim Tilki fwnode_property_read_u32(child, "settling-time-us",
781a44ef7c4SIbrahim Tilki &cfg->settling_time_us);
782a44ef7c4SIbrahim Tilki cfg->bipolar = fwnode_property_read_bool(child, "bipolar");
783a44ef7c4SIbrahim Tilki cfg->buffered_vrefp = fwnode_property_read_bool(child, "adi,buffered-vrefp");
784a44ef7c4SIbrahim Tilki cfg->buffered_vrefn = fwnode_property_read_bool(child, "adi,buffered-vrefn");
785a44ef7c4SIbrahim Tilki cfg->refsel = reference;
786a44ef7c4SIbrahim Tilki cfg->sig_path = sig_path;
787a44ef7c4SIbrahim Tilki cfg->gain = 0;
788a44ef7c4SIbrahim Tilki
789a44ef7c4SIbrahim Tilki /* Enable scale_available property if input mode is PGA */
790a44ef7c4SIbrahim Tilki if (sig_path == MAX11410_PGA_SIG_PATH_PGA) {
791a44ef7c4SIbrahim Tilki __set_bit(IIO_CHAN_INFO_SCALE,
792a44ef7c4SIbrahim Tilki &chanspec.info_mask_separate_available);
793a44ef7c4SIbrahim Tilki cfg->scale_avail = devm_kcalloc(dev, MAX11410_SCALE_AVAIL_SIZE * 2,
794a44ef7c4SIbrahim Tilki sizeof(*cfg->scale_avail),
795a44ef7c4SIbrahim Tilki GFP_KERNEL);
796a44ef7c4SIbrahim Tilki if (!cfg->scale_avail) {
797a44ef7c4SIbrahim Tilki fwnode_handle_put(child);
798a44ef7c4SIbrahim Tilki return -ENOMEM;
799a44ef7c4SIbrahim Tilki }
800a44ef7c4SIbrahim Tilki
801a44ef7c4SIbrahim Tilki scale = max11410_get_scale(st, *cfg);
802a44ef7c4SIbrahim Tilki for (i = 0; i < MAX11410_SCALE_AVAIL_SIZE; i++) {
803a44ef7c4SIbrahim Tilki cfg->scale_avail[2 * i] = scale >> i;
804a44ef7c4SIbrahim Tilki cfg->scale_avail[2 * i + 1] = chanspec.scan_type.realbits;
805a44ef7c4SIbrahim Tilki }
806a44ef7c4SIbrahim Tilki } else {
807a44ef7c4SIbrahim Tilki __clear_bit(IIO_CHAN_INFO_SCALE,
808a44ef7c4SIbrahim Tilki &chanspec.info_mask_separate_available);
809a44ef7c4SIbrahim Tilki }
810a44ef7c4SIbrahim Tilki
811a44ef7c4SIbrahim Tilki chanspec.address = chan_idx;
812a44ef7c4SIbrahim Tilki chanspec.scan_index = chan_idx;
813a44ef7c4SIbrahim Tilki chanspec.channel = inputs[0];
814a44ef7c4SIbrahim Tilki chanspec.channel2 = inputs[1];
815a44ef7c4SIbrahim Tilki
816a44ef7c4SIbrahim Tilki channels[chan_idx] = chanspec;
817a44ef7c4SIbrahim Tilki chan_idx++;
818a44ef7c4SIbrahim Tilki }
819a44ef7c4SIbrahim Tilki
820a44ef7c4SIbrahim Tilki channels[chan_idx] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(chan_idx);
821a44ef7c4SIbrahim Tilki
822a44ef7c4SIbrahim Tilki indio_dev->num_channels = chan_idx + 1;
823a44ef7c4SIbrahim Tilki indio_dev->channels = channels;
824a44ef7c4SIbrahim Tilki
825a44ef7c4SIbrahim Tilki return 0;
826a44ef7c4SIbrahim Tilki }
827a44ef7c4SIbrahim Tilki
max11410_disable_reg(void * reg)828a44ef7c4SIbrahim Tilki static void max11410_disable_reg(void *reg)
829a44ef7c4SIbrahim Tilki {
830a44ef7c4SIbrahim Tilki regulator_disable(reg);
831a44ef7c4SIbrahim Tilki }
832a44ef7c4SIbrahim Tilki
max11410_init_vref(struct device * dev,struct regulator ** vref,const char * id)833a44ef7c4SIbrahim Tilki static int max11410_init_vref(struct device *dev,
834a44ef7c4SIbrahim Tilki struct regulator **vref,
835a44ef7c4SIbrahim Tilki const char *id)
836a44ef7c4SIbrahim Tilki {
837a44ef7c4SIbrahim Tilki struct regulator *reg;
838a44ef7c4SIbrahim Tilki int ret;
839a44ef7c4SIbrahim Tilki
840a44ef7c4SIbrahim Tilki reg = devm_regulator_get_optional(dev, id);
841a44ef7c4SIbrahim Tilki if (PTR_ERR(reg) == -ENODEV) {
842a44ef7c4SIbrahim Tilki *vref = NULL;
843a44ef7c4SIbrahim Tilki return 0;
844a44ef7c4SIbrahim Tilki } else if (IS_ERR(reg)) {
845a44ef7c4SIbrahim Tilki return PTR_ERR(reg);
846a44ef7c4SIbrahim Tilki }
847a44ef7c4SIbrahim Tilki ret = regulator_enable(reg);
848a44ef7c4SIbrahim Tilki if (ret)
849a44ef7c4SIbrahim Tilki return dev_err_probe(dev, ret,
850a44ef7c4SIbrahim Tilki "Failed to enable regulator %s\n", id);
851a44ef7c4SIbrahim Tilki
852a44ef7c4SIbrahim Tilki *vref = reg;
853a44ef7c4SIbrahim Tilki return devm_add_action_or_reset(dev, max11410_disable_reg, reg);
854a44ef7c4SIbrahim Tilki }
855a44ef7c4SIbrahim Tilki
max11410_calibrate(struct max11410_state * st,u32 cal_type)856a44ef7c4SIbrahim Tilki static int max11410_calibrate(struct max11410_state *st, u32 cal_type)
857a44ef7c4SIbrahim Tilki {
858*7b3825e9SNuno Sá int ret, ret2, val;
859a44ef7c4SIbrahim Tilki
860a44ef7c4SIbrahim Tilki ret = max11410_write_reg(st, MAX11410_REG_CAL_START, cal_type);
861a44ef7c4SIbrahim Tilki if (ret)
862a44ef7c4SIbrahim Tilki return ret;
863a44ef7c4SIbrahim Tilki
864a44ef7c4SIbrahim Tilki /* Wait for status register Calibration Ready flag */
865*7b3825e9SNuno Sá ret = read_poll_timeout(max11410_read_reg, ret2,
866*7b3825e9SNuno Sá ret2 || (val & MAX11410_STATUS_CAL_READY_BIT),
867a44ef7c4SIbrahim Tilki 50000, MAX11410_CALIB_TIMEOUT_MS * 1000, true,
868a44ef7c4SIbrahim Tilki st, MAX11410_REG_STATUS, &val);
869*7b3825e9SNuno Sá if (ret)
870*7b3825e9SNuno Sá return ret;
871*7b3825e9SNuno Sá
872*7b3825e9SNuno Sá return ret2;
873a44ef7c4SIbrahim Tilki }
874a44ef7c4SIbrahim Tilki
max11410_self_calibrate(struct max11410_state * st)875a44ef7c4SIbrahim Tilki static int max11410_self_calibrate(struct max11410_state *st)
876a44ef7c4SIbrahim Tilki {
877a44ef7c4SIbrahim Tilki int ret, i;
878a44ef7c4SIbrahim Tilki
879a44ef7c4SIbrahim Tilki ret = regmap_write_bits(st->regmap, MAX11410_REG_FILTER,
880a44ef7c4SIbrahim Tilki MAX11410_FILTER_RATE_MASK,
881a44ef7c4SIbrahim Tilki FIELD_PREP(MAX11410_FILTER_RATE_MASK,
882a44ef7c4SIbrahim Tilki MAX11410_FILTER_RATE_MAX));
883a44ef7c4SIbrahim Tilki if (ret)
884a44ef7c4SIbrahim Tilki return ret;
885a44ef7c4SIbrahim Tilki
886a44ef7c4SIbrahim Tilki ret = max11410_calibrate(st, MAX11410_CAL_START_SELF);
887a44ef7c4SIbrahim Tilki if (ret)
888a44ef7c4SIbrahim Tilki return ret;
889a44ef7c4SIbrahim Tilki
890a44ef7c4SIbrahim Tilki ret = regmap_write_bits(st->regmap, MAX11410_REG_PGA,
891a44ef7c4SIbrahim Tilki MAX11410_PGA_SIG_PATH_MASK,
892a44ef7c4SIbrahim Tilki FIELD_PREP(MAX11410_PGA_SIG_PATH_MASK,
893a44ef7c4SIbrahim Tilki MAX11410_PGA_SIG_PATH_PGA));
894a44ef7c4SIbrahim Tilki if (ret)
895a44ef7c4SIbrahim Tilki return ret;
896a44ef7c4SIbrahim Tilki
897a44ef7c4SIbrahim Tilki /* PGA calibrations */
898a44ef7c4SIbrahim Tilki for (i = 1; i < 8; ++i) {
899a44ef7c4SIbrahim Tilki ret = regmap_write_bits(st->regmap, MAX11410_REG_PGA,
900a44ef7c4SIbrahim Tilki MAX11410_PGA_GAIN_MASK, i);
901a44ef7c4SIbrahim Tilki if (ret)
902a44ef7c4SIbrahim Tilki return ret;
903a44ef7c4SIbrahim Tilki
904a44ef7c4SIbrahim Tilki ret = max11410_calibrate(st, MAX11410_CAL_START_PGA);
905a44ef7c4SIbrahim Tilki if (ret)
906a44ef7c4SIbrahim Tilki return ret;
907a44ef7c4SIbrahim Tilki }
908a44ef7c4SIbrahim Tilki
909a44ef7c4SIbrahim Tilki /* Cleanup */
910a44ef7c4SIbrahim Tilki ret = regmap_write_bits(st->regmap, MAX11410_REG_PGA,
911a44ef7c4SIbrahim Tilki MAX11410_PGA_GAIN_MASK, 0);
912a44ef7c4SIbrahim Tilki if (ret)
913a44ef7c4SIbrahim Tilki return ret;
914a44ef7c4SIbrahim Tilki
915a44ef7c4SIbrahim Tilki ret = regmap_write_bits(st->regmap, MAX11410_REG_FILTER,
916a44ef7c4SIbrahim Tilki MAX11410_FILTER_RATE_MASK, 0);
917a44ef7c4SIbrahim Tilki if (ret)
918a44ef7c4SIbrahim Tilki return ret;
919a44ef7c4SIbrahim Tilki
920a44ef7c4SIbrahim Tilki return regmap_write_bits(st->regmap, MAX11410_REG_PGA,
921a44ef7c4SIbrahim Tilki MAX11410_PGA_SIG_PATH_MASK,
922a44ef7c4SIbrahim Tilki FIELD_PREP(MAX11410_PGA_SIG_PATH_MASK,
923a44ef7c4SIbrahim Tilki MAX11410_PGA_SIG_PATH_BUFFERED));
924a44ef7c4SIbrahim Tilki }
925a44ef7c4SIbrahim Tilki
max11410_probe(struct spi_device * spi)926a44ef7c4SIbrahim Tilki static int max11410_probe(struct spi_device *spi)
927a44ef7c4SIbrahim Tilki {
928a44ef7c4SIbrahim Tilki const char *vrefp_regs[] = { "vref0p", "vref1p", "vref2p" };
929a44ef7c4SIbrahim Tilki const char *vrefn_regs[] = { "vref0n", "vref1n", "vref2n" };
930a44ef7c4SIbrahim Tilki struct device *dev = &spi->dev;
931a44ef7c4SIbrahim Tilki struct max11410_state *st;
932a44ef7c4SIbrahim Tilki struct iio_dev *indio_dev;
933a44ef7c4SIbrahim Tilki int ret, irqs[2];
934a44ef7c4SIbrahim Tilki int i;
935a44ef7c4SIbrahim Tilki
936a44ef7c4SIbrahim Tilki indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
937a44ef7c4SIbrahim Tilki if (!indio_dev)
938a44ef7c4SIbrahim Tilki return -ENOMEM;
939a44ef7c4SIbrahim Tilki
940a44ef7c4SIbrahim Tilki st = iio_priv(indio_dev);
941a44ef7c4SIbrahim Tilki st->spi_dev = spi;
942a44ef7c4SIbrahim Tilki init_completion(&st->completion);
943a44ef7c4SIbrahim Tilki mutex_init(&st->lock);
944a44ef7c4SIbrahim Tilki
945a44ef7c4SIbrahim Tilki indio_dev->name = "max11410";
946a44ef7c4SIbrahim Tilki indio_dev->modes = INDIO_DIRECT_MODE;
947a44ef7c4SIbrahim Tilki indio_dev->info = &max11410_info;
948a44ef7c4SIbrahim Tilki
949a44ef7c4SIbrahim Tilki st->regmap = devm_regmap_init_spi(spi, ®map_config);
950a44ef7c4SIbrahim Tilki if (IS_ERR(st->regmap))
951a44ef7c4SIbrahim Tilki return dev_err_probe(dev, PTR_ERR(st->regmap),
952a44ef7c4SIbrahim Tilki "regmap initialization failed\n");
953a44ef7c4SIbrahim Tilki
954a44ef7c4SIbrahim Tilki ret = max11410_init_vref(dev, &st->avdd, "avdd");
955a44ef7c4SIbrahim Tilki if (ret)
956a44ef7c4SIbrahim Tilki return ret;
957a44ef7c4SIbrahim Tilki
958a44ef7c4SIbrahim Tilki for (i = 0; i < ARRAY_SIZE(vrefp_regs); i++) {
959a44ef7c4SIbrahim Tilki ret = max11410_init_vref(dev, &st->vrefp[i], vrefp_regs[i]);
960a44ef7c4SIbrahim Tilki if (ret)
961a44ef7c4SIbrahim Tilki return ret;
962a44ef7c4SIbrahim Tilki
963a44ef7c4SIbrahim Tilki ret = max11410_init_vref(dev, &st->vrefn[i], vrefn_regs[i]);
964a44ef7c4SIbrahim Tilki if (ret)
965a44ef7c4SIbrahim Tilki return ret;
966a44ef7c4SIbrahim Tilki }
967a44ef7c4SIbrahim Tilki
968a44ef7c4SIbrahim Tilki /*
969a44ef7c4SIbrahim Tilki * Regulators must be configured before parsing channels for
970a44ef7c4SIbrahim Tilki * validating "adi,reference" property of each channel.
971a44ef7c4SIbrahim Tilki */
972a44ef7c4SIbrahim Tilki ret = max11410_parse_channels(st, indio_dev);
973a44ef7c4SIbrahim Tilki if (ret)
974a44ef7c4SIbrahim Tilki return ret;
975a44ef7c4SIbrahim Tilki
976a44ef7c4SIbrahim Tilki irqs[0] = fwnode_irq_get_byname(dev_fwnode(dev), "gpio0");
977a44ef7c4SIbrahim Tilki irqs[1] = fwnode_irq_get_byname(dev_fwnode(dev), "gpio1");
978a44ef7c4SIbrahim Tilki
979a44ef7c4SIbrahim Tilki if (irqs[0] > 0) {
980a44ef7c4SIbrahim Tilki st->irq = irqs[0];
981a44ef7c4SIbrahim Tilki ret = regmap_write(st->regmap, MAX11410_REG_GPIO_CTRL(0),
982a44ef7c4SIbrahim Tilki MAX11410_GPIO_INTRB);
983a44ef7c4SIbrahim Tilki } else if (irqs[1] > 0) {
984a44ef7c4SIbrahim Tilki st->irq = irqs[1];
985a44ef7c4SIbrahim Tilki ret = regmap_write(st->regmap, MAX11410_REG_GPIO_CTRL(1),
986a44ef7c4SIbrahim Tilki MAX11410_GPIO_INTRB);
987a44ef7c4SIbrahim Tilki } else if (spi->irq > 0) {
988a44ef7c4SIbrahim Tilki return dev_err_probe(dev, -ENODEV,
989a44ef7c4SIbrahim Tilki "no interrupt name specified");
990a44ef7c4SIbrahim Tilki }
991a44ef7c4SIbrahim Tilki
992a44ef7c4SIbrahim Tilki if (ret)
993a44ef7c4SIbrahim Tilki return ret;
994a44ef7c4SIbrahim Tilki
995a44ef7c4SIbrahim Tilki ret = regmap_set_bits(st->regmap, MAX11410_REG_CTRL,
996a44ef7c4SIbrahim Tilki MAX11410_CTRL_FORMAT_BIT);
997a44ef7c4SIbrahim Tilki if (ret)
998a44ef7c4SIbrahim Tilki return ret;
999a44ef7c4SIbrahim Tilki
1000a44ef7c4SIbrahim Tilki ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
1001a44ef7c4SIbrahim Tilki &max11410_trigger_handler,
1002a44ef7c4SIbrahim Tilki &max11410_buffer_ops);
1003a44ef7c4SIbrahim Tilki if (ret)
1004a44ef7c4SIbrahim Tilki return ret;
1005a44ef7c4SIbrahim Tilki
1006a44ef7c4SIbrahim Tilki if (st->irq > 0) {
1007a44ef7c4SIbrahim Tilki st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
1008a44ef7c4SIbrahim Tilki indio_dev->name,
1009a44ef7c4SIbrahim Tilki iio_device_id(indio_dev));
1010a44ef7c4SIbrahim Tilki if (!st->trig)
1011a44ef7c4SIbrahim Tilki return -ENOMEM;
1012a44ef7c4SIbrahim Tilki
1013a44ef7c4SIbrahim Tilki st->trig->ops = &max11410_trigger_ops;
1014a44ef7c4SIbrahim Tilki ret = devm_iio_trigger_register(dev, st->trig);
1015a44ef7c4SIbrahim Tilki if (ret)
1016a44ef7c4SIbrahim Tilki return ret;
1017a44ef7c4SIbrahim Tilki
1018a44ef7c4SIbrahim Tilki ret = devm_request_threaded_irq(dev, st->irq, NULL,
1019a44ef7c4SIbrahim Tilki &max11410_interrupt,
1020a44ef7c4SIbrahim Tilki IRQF_ONESHOT, "max11410",
1021a44ef7c4SIbrahim Tilki indio_dev);
1022a44ef7c4SIbrahim Tilki if (ret)
1023a44ef7c4SIbrahim Tilki return ret;
1024a44ef7c4SIbrahim Tilki }
1025a44ef7c4SIbrahim Tilki
1026a44ef7c4SIbrahim Tilki ret = max11410_self_calibrate(st);
1027a44ef7c4SIbrahim Tilki if (ret)
1028a44ef7c4SIbrahim Tilki return dev_err_probe(dev, ret,
1029a44ef7c4SIbrahim Tilki "cannot perform device self calibration\n");
1030a44ef7c4SIbrahim Tilki
1031a44ef7c4SIbrahim Tilki return devm_iio_device_register(dev, indio_dev);
1032a44ef7c4SIbrahim Tilki }
1033a44ef7c4SIbrahim Tilki
1034a44ef7c4SIbrahim Tilki static const struct of_device_id max11410_spi_of_id[] = {
1035a44ef7c4SIbrahim Tilki { .compatible = "adi,max11410" },
1036a44ef7c4SIbrahim Tilki { }
1037a44ef7c4SIbrahim Tilki };
1038a44ef7c4SIbrahim Tilki MODULE_DEVICE_TABLE(of, max11410_spi_of_id);
1039a44ef7c4SIbrahim Tilki
1040a44ef7c4SIbrahim Tilki static const struct spi_device_id max11410_id[] = {
1041a44ef7c4SIbrahim Tilki { "max11410" },
1042a44ef7c4SIbrahim Tilki { }
1043a44ef7c4SIbrahim Tilki };
1044a44ef7c4SIbrahim Tilki MODULE_DEVICE_TABLE(spi, max11410_id);
1045a44ef7c4SIbrahim Tilki
1046a44ef7c4SIbrahim Tilki static struct spi_driver max11410_driver = {
1047a44ef7c4SIbrahim Tilki .driver = {
1048a44ef7c4SIbrahim Tilki .name = "max11410",
1049a44ef7c4SIbrahim Tilki .of_match_table = max11410_spi_of_id,
1050a44ef7c4SIbrahim Tilki },
1051a44ef7c4SIbrahim Tilki .probe = max11410_probe,
1052a44ef7c4SIbrahim Tilki .id_table = max11410_id,
1053a44ef7c4SIbrahim Tilki };
1054a44ef7c4SIbrahim Tilki module_spi_driver(max11410_driver);
1055a44ef7c4SIbrahim Tilki
1056a44ef7c4SIbrahim Tilki MODULE_AUTHOR("David Jung <David.Jung@analog.com>");
1057a44ef7c4SIbrahim Tilki MODULE_AUTHOR("Ibrahim Tilki <Ibrahim.Tilki@analog.com>");
1058a44ef7c4SIbrahim Tilki MODULE_DESCRIPTION("Analog Devices MAX11410 ADC");
1059a44ef7c4SIbrahim Tilki MODULE_LICENSE("GPL");
1060