Commit | Line | Data |
---|---|---|
3a89b289 MF |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Driver for Microchip MCP3911, Two-channel Analog Front End | |
4 | * | |
5 | * Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com> | |
6 | * Copyright (C) 2018 Kent Gustavsson <kent@minoris.se> | |
7 | */ | |
5db9f38d MF |
8 | #include <linux/bitfield.h> |
9 | #include <linux/bits.h> | |
3a89b289 MF |
10 | #include <linux/clk.h> |
11 | #include <linux/delay.h> | |
12 | #include <linux/err.h> | |
3a89b289 | 13 | #include <linux/module.h> |
4efc1c61 JC |
14 | #include <linux/mod_devicetable.h> |
15 | #include <linux/property.h> | |
3a89b289 MF |
16 | #include <linux/regulator/consumer.h> |
17 | #include <linux/spi/spi.h> | |
18 | ||
5db9f38d MF |
19 | #include <linux/iio/iio.h> |
20 | #include <linux/iio/buffer.h> | |
21 | #include <linux/iio/triggered_buffer.h> | |
22 | #include <linux/iio/trigger_consumer.h> | |
23 | #include <linux/iio/trigger.h> | |
24 | ||
25 | #include <asm/unaligned.h> | |
26 | ||
3a89b289 MF |
27 | #define MCP3911_REG_CHANNEL0 0x00 |
28 | #define MCP3911_REG_CHANNEL1 0x03 | |
29 | #define MCP3911_REG_MOD 0x06 | |
30 | #define MCP3911_REG_PHASE 0x07 | |
31 | #define MCP3911_REG_GAIN 0x09 | |
8cf5f032 MF |
32 | #define MCP3911_GAIN_MASK(ch) (GENMASK(2, 0) << 3 * ch) |
33 | #define MCP3911_GAIN_VAL(ch, val) ((val << 3 * ch) & MCP3911_GAIN_MASK(ch)) | |
3a89b289 MF |
34 | |
35 | #define MCP3911_REG_STATUSCOM 0x0a | |
08a65f61 | 36 | #define MCP3911_STATUSCOM_DRHIZ BIT(12) |
5db9f38d | 37 | #define MCP3911_STATUSCOM_READ GENMASK(7, 6) |
3a89b289 MF |
38 | #define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4) |
39 | #define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3) | |
40 | #define MCP3911_STATUSCOM_EN_OFFCAL BIT(2) | |
41 | #define MCP3911_STATUSCOM_EN_GAINCAL BIT(1) | |
42 | ||
43 | #define MCP3911_REG_CONFIG 0x0c | |
44 | #define MCP3911_CONFIG_CLKEXT BIT(1) | |
45 | #define MCP3911_CONFIG_VREFEXT BIT(2) | |
6d965885 | 46 | #define MCP3911_CONFIG_OSR GENMASK(13, 11) |
3a89b289 MF |
47 | |
48 | #define MCP3911_REG_OFFCAL_CH0 0x0e | |
49 | #define MCP3911_REG_GAINCAL_CH0 0x11 | |
50 | #define MCP3911_REG_OFFCAL_CH1 0x14 | |
51 | #define MCP3911_REG_GAINCAL_CH1 0x17 | |
52 | #define MCP3911_REG_VREFCAL 0x1a | |
53 | ||
54 | #define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3) | |
55 | #define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6) | |
56 | ||
9e2238e3 MF |
57 | /* Internal voltage reference in mV */ |
58 | #define MCP3911_INT_VREF_MV 1200 | |
3a89b289 | 59 | |
815f1647 MF |
60 | #define MCP3911_REG_READ(reg, id) ((((reg) << 1) | ((id) << 6) | (1 << 0)) & 0xff) |
61 | #define MCP3911_REG_WRITE(reg, id) ((((reg) << 1) | ((id) << 6) | (0 << 0)) & 0xff) | |
aa6c77d0 | 62 | #define MCP3911_REG_MASK GENMASK(4, 1) |
3a89b289 MF |
63 | |
64 | #define MCP3911_NUM_CHANNELS 2 | |
8cf5f032 | 65 | #define MCP3911_NUM_SCALES 6 |
3a89b289 | 66 | |
6d965885 | 67 | static const int mcp3911_osr_table[] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 }; |
8cf5f032 | 68 | static u32 mcp3911_scale_table[MCP3911_NUM_SCALES][2]; |
6d965885 | 69 | |
3a89b289 MF |
70 | struct mcp3911 { |
71 | struct spi_device *spi; | |
72 | struct mutex lock; | |
73 | struct regulator *vref; | |
74 | struct clk *clki; | |
75 | u32 dev_addr; | |
08a65f61 | 76 | struct iio_trigger *trig; |
8cf5f032 | 77 | u32 gain[MCP3911_NUM_CHANNELS]; |
5db9f38d MF |
78 | struct { |
79 | u32 channels[MCP3911_NUM_CHANNELS]; | |
80 | s64 ts __aligned(8); | |
81 | } scan; | |
82 | ||
83 | u8 tx_buf __aligned(IIO_DMA_MINALIGN); | |
84 | u8 rx_buf[MCP3911_NUM_CHANNELS * 3]; | |
3a89b289 MF |
85 | }; |
86 | ||
87 | static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len) | |
88 | { | |
89 | int ret; | |
90 | ||
91 | reg = MCP3911_REG_READ(reg, adc->dev_addr); | |
92 | ret = spi_write_then_read(adc->spi, ®, 1, val, len); | |
93 | if (ret < 0) | |
94 | return ret; | |
95 | ||
96 | be32_to_cpus(val); | |
97 | *val >>= ((4 - len) * 8); | |
aa6c77d0 MF |
98 | dev_dbg(&adc->spi->dev, "reading 0x%x from register 0x%lx\n", *val, |
99 | FIELD_GET(MCP3911_REG_MASK, reg)); | |
3a89b289 MF |
100 | return ret; |
101 | } | |
102 | ||
103 | static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len) | |
104 | { | |
105 | dev_dbg(&adc->spi->dev, "writing 0x%x to register 0x%x\n", val, reg); | |
106 | ||
107 | val <<= (3 - len) * 8; | |
108 | cpu_to_be32s(&val); | |
109 | val |= MCP3911_REG_WRITE(reg, adc->dev_addr); | |
110 | ||
111 | return spi_write(adc->spi, &val, len + 1); | |
112 | } | |
113 | ||
114 | static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, | |
115 | u32 val, u8 len) | |
116 | { | |
117 | u32 tmp; | |
118 | int ret; | |
119 | ||
120 | ret = mcp3911_read(adc, reg, &tmp, len); | |
121 | if (ret) | |
122 | return ret; | |
123 | ||
124 | val &= mask; | |
125 | val |= tmp & ~mask; | |
126 | return mcp3911_write(adc, reg, val, len); | |
127 | } | |
128 | ||
6d965885 MF |
129 | static int mcp3911_write_raw_get_fmt(struct iio_dev *indio_dev, |
130 | struct iio_chan_spec const *chan, | |
131 | long mask) | |
132 | { | |
133 | switch (mask) { | |
134 | case IIO_CHAN_INFO_SCALE: | |
135 | return IIO_VAL_INT_PLUS_NANO; | |
136 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | |
137 | return IIO_VAL_INT; | |
138 | default: | |
139 | return IIO_VAL_INT_PLUS_NANO; | |
140 | } | |
141 | } | |
142 | ||
143 | static int mcp3911_read_avail(struct iio_dev *indio_dev, | |
144 | struct iio_chan_spec const *chan, | |
145 | const int **vals, int *type, int *length, | |
146 | long info) | |
147 | { | |
148 | switch (info) { | |
149 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | |
150 | *type = IIO_VAL_INT; | |
151 | *vals = mcp3911_osr_table; | |
152 | *length = ARRAY_SIZE(mcp3911_osr_table); | |
153 | return IIO_AVAIL_LIST; | |
8cf5f032 MF |
154 | case IIO_CHAN_INFO_SCALE: |
155 | *type = IIO_VAL_INT_PLUS_NANO; | |
156 | *vals = (int *)mcp3911_scale_table; | |
157 | *length = ARRAY_SIZE(mcp3911_scale_table) * 2; | |
158 | return IIO_AVAIL_LIST; | |
6d965885 MF |
159 | default: |
160 | return -EINVAL; | |
161 | } | |
162 | } | |
163 | ||
3a89b289 MF |
164 | static int mcp3911_read_raw(struct iio_dev *indio_dev, |
165 | struct iio_chan_spec const *channel, int *val, | |
166 | int *val2, long mask) | |
167 | { | |
168 | struct mcp3911 *adc = iio_priv(indio_dev); | |
169 | int ret = -EINVAL; | |
170 | ||
171 | mutex_lock(&adc->lock); | |
172 | switch (mask) { | |
173 | case IIO_CHAN_INFO_RAW: | |
174 | ret = mcp3911_read(adc, | |
175 | MCP3911_CHANNEL(channel->channel), val, 3); | |
176 | if (ret) | |
177 | goto out; | |
178 | ||
8f89e33b MF |
179 | *val = sign_extend32(*val, 23); |
180 | ||
3a89b289 MF |
181 | ret = IIO_VAL_INT; |
182 | break; | |
183 | ||
184 | case IIO_CHAN_INFO_OFFSET: | |
185 | ret = mcp3911_read(adc, | |
186 | MCP3911_OFFCAL(channel->channel), val, 3); | |
187 | if (ret) | |
188 | goto out; | |
189 | ||
190 | ret = IIO_VAL_INT; | |
191 | break; | |
6d965885 MF |
192 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
193 | ret = mcp3911_read(adc, MCP3911_REG_CONFIG, val, 2); | |
194 | if (ret) | |
195 | goto out; | |
196 | ||
197 | *val = FIELD_GET(MCP3911_CONFIG_OSR, *val); | |
198 | *val = 32 << *val; | |
199 | ret = IIO_VAL_INT; | |
200 | break; | |
3a89b289 MF |
201 | |
202 | case IIO_CHAN_INFO_SCALE: | |
8cf5f032 MF |
203 | *val = mcp3911_scale_table[ilog2(adc->gain[channel->channel])][0]; |
204 | *val2 = mcp3911_scale_table[ilog2(adc->gain[channel->channel])][1]; | |
205 | ret = IIO_VAL_INT_PLUS_NANO; | |
3a89b289 MF |
206 | break; |
207 | } | |
208 | ||
209 | out: | |
210 | mutex_unlock(&adc->lock); | |
211 | return ret; | |
212 | } | |
213 | ||
214 | static int mcp3911_write_raw(struct iio_dev *indio_dev, | |
215 | struct iio_chan_spec const *channel, int val, | |
216 | int val2, long mask) | |
217 | { | |
218 | struct mcp3911 *adc = iio_priv(indio_dev); | |
219 | int ret = -EINVAL; | |
220 | ||
221 | mutex_lock(&adc->lock); | |
222 | switch (mask) { | |
8cf5f032 MF |
223 | case IIO_CHAN_INFO_SCALE: |
224 | for (int i = 0; i < MCP3911_NUM_SCALES; i++) { | |
225 | if (val == mcp3911_scale_table[i][0] && | |
226 | val2 == mcp3911_scale_table[i][1]) { | |
227 | ||
228 | adc->gain[channel->channel] = BIT(i); | |
229 | ret = mcp3911_update(adc, MCP3911_REG_GAIN, | |
230 | MCP3911_GAIN_MASK(channel->channel), | |
231 | MCP3911_GAIN_VAL(channel->channel, i), 1); | |
232 | } | |
233 | } | |
234 | break; | |
3a89b289 MF |
235 | case IIO_CHAN_INFO_OFFSET: |
236 | if (val2 != 0) { | |
237 | ret = -EINVAL; | |
238 | goto out; | |
239 | } | |
240 | ||
241 | /* Write offset */ | |
242 | ret = mcp3911_write(adc, MCP3911_OFFCAL(channel->channel), val, | |
243 | 3); | |
244 | if (ret) | |
245 | goto out; | |
246 | ||
247 | /* Enable offset*/ | |
248 | ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, | |
249 | MCP3911_STATUSCOM_EN_OFFCAL, | |
250 | MCP3911_STATUSCOM_EN_OFFCAL, 2); | |
251 | break; | |
6d965885 MF |
252 | |
253 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | |
7578847b | 254 | for (int i = 0; i < ARRAY_SIZE(mcp3911_osr_table); i++) { |
6d965885 MF |
255 | if (val == mcp3911_osr_table[i]) { |
256 | val = FIELD_PREP(MCP3911_CONFIG_OSR, i); | |
257 | ret = mcp3911_update(adc, MCP3911_REG_CONFIG, MCP3911_CONFIG_OSR, | |
258 | val, 2); | |
259 | break; | |
260 | } | |
261 | } | |
262 | break; | |
3a89b289 MF |
263 | } |
264 | ||
265 | out: | |
266 | mutex_unlock(&adc->lock); | |
267 | return ret; | |
268 | } | |
269 | ||
8cf5f032 MF |
270 | static int mcp3911_calc_scale_table(struct mcp3911 *adc) |
271 | { | |
272 | u32 ref = MCP3911_INT_VREF_MV; | |
273 | u32 div; | |
274 | int ret; | |
275 | u64 tmp; | |
276 | ||
277 | if (adc->vref) { | |
278 | ret = regulator_get_voltage(adc->vref); | |
279 | if (ret < 0) { | |
280 | dev_err(&adc->spi->dev, | |
281 | "failed to get vref voltage: %d\n", | |
282 | ret); | |
283 | return ret; | |
284 | } | |
285 | ||
286 | ref = ret / 1000; | |
287 | } | |
288 | ||
289 | /* | |
290 | * For 24-bit Conversion | |
291 | * Raw = ((Voltage)/(Vref) * 2^23 * Gain * 1.5 | |
292 | * Voltage = Raw * (Vref)/(2^23 * Gain * 1.5) | |
293 | * | |
294 | * ref = Reference voltage | |
295 | * div = (2^23 * 1.5 * gain) = 12582912 * gain | |
296 | */ | |
297 | for (int i = 0; i < MCP3911_NUM_SCALES; i++) { | |
298 | div = 12582912 * BIT(i); | |
299 | tmp = div_s64((s64)ref * 1000000000LL, div); | |
300 | ||
301 | mcp3911_scale_table[i][0] = 0; | |
302 | mcp3911_scale_table[i][1] = tmp; | |
303 | } | |
304 | ||
305 | return 0; | |
306 | } | |
307 | ||
3a89b289 MF |
308 | #define MCP3911_CHAN(idx) { \ |
309 | .type = IIO_VOLTAGE, \ | |
310 | .indexed = 1, \ | |
311 | .channel = idx, \ | |
5db9f38d | 312 | .scan_index = idx, \ |
6d965885 | 313 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ |
3a89b289 MF |
314 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
315 | BIT(IIO_CHAN_INFO_OFFSET) | \ | |
316 | BIT(IIO_CHAN_INFO_SCALE), \ | |
8cf5f032 | 317 | .info_mask_shared_by_type_available = \ |
6d965885 | 318 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ |
8cf5f032 MF |
319 | .info_mask_separate_available = \ |
320 | BIT(IIO_CHAN_INFO_SCALE), \ | |
5db9f38d MF |
321 | .scan_type = { \ |
322 | .sign = 's', \ | |
323 | .realbits = 24, \ | |
324 | .storagebits = 32, \ | |
325 | .endianness = IIO_BE, \ | |
326 | }, \ | |
3a89b289 MF |
327 | } |
328 | ||
329 | static const struct iio_chan_spec mcp3911_channels[] = { | |
330 | MCP3911_CHAN(0), | |
331 | MCP3911_CHAN(1), | |
5db9f38d | 332 | IIO_CHAN_SOFT_TIMESTAMP(2), |
3a89b289 MF |
333 | }; |
334 | ||
5db9f38d MF |
335 | static irqreturn_t mcp3911_trigger_handler(int irq, void *p) |
336 | { | |
337 | struct iio_poll_func *pf = p; | |
338 | struct iio_dev *indio_dev = pf->indio_dev; | |
339 | struct mcp3911 *adc = iio_priv(indio_dev); | |
340 | struct spi_transfer xfer[] = { | |
341 | { | |
342 | .tx_buf = &adc->tx_buf, | |
343 | .len = 1, | |
344 | }, { | |
345 | .rx_buf = adc->rx_buf, | |
346 | .len = sizeof(adc->rx_buf), | |
347 | }, | |
348 | }; | |
349 | int scan_index; | |
350 | int i = 0; | |
351 | int ret; | |
352 | ||
353 | mutex_lock(&adc->lock); | |
354 | adc->tx_buf = MCP3911_REG_READ(MCP3911_CHANNEL(0), adc->dev_addr); | |
355 | ret = spi_sync_transfer(adc->spi, xfer, ARRAY_SIZE(xfer)); | |
356 | if (ret < 0) { | |
357 | dev_warn(&adc->spi->dev, | |
358 | "failed to get conversion data\n"); | |
359 | goto out; | |
360 | } | |
361 | ||
362 | for_each_set_bit(scan_index, indio_dev->active_scan_mask, indio_dev->masklength) { | |
363 | const struct iio_chan_spec *scan_chan = &indio_dev->channels[scan_index]; | |
364 | ||
365 | adc->scan.channels[i] = get_unaligned_be24(&adc->rx_buf[scan_chan->channel * 3]); | |
366 | i++; | |
367 | } | |
368 | iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan, | |
369 | iio_get_time_ns(indio_dev)); | |
370 | out: | |
371 | mutex_unlock(&adc->lock); | |
372 | iio_trigger_notify_done(indio_dev->trig); | |
373 | ||
374 | return IRQ_HANDLED; | |
375 | } | |
376 | ||
3a89b289 MF |
377 | static const struct iio_info mcp3911_info = { |
378 | .read_raw = mcp3911_read_raw, | |
379 | .write_raw = mcp3911_write_raw, | |
6d965885 MF |
380 | .read_avail = mcp3911_read_avail, |
381 | .write_raw_get_fmt = mcp3911_write_raw_get_fmt, | |
3a89b289 MF |
382 | }; |
383 | ||
4efc1c61 | 384 | static int mcp3911_config(struct mcp3911 *adc) |
3a89b289 | 385 | { |
4efc1c61 | 386 | struct device *dev = &adc->spi->dev; |
5db9f38d | 387 | u32 regval; |
3a89b289 MF |
388 | int ret; |
389 | ||
cfbd76d5 MF |
390 | ret = device_property_read_u32(dev, "microchip,device-addr", &adc->dev_addr); |
391 | ||
392 | /* | |
393 | * Fallback to "device-addr" due to historical mismatch between | |
394 | * dt-bindings and implementation | |
395 | */ | |
396 | if (ret) | |
397 | device_property_read_u32(dev, "device-addr", &adc->dev_addr); | |
3a89b289 MF |
398 | if (adc->dev_addr > 3) { |
399 | dev_err(&adc->spi->dev, | |
400 | "invalid device address (%i). Must be in range 0-3.\n", | |
401 | adc->dev_addr); | |
402 | return -EINVAL; | |
403 | } | |
404 | dev_dbg(&adc->spi->dev, "use device address %i\n", adc->dev_addr); | |
405 | ||
5db9f38d | 406 | ret = mcp3911_read(adc, MCP3911_REG_CONFIG, ®val, 2); |
3a89b289 MF |
407 | if (ret) |
408 | return ret; | |
409 | ||
5db9f38d | 410 | regval &= ~MCP3911_CONFIG_VREFEXT; |
3a89b289 MF |
411 | if (adc->vref) { |
412 | dev_dbg(&adc->spi->dev, "use external voltage reference\n"); | |
5db9f38d | 413 | regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 1); |
3a89b289 MF |
414 | } else { |
415 | dev_dbg(&adc->spi->dev, | |
416 | "use internal voltage reference (1.2V)\n"); | |
5db9f38d | 417 | regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 0); |
3a89b289 MF |
418 | } |
419 | ||
5db9f38d | 420 | regval &= ~MCP3911_CONFIG_CLKEXT; |
3a89b289 MF |
421 | if (adc->clki) { |
422 | dev_dbg(&adc->spi->dev, "use external clock as clocksource\n"); | |
5db9f38d | 423 | regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 1); |
3a89b289 MF |
424 | } else { |
425 | dev_dbg(&adc->spi->dev, | |
426 | "use crystal oscillator as clocksource\n"); | |
5db9f38d | 427 | regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 0); |
3a89b289 MF |
428 | } |
429 | ||
5db9f38d MF |
430 | ret = mcp3911_write(adc, MCP3911_REG_CONFIG, regval, 2); |
431 | if (ret) | |
432 | return ret; | |
433 | ||
434 | ret = mcp3911_read(adc, MCP3911_REG_STATUSCOM, ®val, 2); | |
435 | if (ret) | |
436 | return ret; | |
437 | ||
438 | /* Address counter incremented, cycle through register types */ | |
439 | regval &= ~MCP3911_STATUSCOM_READ; | |
440 | regval |= FIELD_PREP(MCP3911_STATUSCOM_READ, 0x02); | |
441 | ||
442 | return mcp3911_write(adc, MCP3911_REG_STATUSCOM, regval, 2); | |
3a89b289 MF |
443 | } |
444 | ||
0e0a07ad MF |
445 | static void mcp3911_cleanup_regulator(void *vref) |
446 | { | |
447 | regulator_disable(vref); | |
448 | } | |
449 | ||
08a65f61 MF |
450 | static int mcp3911_set_trigger_state(struct iio_trigger *trig, bool enable) |
451 | { | |
452 | struct mcp3911 *adc = iio_trigger_get_drvdata(trig); | |
453 | ||
454 | if (enable) | |
455 | enable_irq(adc->spi->irq); | |
456 | else | |
457 | disable_irq(adc->spi->irq); | |
458 | ||
459 | return 0; | |
460 | } | |
461 | ||
462 | static const struct iio_trigger_ops mcp3911_trigger_ops = { | |
463 | .validate_device = iio_trigger_validate_own_device, | |
464 | .set_trigger_state = mcp3911_set_trigger_state, | |
465 | }; | |
466 | ||
3a89b289 MF |
467 | static int mcp3911_probe(struct spi_device *spi) |
468 | { | |
469 | struct iio_dev *indio_dev; | |
470 | struct mcp3911 *adc; | |
471 | int ret; | |
472 | ||
473 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); | |
474 | if (!indio_dev) | |
475 | return -ENOMEM; | |
476 | ||
477 | adc = iio_priv(indio_dev); | |
478 | adc->spi = spi; | |
479 | ||
480 | adc->vref = devm_regulator_get_optional(&adc->spi->dev, "vref"); | |
481 | if (IS_ERR(adc->vref)) { | |
482 | if (PTR_ERR(adc->vref) == -ENODEV) { | |
483 | adc->vref = NULL; | |
484 | } else { | |
485 | dev_err(&adc->spi->dev, | |
486 | "failed to get regulator (%ld)\n", | |
487 | PTR_ERR(adc->vref)); | |
488 | return PTR_ERR(adc->vref); | |
489 | } | |
490 | ||
491 | } else { | |
492 | ret = regulator_enable(adc->vref); | |
493 | if (ret) | |
494 | return ret; | |
0e0a07ad MF |
495 | |
496 | ret = devm_add_action_or_reset(&spi->dev, | |
497 | mcp3911_cleanup_regulator, adc->vref); | |
498 | if (ret) | |
499 | return ret; | |
3a89b289 MF |
500 | } |
501 | ||
0e0a07ad | 502 | adc->clki = devm_clk_get_enabled(&adc->spi->dev, NULL); |
3a89b289 MF |
503 | if (IS_ERR(adc->clki)) { |
504 | if (PTR_ERR(adc->clki) == -ENOENT) { | |
505 | adc->clki = NULL; | |
506 | } else { | |
507 | dev_err(&adc->spi->dev, | |
508 | "failed to get adc clk (%ld)\n", | |
509 | PTR_ERR(adc->clki)); | |
0e0a07ad | 510 | return PTR_ERR(adc->clki); |
3a89b289 MF |
511 | } |
512 | } | |
513 | ||
4efc1c61 | 514 | ret = mcp3911_config(adc); |
3a89b289 | 515 | if (ret) |
0e0a07ad | 516 | return ret; |
3a89b289 | 517 | |
08a65f61 MF |
518 | if (device_property_read_bool(&adc->spi->dev, "microchip,data-ready-hiz")) |
519 | ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, MCP3911_STATUSCOM_DRHIZ, | |
520 | 0, 2); | |
521 | else | |
522 | ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, MCP3911_STATUSCOM_DRHIZ, | |
523 | MCP3911_STATUSCOM_DRHIZ, 2); | |
524 | if (ret) | |
525 | return ret; | |
526 | ||
8cf5f032 MF |
527 | ret = mcp3911_calc_scale_table(adc); |
528 | if (ret) | |
529 | return ret; | |
530 | ||
531 | /* Set gain to 1 for all channels */ | |
532 | for (int i = 0; i < MCP3911_NUM_CHANNELS; i++) { | |
533 | adc->gain[i] = 1; | |
534 | ret = mcp3911_update(adc, MCP3911_REG_GAIN, | |
535 | MCP3911_GAIN_MASK(i), | |
536 | MCP3911_GAIN_VAL(i, 0), 1); | |
537 | if (ret) | |
538 | return ret; | |
539 | } | |
540 | ||
3a89b289 MF |
541 | indio_dev->name = spi_get_device_id(spi)->name; |
542 | indio_dev->modes = INDIO_DIRECT_MODE; | |
543 | indio_dev->info = &mcp3911_info; | |
544 | spi_set_drvdata(spi, indio_dev); | |
545 | ||
546 | indio_dev->channels = mcp3911_channels; | |
547 | indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels); | |
548 | ||
549 | mutex_init(&adc->lock); | |
550 | ||
08a65f61 MF |
551 | if (spi->irq > 0) { |
552 | adc->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", | |
553 | indio_dev->name, | |
554 | iio_device_id(indio_dev)); | |
555 | if (!adc->trig) | |
a83695a6 | 556 | return -ENOMEM; |
08a65f61 MF |
557 | |
558 | adc->trig->ops = &mcp3911_trigger_ops; | |
559 | iio_trigger_set_drvdata(adc->trig, adc); | |
560 | ret = devm_iio_trigger_register(&spi->dev, adc->trig); | |
561 | if (ret) | |
562 | return ret; | |
563 | ||
564 | /* | |
565 | * The device generates interrupts as long as it is powered up. | |
566 | * Some platforms might not allow the option to power it down so | |
567 | * don't enable the interrupt to avoid extra load on the system. | |
568 | */ | |
569 | ret = devm_request_irq(&spi->dev, spi->irq, | |
570 | &iio_trigger_generic_data_rdy_poll, IRQF_NO_AUTOEN | IRQF_ONESHOT, | |
571 | indio_dev->name, adc->trig); | |
572 | if (ret) | |
573 | return ret; | |
574 | } | |
575 | ||
5db9f38d MF |
576 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, |
577 | NULL, | |
578 | mcp3911_trigger_handler, NULL); | |
579 | if (ret) | |
580 | return ret; | |
581 | ||
0e0a07ad | 582 | return devm_iio_device_register(&adc->spi->dev, indio_dev); |
3a89b289 MF |
583 | } |
584 | ||
585 | static const struct of_device_id mcp3911_dt_ids[] = { | |
586 | { .compatible = "microchip,mcp3911" }, | |
587 | { } | |
588 | }; | |
589 | MODULE_DEVICE_TABLE(of, mcp3911_dt_ids); | |
590 | ||
591 | static const struct spi_device_id mcp3911_id[] = { | |
592 | { "mcp3911", 0 }, | |
593 | { } | |
594 | }; | |
595 | MODULE_DEVICE_TABLE(spi, mcp3911_id); | |
596 | ||
597 | static struct spi_driver mcp3911_driver = { | |
598 | .driver = { | |
599 | .name = "mcp3911", | |
600 | .of_match_table = mcp3911_dt_ids, | |
601 | }, | |
602 | .probe = mcp3911_probe, | |
3a89b289 MF |
603 | .id_table = mcp3911_id, |
604 | }; | |
605 | module_spi_driver(mcp3911_driver); | |
606 | ||
607 | MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>"); | |
608 | MODULE_AUTHOR("Kent Gustavsson <kent@minoris.se>"); | |
609 | MODULE_DESCRIPTION("Microchip Technology MCP3911"); | |
610 | MODULE_LICENSE("GPL v2"); |