1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * ADXRS290 SPI Gyroscope Driver |
4 | * |
5 | * Copyright (C) 2020 Nishant Malpani <nish.malpani25@gmail.com> |
6 | * Copyright (C) 2020 Analog Devices, Inc. |
7 | */ |
8 | |
9 | #include <linux/bitfield.h> |
10 | #include <linux/bitops.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/device.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> |
15 | #include <linux/spi/spi.h> |
16 | |
17 | #include <linux/iio/buffer.h> |
18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/sysfs.h> |
20 | #include <linux/iio/trigger.h> |
21 | #include <linux/iio/triggered_buffer.h> |
22 | #include <linux/iio/trigger_consumer.h> |
23 | |
24 | #define ADXRS290_ADI_ID 0xAD |
25 | #define ADXRS290_MEMS_ID 0x1D |
26 | #define ADXRS290_DEV_ID 0x92 |
27 | |
28 | #define ADXRS290_REG_ADI_ID 0x00 |
29 | #define ADXRS290_REG_MEMS_ID 0x01 |
30 | #define ADXRS290_REG_DEV_ID 0x02 |
31 | #define ADXRS290_REG_REV_ID 0x03 |
32 | #define ADXRS290_REG_SN0 0x04 /* Serial Number Registers, 4 bytes */ |
33 | #define ADXRS290_REG_DATAX0 0x08 /* Roll Rate o/p Data Regs, 2 bytes */ |
34 | #define ADXRS290_REG_DATAY0 0x0A /* Pitch Rate o/p Data Regs, 2 bytes */ |
35 | #define ADXRS290_REG_TEMP0 0x0C |
36 | #define ADXRS290_REG_POWER_CTL 0x10 |
37 | #define ADXRS290_REG_FILTER 0x11 |
38 | #define ADXRS290_REG_DATA_RDY 0x12 |
39 | |
40 | #define ADXRS290_READ BIT(7) |
41 | #define ADXRS290_TSM BIT(0) |
42 | #define ADXRS290_MEASUREMENT BIT(1) |
43 | #define ADXRS290_DATA_RDY_OUT BIT(0) |
44 | #define ADXRS290_SYNC_MASK GENMASK(1, 0) |
45 | #define ADXRS290_SYNC(x) FIELD_PREP(ADXRS290_SYNC_MASK, x) |
46 | #define ADXRS290_LPF_MASK GENMASK(2, 0) |
47 | #define ADXRS290_LPF(x) FIELD_PREP(ADXRS290_LPF_MASK, x) |
48 | #define ADXRS290_HPF_MASK GENMASK(7, 4) |
49 | #define ADXRS290_HPF(x) FIELD_PREP(ADXRS290_HPF_MASK, x) |
50 | |
51 | #define ADXRS290_READ_REG(reg) (ADXRS290_READ | (reg)) |
52 | |
53 | #define ADXRS290_MAX_TRANSITION_TIME_MS 100 |
54 | |
55 | enum adxrs290_mode { |
56 | ADXRS290_MODE_STANDBY, |
57 | ADXRS290_MODE_MEASUREMENT, |
58 | }; |
59 | |
60 | enum adxrs290_scan_index { |
61 | ADXRS290_IDX_X, |
62 | ADXRS290_IDX_Y, |
63 | ADXRS290_IDX_TEMP, |
64 | ADXRS290_IDX_TS, |
65 | }; |
66 | |
67 | struct adxrs290_state { |
68 | struct spi_device *spi; |
69 | /* Serialize reads and their subsequent processing */ |
70 | struct mutex lock; |
71 | enum adxrs290_mode mode; |
72 | unsigned int lpf_3db_freq_idx; |
73 | unsigned int hpf_3db_freq_idx; |
74 | struct iio_trigger *dready_trig; |
75 | /* Ensure correct alignment of timestamp when present */ |
76 | struct { |
77 | s16 channels[3]; |
78 | s64 ts __aligned(8); |
79 | } buffer; |
80 | }; |
81 | |
82 | /* |
83 | * Available cut-off frequencies of the low pass filter in Hz. |
84 | * The integer part and fractional part are represented separately. |
85 | */ |
86 | static const int adxrs290_lpf_3db_freq_hz_table[][2] = { |
87 | [0] = {480, 0}, |
88 | [1] = {320, 0}, |
89 | [2] = {160, 0}, |
90 | [3] = {80, 0}, |
91 | [4] = {56, 600000}, |
92 | [5] = {40, 0}, |
93 | [6] = {28, 300000}, |
94 | [7] = {20, 0}, |
95 | }; |
96 | |
97 | /* |
98 | * Available cut-off frequencies of the high pass filter in Hz. |
99 | * The integer part and fractional part are represented separately. |
100 | */ |
101 | static const int adxrs290_hpf_3db_freq_hz_table[][2] = { |
102 | [0] = {0, 0}, |
103 | [1] = {0, 11000}, |
104 | [2] = {0, 22000}, |
105 | [3] = {0, 44000}, |
106 | [4] = {0, 87000}, |
107 | [5] = {0, 175000}, |
108 | [6] = {0, 350000}, |
109 | [7] = {0, 700000}, |
110 | [8] = {1, 400000}, |
111 | [9] = {2, 800000}, |
112 | [10] = {11, 300000}, |
113 | }; |
114 | |
115 | static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int *val) |
116 | { |
117 | struct adxrs290_state *st = iio_priv(indio_dev); |
118 | int ret = 0; |
119 | int temp; |
120 | |
121 | mutex_lock(&st->lock); |
122 | temp = spi_w8r16(spi: st->spi, cmd); |
123 | if (temp < 0) { |
124 | ret = temp; |
125 | goto err_unlock; |
126 | } |
127 | |
128 | *val = sign_extend32(value: temp, index: 15); |
129 | |
130 | err_unlock: |
131 | mutex_unlock(lock: &st->lock); |
132 | return ret; |
133 | } |
134 | |
135 | static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val) |
136 | { |
137 | const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_TEMP0); |
138 | struct adxrs290_state *st = iio_priv(indio_dev); |
139 | int ret = 0; |
140 | int temp; |
141 | |
142 | mutex_lock(&st->lock); |
143 | temp = spi_w8r16(spi: st->spi, cmd); |
144 | if (temp < 0) { |
145 | ret = temp; |
146 | goto err_unlock; |
147 | } |
148 | |
149 | /* extract lower 12 bits temperature reading */ |
150 | *val = sign_extend32(value: temp, index: 11); |
151 | |
152 | err_unlock: |
153 | mutex_unlock(lock: &st->lock); |
154 | return ret; |
155 | } |
156 | |
157 | static int adxrs290_get_3db_freq(struct iio_dev *indio_dev, u8 *val, u8 *val2) |
158 | { |
159 | const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_FILTER); |
160 | struct adxrs290_state *st = iio_priv(indio_dev); |
161 | int ret = 0; |
162 | short temp; |
163 | |
164 | mutex_lock(&st->lock); |
165 | temp = spi_w8r8(spi: st->spi, cmd); |
166 | if (temp < 0) { |
167 | ret = temp; |
168 | goto err_unlock; |
169 | } |
170 | |
171 | *val = FIELD_GET(ADXRS290_LPF_MASK, temp); |
172 | *val2 = FIELD_GET(ADXRS290_HPF_MASK, temp); |
173 | |
174 | err_unlock: |
175 | mutex_unlock(lock: &st->lock); |
176 | return ret; |
177 | } |
178 | |
179 | static int adxrs290_spi_write_reg(struct spi_device *spi, const u8 reg, |
180 | const u8 val) |
181 | { |
182 | u8 buf[2]; |
183 | |
184 | buf[0] = reg; |
185 | buf[1] = val; |
186 | |
187 | return spi_write_then_read(spi, txbuf: buf, ARRAY_SIZE(buf), NULL, n_rx: 0); |
188 | } |
189 | |
190 | static int adxrs290_find_match(const int (*freq_tbl)[2], const int n, |
191 | const int val, const int val2) |
192 | { |
193 | int i; |
194 | |
195 | for (i = 0; i < n; i++) { |
196 | if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2) |
197 | return i; |
198 | } |
199 | |
200 | return -EINVAL; |
201 | } |
202 | |
203 | static int adxrs290_set_filter_freq(struct iio_dev *indio_dev, |
204 | const unsigned int lpf_idx, |
205 | const unsigned int hpf_idx) |
206 | { |
207 | struct adxrs290_state *st = iio_priv(indio_dev); |
208 | u8 val; |
209 | |
210 | val = ADXRS290_HPF(hpf_idx) | ADXRS290_LPF(lpf_idx); |
211 | |
212 | return adxrs290_spi_write_reg(spi: st->spi, ADXRS290_REG_FILTER, val); |
213 | } |
214 | |
215 | static int adxrs290_set_mode(struct iio_dev *indio_dev, enum adxrs290_mode mode) |
216 | { |
217 | struct adxrs290_state *st = iio_priv(indio_dev); |
218 | int val, ret; |
219 | |
220 | if (st->mode == mode) |
221 | return 0; |
222 | |
223 | mutex_lock(&st->lock); |
224 | |
225 | ret = spi_w8r8(spi: st->spi, ADXRS290_READ_REG(ADXRS290_REG_POWER_CTL)); |
226 | if (ret < 0) |
227 | goto out_unlock; |
228 | |
229 | val = ret; |
230 | |
231 | switch (mode) { |
232 | case ADXRS290_MODE_STANDBY: |
233 | val &= ~ADXRS290_MEASUREMENT; |
234 | break; |
235 | case ADXRS290_MODE_MEASUREMENT: |
236 | val |= ADXRS290_MEASUREMENT; |
237 | break; |
238 | default: |
239 | ret = -EINVAL; |
240 | goto out_unlock; |
241 | } |
242 | |
243 | ret = adxrs290_spi_write_reg(spi: st->spi, ADXRS290_REG_POWER_CTL, val); |
244 | if (ret < 0) { |
245 | dev_err(&st->spi->dev, "unable to set mode: %d\n" , ret); |
246 | goto out_unlock; |
247 | } |
248 | |
249 | /* update cached mode */ |
250 | st->mode = mode; |
251 | |
252 | out_unlock: |
253 | mutex_unlock(lock: &st->lock); |
254 | return ret; |
255 | } |
256 | |
257 | static void adxrs290_chip_off_action(void *data) |
258 | { |
259 | struct iio_dev *indio_dev = data; |
260 | |
261 | adxrs290_set_mode(indio_dev, mode: ADXRS290_MODE_STANDBY); |
262 | } |
263 | |
264 | static int adxrs290_initial_setup(struct iio_dev *indio_dev) |
265 | { |
266 | struct adxrs290_state *st = iio_priv(indio_dev); |
267 | struct spi_device *spi = st->spi; |
268 | int ret; |
269 | |
270 | ret = adxrs290_spi_write_reg(spi, ADXRS290_REG_POWER_CTL, |
271 | ADXRS290_MEASUREMENT | ADXRS290_TSM); |
272 | if (ret < 0) |
273 | return ret; |
274 | |
275 | st->mode = ADXRS290_MODE_MEASUREMENT; |
276 | |
277 | return devm_add_action_or_reset(&spi->dev, adxrs290_chip_off_action, |
278 | indio_dev); |
279 | } |
280 | |
281 | static int adxrs290_read_raw(struct iio_dev *indio_dev, |
282 | struct iio_chan_spec const *chan, |
283 | int *val, |
284 | int *val2, |
285 | long mask) |
286 | { |
287 | struct adxrs290_state *st = iio_priv(indio_dev); |
288 | unsigned int t; |
289 | int ret; |
290 | |
291 | switch (mask) { |
292 | case IIO_CHAN_INFO_RAW: |
293 | ret = iio_device_claim_direct_mode(indio_dev); |
294 | if (ret) |
295 | return ret; |
296 | |
297 | switch (chan->type) { |
298 | case IIO_ANGL_VEL: |
299 | ret = adxrs290_get_rate_data(indio_dev, |
300 | ADXRS290_READ_REG(chan->address), |
301 | val); |
302 | if (ret < 0) |
303 | break; |
304 | |
305 | ret = IIO_VAL_INT; |
306 | break; |
307 | case IIO_TEMP: |
308 | ret = adxrs290_get_temp_data(indio_dev, val); |
309 | if (ret < 0) |
310 | break; |
311 | |
312 | ret = IIO_VAL_INT; |
313 | break; |
314 | default: |
315 | ret = -EINVAL; |
316 | break; |
317 | } |
318 | |
319 | iio_device_release_direct_mode(indio_dev); |
320 | return ret; |
321 | case IIO_CHAN_INFO_SCALE: |
322 | switch (chan->type) { |
323 | case IIO_ANGL_VEL: |
324 | /* 1 LSB = 0.005 degrees/sec */ |
325 | *val = 0; |
326 | *val2 = 87266; |
327 | return IIO_VAL_INT_PLUS_NANO; |
328 | case IIO_TEMP: |
329 | /* 1 LSB = 0.1 degrees Celsius */ |
330 | *val = 100; |
331 | return IIO_VAL_INT; |
332 | default: |
333 | return -EINVAL; |
334 | } |
335 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
336 | switch (chan->type) { |
337 | case IIO_ANGL_VEL: |
338 | t = st->lpf_3db_freq_idx; |
339 | *val = adxrs290_lpf_3db_freq_hz_table[t][0]; |
340 | *val2 = adxrs290_lpf_3db_freq_hz_table[t][1]; |
341 | return IIO_VAL_INT_PLUS_MICRO; |
342 | default: |
343 | return -EINVAL; |
344 | } |
345 | case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: |
346 | switch (chan->type) { |
347 | case IIO_ANGL_VEL: |
348 | t = st->hpf_3db_freq_idx; |
349 | *val = adxrs290_hpf_3db_freq_hz_table[t][0]; |
350 | *val2 = adxrs290_hpf_3db_freq_hz_table[t][1]; |
351 | return IIO_VAL_INT_PLUS_MICRO; |
352 | default: |
353 | return -EINVAL; |
354 | } |
355 | } |
356 | |
357 | return -EINVAL; |
358 | } |
359 | |
360 | static int adxrs290_write_raw(struct iio_dev *indio_dev, |
361 | struct iio_chan_spec const *chan, |
362 | int val, |
363 | int val2, |
364 | long mask) |
365 | { |
366 | struct adxrs290_state *st = iio_priv(indio_dev); |
367 | int ret, lpf_idx, hpf_idx; |
368 | |
369 | ret = iio_device_claim_direct_mode(indio_dev); |
370 | if (ret) |
371 | return ret; |
372 | |
373 | switch (mask) { |
374 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
375 | lpf_idx = adxrs290_find_match(freq_tbl: adxrs290_lpf_3db_freq_hz_table, |
376 | ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table), |
377 | val, val2); |
378 | if (lpf_idx < 0) { |
379 | ret = -EINVAL; |
380 | break; |
381 | } |
382 | |
383 | /* caching the updated state of the low-pass filter */ |
384 | st->lpf_3db_freq_idx = lpf_idx; |
385 | /* retrieving the current state of the high-pass filter */ |
386 | hpf_idx = st->hpf_3db_freq_idx; |
387 | ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); |
388 | break; |
389 | |
390 | case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: |
391 | hpf_idx = adxrs290_find_match(freq_tbl: adxrs290_hpf_3db_freq_hz_table, |
392 | ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table), |
393 | val, val2); |
394 | if (hpf_idx < 0) { |
395 | ret = -EINVAL; |
396 | break; |
397 | } |
398 | |
399 | /* caching the updated state of the high-pass filter */ |
400 | st->hpf_3db_freq_idx = hpf_idx; |
401 | /* retrieving the current state of the low-pass filter */ |
402 | lpf_idx = st->lpf_3db_freq_idx; |
403 | ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); |
404 | break; |
405 | |
406 | default: |
407 | ret = -EINVAL; |
408 | break; |
409 | } |
410 | |
411 | iio_device_release_direct_mode(indio_dev); |
412 | return ret; |
413 | } |
414 | |
415 | static int adxrs290_read_avail(struct iio_dev *indio_dev, |
416 | struct iio_chan_spec const *chan, |
417 | const int **vals, int *type, int *length, |
418 | long mask) |
419 | { |
420 | switch (mask) { |
421 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
422 | *vals = (const int *)adxrs290_lpf_3db_freq_hz_table; |
423 | *type = IIO_VAL_INT_PLUS_MICRO; |
424 | /* Values are stored in a 2D matrix */ |
425 | *length = ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table) * 2; |
426 | |
427 | return IIO_AVAIL_LIST; |
428 | case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: |
429 | *vals = (const int *)adxrs290_hpf_3db_freq_hz_table; |
430 | *type = IIO_VAL_INT_PLUS_MICRO; |
431 | /* Values are stored in a 2D matrix */ |
432 | *length = ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table) * 2; |
433 | |
434 | return IIO_AVAIL_LIST; |
435 | default: |
436 | return -EINVAL; |
437 | } |
438 | } |
439 | |
440 | static int adxrs290_reg_access_rw(struct spi_device *spi, unsigned int reg, |
441 | unsigned int *readval) |
442 | { |
443 | int ret; |
444 | |
445 | ret = spi_w8r8(spi, ADXRS290_READ_REG(reg)); |
446 | if (ret < 0) |
447 | return ret; |
448 | |
449 | *readval = ret; |
450 | |
451 | return 0; |
452 | } |
453 | |
454 | static int adxrs290_reg_access(struct iio_dev *indio_dev, unsigned int reg, |
455 | unsigned int writeval, unsigned int *readval) |
456 | { |
457 | struct adxrs290_state *st = iio_priv(indio_dev); |
458 | |
459 | if (readval) |
460 | return adxrs290_reg_access_rw(spi: st->spi, reg, readval); |
461 | else |
462 | return adxrs290_spi_write_reg(spi: st->spi, reg, val: writeval); |
463 | } |
464 | |
465 | static int adxrs290_data_rdy_trigger_set_state(struct iio_trigger *trig, |
466 | bool state) |
467 | { |
468 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); |
469 | struct adxrs290_state *st = iio_priv(indio_dev); |
470 | int ret; |
471 | u8 val; |
472 | |
473 | val = state ? ADXRS290_SYNC(ADXRS290_DATA_RDY_OUT) : 0; |
474 | |
475 | ret = adxrs290_spi_write_reg(spi: st->spi, ADXRS290_REG_DATA_RDY, val); |
476 | if (ret < 0) |
477 | dev_err(&st->spi->dev, "failed to start data rdy interrupt\n" ); |
478 | |
479 | return ret; |
480 | } |
481 | |
482 | static void adxrs290_reset_trig(struct iio_trigger *trig) |
483 | { |
484 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); |
485 | int val; |
486 | |
487 | /* |
488 | * Data ready interrupt is reset after a read of the data registers. |
489 | * Here, we only read the 16b DATAY registers as that marks the end of |
490 | * a read of the data registers and initiates a reset for the interrupt |
491 | * line. |
492 | */ |
493 | adxrs290_get_rate_data(indio_dev, |
494 | ADXRS290_READ_REG(ADXRS290_REG_DATAY0), val: &val); |
495 | } |
496 | |
497 | static const struct iio_trigger_ops adxrs290_trigger_ops = { |
498 | .set_trigger_state = &adxrs290_data_rdy_trigger_set_state, |
499 | .validate_device = &iio_trigger_validate_own_device, |
500 | .reenable = &adxrs290_reset_trig, |
501 | }; |
502 | |
503 | static irqreturn_t adxrs290_trigger_handler(int irq, void *p) |
504 | { |
505 | struct iio_poll_func *pf = p; |
506 | struct iio_dev *indio_dev = pf->indio_dev; |
507 | struct adxrs290_state *st = iio_priv(indio_dev); |
508 | u8 tx = ADXRS290_READ_REG(ADXRS290_REG_DATAX0); |
509 | int ret; |
510 | |
511 | mutex_lock(&st->lock); |
512 | |
513 | /* exercise a bulk data capture starting from reg DATAX0... */ |
514 | ret = spi_write_then_read(spi: st->spi, txbuf: &tx, n_tx: sizeof(tx), rxbuf: st->buffer.channels, |
515 | n_rx: sizeof(st->buffer.channels)); |
516 | if (ret < 0) |
517 | goto out_unlock_notify; |
518 | |
519 | iio_push_to_buffers_with_timestamp(indio_dev, data: &st->buffer, |
520 | timestamp: pf->timestamp); |
521 | |
522 | out_unlock_notify: |
523 | mutex_unlock(lock: &st->lock); |
524 | iio_trigger_notify_done(trig: indio_dev->trig); |
525 | |
526 | return IRQ_HANDLED; |
527 | } |
528 | |
529 | #define ADXRS290_ANGL_VEL_CHANNEL(reg, axis) { \ |
530 | .type = IIO_ANGL_VEL, \ |
531 | .address = reg, \ |
532 | .modified = 1, \ |
533 | .channel2 = IIO_MOD_##axis, \ |
534 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
535 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
536 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ |
537 | BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ |
538 | .info_mask_shared_by_type_available = \ |
539 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ |
540 | BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ |
541 | .scan_index = ADXRS290_IDX_##axis, \ |
542 | .scan_type = { \ |
543 | .sign = 's', \ |
544 | .realbits = 16, \ |
545 | .storagebits = 16, \ |
546 | .endianness = IIO_LE, \ |
547 | }, \ |
548 | } |
549 | |
550 | static const struct iio_chan_spec adxrs290_channels[] = { |
551 | ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAX0, X), |
552 | ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAY0, Y), |
553 | { |
554 | .type = IIO_TEMP, |
555 | .address = ADXRS290_REG_TEMP0, |
556 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
557 | BIT(IIO_CHAN_INFO_SCALE), |
558 | .scan_index = ADXRS290_IDX_TEMP, |
559 | .scan_type = { |
560 | .sign = 's', |
561 | .realbits = 12, |
562 | .storagebits = 16, |
563 | .endianness = IIO_LE, |
564 | }, |
565 | }, |
566 | IIO_CHAN_SOFT_TIMESTAMP(ADXRS290_IDX_TS), |
567 | }; |
568 | |
569 | static const unsigned long adxrs290_avail_scan_masks[] = { |
570 | BIT(ADXRS290_IDX_X) | BIT(ADXRS290_IDX_Y) | BIT(ADXRS290_IDX_TEMP), |
571 | 0 |
572 | }; |
573 | |
574 | static const struct iio_info adxrs290_info = { |
575 | .read_raw = &adxrs290_read_raw, |
576 | .write_raw = &adxrs290_write_raw, |
577 | .read_avail = &adxrs290_read_avail, |
578 | .debugfs_reg_access = &adxrs290_reg_access, |
579 | }; |
580 | |
581 | static int adxrs290_probe_trigger(struct iio_dev *indio_dev) |
582 | { |
583 | struct adxrs290_state *st = iio_priv(indio_dev); |
584 | int ret; |
585 | |
586 | if (!st->spi->irq) { |
587 | dev_info(&st->spi->dev, "no irq, using polling\n" ); |
588 | return 0; |
589 | } |
590 | |
591 | st->dready_trig = devm_iio_trigger_alloc(&st->spi->dev, "%s-dev%d" , |
592 | indio_dev->name, |
593 | iio_device_id(indio_dev)); |
594 | if (!st->dready_trig) |
595 | return -ENOMEM; |
596 | |
597 | st->dready_trig->ops = &adxrs290_trigger_ops; |
598 | iio_trigger_set_drvdata(trig: st->dready_trig, data: indio_dev); |
599 | |
600 | ret = devm_request_irq(dev: &st->spi->dev, irq: st->spi->irq, |
601 | handler: &iio_trigger_generic_data_rdy_poll, |
602 | IRQF_ONESHOT, devname: "adxrs290_irq" , dev_id: st->dready_trig); |
603 | if (ret < 0) |
604 | return dev_err_probe(dev: &st->spi->dev, err: ret, |
605 | fmt: "request irq %d failed\n" , st->spi->irq); |
606 | |
607 | ret = devm_iio_trigger_register(dev: &st->spi->dev, trig_info: st->dready_trig); |
608 | if (ret) { |
609 | dev_err(&st->spi->dev, "iio trigger register failed\n" ); |
610 | return ret; |
611 | } |
612 | |
613 | indio_dev->trig = iio_trigger_get(trig: st->dready_trig); |
614 | |
615 | return 0; |
616 | } |
617 | |
618 | static int adxrs290_probe(struct spi_device *spi) |
619 | { |
620 | struct iio_dev *indio_dev; |
621 | struct adxrs290_state *st; |
622 | u8 val, val2; |
623 | int ret; |
624 | |
625 | indio_dev = devm_iio_device_alloc(parent: &spi->dev, sizeof_priv: sizeof(*st)); |
626 | if (!indio_dev) |
627 | return -ENOMEM; |
628 | |
629 | st = iio_priv(indio_dev); |
630 | st->spi = spi; |
631 | |
632 | indio_dev->name = "adxrs290" ; |
633 | indio_dev->modes = INDIO_DIRECT_MODE; |
634 | indio_dev->channels = adxrs290_channels; |
635 | indio_dev->num_channels = ARRAY_SIZE(adxrs290_channels); |
636 | indio_dev->info = &adxrs290_info; |
637 | indio_dev->available_scan_masks = adxrs290_avail_scan_masks; |
638 | |
639 | mutex_init(&st->lock); |
640 | |
641 | val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_ADI_ID)); |
642 | if (val != ADXRS290_ADI_ID) { |
643 | dev_err(&spi->dev, "Wrong ADI ID 0x%02x\n" , val); |
644 | return -ENODEV; |
645 | } |
646 | |
647 | val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_MEMS_ID)); |
648 | if (val != ADXRS290_MEMS_ID) { |
649 | dev_err(&spi->dev, "Wrong MEMS ID 0x%02x\n" , val); |
650 | return -ENODEV; |
651 | } |
652 | |
653 | val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_DEV_ID)); |
654 | if (val != ADXRS290_DEV_ID) { |
655 | dev_err(&spi->dev, "Wrong DEV ID 0x%02x\n" , val); |
656 | return -ENODEV; |
657 | } |
658 | |
659 | /* default mode the gyroscope starts in */ |
660 | st->mode = ADXRS290_MODE_STANDBY; |
661 | |
662 | /* switch to measurement mode and switch on the temperature sensor */ |
663 | ret = adxrs290_initial_setup(indio_dev); |
664 | if (ret < 0) |
665 | return ret; |
666 | |
667 | /* max transition time to measurement mode */ |
668 | msleep(ADXRS290_MAX_TRANSITION_TIME_MS); |
669 | |
670 | ret = adxrs290_get_3db_freq(indio_dev, val: &val, val2: &val2); |
671 | if (ret < 0) |
672 | return ret; |
673 | |
674 | st->lpf_3db_freq_idx = val; |
675 | st->hpf_3db_freq_idx = val2; |
676 | |
677 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, |
678 | &iio_pollfunc_store_time, |
679 | &adxrs290_trigger_handler, NULL); |
680 | if (ret < 0) |
681 | return dev_err_probe(dev: &spi->dev, err: ret, |
682 | fmt: "iio triggered buffer setup failed\n" ); |
683 | |
684 | ret = adxrs290_probe_trigger(indio_dev); |
685 | if (ret < 0) |
686 | return ret; |
687 | |
688 | return devm_iio_device_register(&spi->dev, indio_dev); |
689 | } |
690 | |
691 | static const struct of_device_id adxrs290_of_match[] = { |
692 | { .compatible = "adi,adxrs290" }, |
693 | { } |
694 | }; |
695 | MODULE_DEVICE_TABLE(of, adxrs290_of_match); |
696 | |
697 | static struct spi_driver adxrs290_driver = { |
698 | .driver = { |
699 | .name = "adxrs290" , |
700 | .of_match_table = adxrs290_of_match, |
701 | }, |
702 | .probe = adxrs290_probe, |
703 | }; |
704 | module_spi_driver(adxrs290_driver); |
705 | |
706 | MODULE_AUTHOR("Nishant Malpani <nish.malpani25@gmail.com>" ); |
707 | MODULE_DESCRIPTION("Analog Devices ADXRS290 Gyroscope SPI driver" ); |
708 | MODULE_LICENSE("GPL" ); |
709 | |