1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Common library for ADIS16XXX devices
5 * Copyright 2012 Analog Devices Inc.
6 * Author: Lars-Peter Clausen <lars@metafoo.de>
9 #include <linux/export.h>
10 #include <linux/interrupt.h>
11 #include <linux/mutex.h>
12 #include <linux/kernel.h>
13 #include <linux/spi/spi.h>
14 #include <linux/slab.h>
16 #include <linux/iio/iio.h>
17 #include <linux/iio/buffer.h>
18 #include <linux/iio/trigger_consumer.h>
19 #include <linux/iio/triggered_buffer.h>
20 #include <linux/iio/imu/adis.h>
22 static int adis_update_scan_mode_burst(struct iio_dev
*indio_dev
,
23 const unsigned long *scan_mask
)
25 struct adis
*adis
= iio_device_get_drvdata(indio_dev
);
26 unsigned int burst_length
, burst_max_length
;
29 burst_length
= adis
->data
->burst_len
+ adis
->burst_extra_len
;
31 if (adis
->data
->burst_max_len
)
32 burst_max_length
= adis
->data
->burst_max_len
;
34 burst_max_length
= burst_length
;
36 adis
->xfer
= kcalloc(2, sizeof(*adis
->xfer
), GFP_KERNEL
);
40 adis
->buffer
= kzalloc(burst_max_length
+ sizeof(u16
), GFP_KERNEL
);
47 tx
= adis
->buffer
+ burst_max_length
;
48 tx
[0] = ADIS_READ_REG(adis
->data
->burst_reg_cmd
);
51 adis
->xfer
[0].tx_buf
= tx
;
52 adis
->xfer
[0].bits_per_word
= 8;
53 adis
->xfer
[0].len
= 2;
54 if (adis
->data
->burst_max_speed_hz
)
55 adis
->xfer
[0].speed_hz
= adis
->data
->burst_max_speed_hz
;
56 adis
->xfer
[1].rx_buf
= adis
->buffer
;
57 adis
->xfer
[1].bits_per_word
= 8;
58 adis
->xfer
[1].len
= burst_length
;
59 if (adis
->data
->burst_max_speed_hz
)
60 adis
->xfer
[1].speed_hz
= adis
->data
->burst_max_speed_hz
;
62 spi_message_init(&adis
->msg
);
63 spi_message_add_tail(&adis
->xfer
[0], &adis
->msg
);
64 spi_message_add_tail(&adis
->xfer
[1], &adis
->msg
);
69 int adis_update_scan_mode(struct iio_dev
*indio_dev
,
70 const unsigned long *scan_mask
)
72 struct adis
*adis
= iio_device_get_drvdata(indio_dev
);
73 const struct iio_chan_spec
*chan
;
74 unsigned int scan_count
;
81 if (adis
->data
->burst_len
)
82 return adis_update_scan_mode_burst(indio_dev
, scan_mask
);
84 scan_count
= indio_dev
->scan_bytes
/ 2;
86 adis
->xfer
= kcalloc(scan_count
+ 1, sizeof(*adis
->xfer
), GFP_KERNEL
);
90 adis
->buffer
= kcalloc(indio_dev
->scan_bytes
, 2, GFP_KERNEL
);
100 spi_message_init(&adis
->msg
);
102 for (j
= 0; j
<= scan_count
; j
++) {
103 adis
->xfer
[j
].bits_per_word
= 8;
105 adis
->xfer
[j
].cs_change
= 1;
106 adis
->xfer
[j
].len
= 2;
107 adis
->xfer
[j
].delay
.value
= adis
->data
->read_delay
;
108 adis
->xfer
[j
].delay
.unit
= SPI_DELAY_UNIT_USECS
;
110 adis
->xfer
[j
].tx_buf
= &tx
[j
];
112 adis
->xfer
[j
].rx_buf
= &rx
[j
- 1];
113 spi_message_add_tail(&adis
->xfer
[j
], &adis
->msg
);
116 chan
= indio_dev
->channels
;
117 for (i
= 0; i
< indio_dev
->num_channels
; i
++, chan
++) {
118 if (!test_bit(chan
->scan_index
, scan_mask
))
120 if (chan
->scan_type
.storagebits
== 32)
121 *tx
++ = cpu_to_be16((chan
->address
+ 2) << 8);
122 *tx
++ = cpu_to_be16(chan
->address
<< 8);
127 EXPORT_SYMBOL_NS_GPL(adis_update_scan_mode
, "IIO_ADISLIB");
129 static int adis_paging_trigger_handler(struct adis
*adis
)
133 guard(mutex
)(&adis
->state_lock
);
134 if (adis
->current_page
!= 0) {
135 adis
->tx
[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID
);
137 ret
= spi_write(adis
->spi
, adis
->tx
, 2);
139 dev_err(&adis
->spi
->dev
, "Failed to change device page: %d\n", ret
);
143 adis
->current_page
= 0;
146 return spi_sync(adis
->spi
, &adis
->msg
);
149 static irqreturn_t
adis_trigger_handler(int irq
, void *p
)
151 struct iio_poll_func
*pf
= p
;
152 struct iio_dev
*indio_dev
= pf
->indio_dev
;
153 struct adis
*adis
= iio_device_get_drvdata(indio_dev
);
156 if (adis
->data
->has_paging
)
157 ret
= adis_paging_trigger_handler(adis
);
159 ret
= spi_sync(adis
->spi
, &adis
->msg
);
161 dev_err(&adis
->spi
->dev
, "Failed to read data: %d", ret
);
165 iio_push_to_buffers_with_timestamp(indio_dev
, adis
->buffer
,
169 iio_trigger_notify_done(indio_dev
->trig
);
174 static void adis_buffer_cleanup(void *arg
)
176 struct adis
*adis
= arg
;
183 * devm_adis_setup_buffer_and_trigger_with_attrs() - Sets up buffer and trigger
184 * for the managed adis device with buffer attributes.
185 * @adis: The adis device
186 * @indio_dev: The IIO device
187 * @trigger_handler: Trigger handler: should handle the buffer readings.
188 * @ops: Optional buffer setup functions, may be NULL.
189 * @buffer_attrs: Extra buffer attributes.
191 * Returns 0 on success, a negative error code otherwise.
193 * This function sets up the buffer (with buffer setup functions and extra
194 * buffer attributes) and trigger for a adis devices with buffer attributes.
197 devm_adis_setup_buffer_and_trigger_with_attrs(struct adis
*adis
, struct iio_dev
*indio_dev
,
198 irq_handler_t trigger_handler
,
199 const struct iio_buffer_setup_ops
*ops
,
200 const struct iio_dev_attr
**buffer_attrs
)
204 if (!trigger_handler
)
205 trigger_handler
= adis_trigger_handler
;
207 ret
= devm_iio_triggered_buffer_setup_ext(&adis
->spi
->dev
, indio_dev
,
208 &iio_pollfunc_store_time
,
210 IIO_BUFFER_DIRECTION_IN
,
216 if (adis
->spi
->irq
) {
217 ret
= devm_adis_probe_trigger(adis
, indio_dev
);
222 return devm_add_action_or_reset(&adis
->spi
->dev
, adis_buffer_cleanup
,
225 EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger_with_attrs
, "IIO_ADISLIB");