Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
a9d26f00 | 2 | #include <linux/interrupt.h> |
a9d26f00 | 3 | #include <linux/mutex.h> |
a9d26f00 BS |
4 | #include <linux/kernel.h> |
5 | #include <linux/spi/spi.h> | |
1cb6c1f5 | 6 | #include <linux/slab.h> |
2a29a90b | 7 | #include <linux/bitops.h> |
8e336a72 | 8 | #include <linux/export.h> |
a9d26f00 | 9 | |
06458e27 | 10 | #include <linux/iio/iio.h> |
1ffe2e7a LPC |
11 | #include <linux/iio/buffer.h> |
12 | #include <linux/iio/triggered_buffer.h> | |
06458e27 | 13 | #include <linux/iio/trigger_consumer.h> |
cd888a17 | 14 | |
a9d26f00 BS |
15 | #include "adis16400.h" |
16 | ||
5eda3550 LPC |
17 | int adis16400_update_scan_mode(struct iio_dev *indio_dev, |
18 | const unsigned long *scan_mask) | |
3fd66da1 | 19 | { |
38d15f06 | 20 | struct adis16400_state *st = iio_priv(indio_dev); |
5eda3550 | 21 | struct adis *adis = &st->adis; |
9df56035 PC |
22 | unsigned int burst_length; |
23 | u8 *tx; | |
3fd66da1 | 24 | |
5eda3550 LPC |
25 | if (st->variant->flags & ADIS16400_NO_BURST) |
26 | return adis_update_scan_mode(indio_dev, scan_mask); | |
3fd66da1 | 27 | |
5eda3550 LPC |
28 | kfree(adis->xfer); |
29 | kfree(adis->buffer); | |
2a29a90b | 30 | |
9df56035 PC |
31 | /* All but the timestamp channel */ |
32 | burst_length = (indio_dev->num_channels - 1) * sizeof(u16); | |
d046ba26 LPC |
33 | if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) |
34 | burst_length += sizeof(u16); | |
9df56035 | 35 | |
5eda3550 LPC |
36 | adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL); |
37 | if (!adis->xfer) | |
38 | return -ENOMEM; | |
2a29a90b | 39 | |
9df56035 | 40 | adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL); |
5eda3550 | 41 | if (!adis->buffer) |
2a29a90b JC |
42 | return -ENOMEM; |
43 | ||
9df56035 | 44 | tx = adis->buffer + burst_length; |
5eda3550 LPC |
45 | tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD); |
46 | tx[1] = 0; | |
47 | ||
48 | adis->xfer[0].tx_buf = tx; | |
49 | adis->xfer[0].bits_per_word = 8; | |
50 | adis->xfer[0].len = 2; | |
9df56035 | 51 | adis->xfer[1].rx_buf = adis->buffer; |
5eda3550 | 52 | adis->xfer[1].bits_per_word = 8; |
9df56035 | 53 | adis->xfer[1].len = burst_length; |
5eda3550 LPC |
54 | |
55 | spi_message_init(&adis->msg); | |
56 | spi_message_add_tail(&adis->xfer[0], &adis->msg); | |
57 | spi_message_add_tail(&adis->xfer[1], &adis->msg); | |
58 | ||
59 | return 0; | |
2a29a90b JC |
60 | } |
61 | ||
5eda3550 | 62 | irqreturn_t adis16400_trigger_handler(int irq, void *p) |
a9d26f00 | 63 | { |
e7854845 | 64 | struct iio_poll_func *pf = p; |
e65bc6ac | 65 | struct iio_dev *indio_dev = pf->indio_dev; |
38d15f06 | 66 | struct adis16400_state *st = iio_priv(indio_dev); |
5eda3550 LPC |
67 | struct adis *adis = &st->adis; |
68 | u32 old_speed_hz = st->adis.spi->max_speed_hz; | |
d046ba26 | 69 | void *buffer; |
5eda3550 LPC |
70 | int ret; |
71 | ||
72 | if (!adis->buffer) | |
73 | return -ENOMEM; | |
74 | ||
75 | if (!(st->variant->flags & ADIS16400_NO_BURST) && | |
76 | st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { | |
77 | st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; | |
78 | spi_setup(st->adis.spi); | |
a9d26f00 BS |
79 | } |
80 | ||
5eda3550 LPC |
81 | ret = spi_sync(adis->spi, &adis->msg); |
82 | if (ret) | |
83 | dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); | |
84 | ||
85 | if (!(st->variant->flags & ADIS16400_NO_BURST)) { | |
86 | st->adis.spi->max_speed_hz = old_speed_hz; | |
87 | spi_setup(st->adis.spi); | |
2a29a90b | 88 | } |
5eda3550 | 89 | |
d046ba26 LPC |
90 | if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) |
91 | buffer = adis->buffer + sizeof(u16); | |
92 | else | |
93 | buffer = adis->buffer; | |
94 | ||
95 | iio_push_to_buffers_with_timestamp(indio_dev, buffer, | |
8c7b0322 | 96 | pf->timestamp); |
a9d26f00 | 97 | |
e7854845 | 98 | iio_trigger_notify_done(indio_dev->trig); |
a9d26f00 | 99 | |
e7854845 | 100 | return IRQ_HANDLED; |
a9d26f00 | 101 | } |