blob: 28d4df2fe76a4cf917c16f7b87c9d54b6b63bc06 [file] [log] [blame]
Lars-Peter Clausenccd2b522012-11-13 13:28:00 +00001/*
2 * Common library for ADIS16XXX devices
3 *
4 * Copyright 2012 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2 or later.
8 */
9
10#include <linux/delay.h>
11#include <linux/mutex.h>
12#include <linux/device.h>
13#include <linux/kernel.h>
14#include <linux/spi/spi.h>
15#include <linux/slab.h>
16#include <linux/sysfs.h>
17#include <linux/module.h>
18#include <asm/unaligned.h>
19
20#include <linux/iio/iio.h>
21#include <linux/iio/sysfs.h>
22#include <linux/iio/buffer.h>
Lars-Peter Clausenec04cb02012-11-13 13:28:00 +000023#include <linux/iio/imu/adis.h>
Lars-Peter Clausenccd2b522012-11-13 13:28:00 +000024
25#define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2)
26#define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH BIT(1)
27#define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
28#define ADIS_GLOB_CMD_SW_RESET BIT(7)
29
30/**
31 * adis_write_reg_8() - Write single byte to a register
32 * @adis: The adis device
33 * @reg: The address of the register to be written
34 * @val: The value to write
35 */
36int adis_write_reg_8(struct adis *adis, unsigned int reg, uint8_t val)
37{
38 int ret;
39
40 mutex_lock(&adis->txrx_lock);
41 adis->tx[0] = ADIS_WRITE_REG(reg);
42 adis->tx[1] = val;
43
44 ret = spi_write(adis->spi, adis->tx, 2);
45 mutex_unlock(&adis->txrx_lock);
46
47 return ret;
48}
49EXPORT_SYMBOL_GPL(adis_write_reg_8);
50
51/**
52 * adis_write_reg_16() - Write 2 bytes to a pair of registers
53 * @adis: The adis device
54 * @reg: The address of the lower of the two registers
55 * @val: Value to be written
56 */
57int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t value)
58{
59 int ret;
60 struct spi_message msg;
61 struct spi_transfer xfers[] = {
62 {
63 .tx_buf = adis->tx,
64 .bits_per_word = 8,
65 .len = 2,
66 .cs_change = 1,
67 .delay_usecs = adis->data->write_delay,
68 }, {
69 .tx_buf = adis->tx + 2,
70 .bits_per_word = 8,
71 .len = 2,
72 .delay_usecs = adis->data->write_delay,
73 },
74 };
75
76 mutex_lock(&adis->txrx_lock);
77 adis->tx[0] = ADIS_WRITE_REG(reg);
78 adis->tx[1] = value & 0xff;
79 adis->tx[2] = ADIS_WRITE_REG(reg + 1);
80 adis->tx[3] = (value >> 8) & 0xff;
81
82 spi_message_init(&msg);
83 spi_message_add_tail(&xfers[0], &msg);
84 spi_message_add_tail(&xfers[1], &msg);
85 ret = spi_sync(adis->spi, &msg);
86 mutex_unlock(&adis->txrx_lock);
87
88 return ret;
89}
90EXPORT_SYMBOL_GPL(adis_write_reg_16);
91
92/**
93 * adis_read_reg_16() - read 2 bytes from a 16-bit register
94 * @adis: The adis device
95 * @reg: The address of the lower of the two registers
96 * @val: The value read back from the device
97 */
98int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val)
99{
100 struct spi_message msg;
101 int ret;
102 struct spi_transfer xfers[] = {
103 {
104 .tx_buf = adis->tx,
105 .bits_per_word = 8,
106 .len = 2,
107 .cs_change = 1,
108 .delay_usecs = adis->data->read_delay,
109 }, {
110 .rx_buf = adis->rx,
111 .bits_per_word = 8,
112 .len = 2,
113 .delay_usecs = adis->data->read_delay,
114 },
115 };
116
117 mutex_lock(&adis->txrx_lock);
118 adis->tx[0] = ADIS_READ_REG(reg);
119 adis->tx[1] = 0;
120
121 spi_message_init(&msg);
122 spi_message_add_tail(&xfers[0], &msg);
123 spi_message_add_tail(&xfers[1], &msg);
124 ret = spi_sync(adis->spi, &msg);
125 if (ret) {
126 dev_err(&adis->spi->dev, "Failed to read 16 bit register 0x%02X: %d\n",
127 reg, ret);
128 goto error_ret;
129 }
130 *val = get_unaligned_be16(adis->rx);
131
132error_ret:
133 mutex_unlock(&adis->txrx_lock);
134 return ret;
135}
136EXPORT_SYMBOL_GPL(adis_read_reg_16);
137
Lars-Peter Clausen78026a62012-11-20 13:36:00 +0000138#ifdef CONFIG_DEBUG_FS
139
140int adis_debugfs_reg_access(struct iio_dev *indio_dev,
141 unsigned int reg, unsigned int writeval, unsigned int *readval)
142{
143 struct adis *adis = iio_device_get_drvdata(indio_dev);
144
145 if (readval) {
146 uint16_t val16;
147 int ret;
148
149 ret = adis_read_reg_16(adis, reg, &val16);
150 *readval = val16;
151
152 return ret;
153 } else {
154 return adis_write_reg_16(adis, reg, writeval);
155 }
156}
157EXPORT_SYMBOL(adis_debugfs_reg_access);
158
159#endif
160
Lars-Peter Clausenccd2b522012-11-13 13:28:00 +0000161/**
162 * adis_enable_irq() - Enable or disable data ready IRQ
163 * @adis: The adis device
164 * @enable: Whether to enable the IRQ
165 *
166 * Returns 0 on success, negative error code otherwise
167 */
168int adis_enable_irq(struct adis *adis, bool enable)
169{
170 int ret = 0;
171 uint16_t msc;
172
173 ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
174 if (ret)
175 goto error_ret;
176
177 msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;
178 msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;
179 if (enable)
180 msc |= ADIS_MSC_CTRL_DATA_RDY_EN;
181 else
182 msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;
183
184 ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
185
186error_ret:
187 return ret;
188}
189EXPORT_SYMBOL(adis_enable_irq);
190
191/**
192 * adis_check_status() - Check the device for error conditions
193 * @adis: The adis device
194 *
195 * Returns 0 on success, a negative error code otherwise
196 */
197int adis_check_status(struct adis *adis)
198{
199 uint16_t status;
200 int ret;
201 int i;
202
203 ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
204 if (ret < 0)
205 return ret;
206
207 status &= adis->data->status_error_mask;
208
209 if (status == 0)
210 return 0;
211
212 for (i = 0; i < 16; ++i) {
213 if (status & BIT(i)) {
214 dev_err(&adis->spi->dev, "%s.\n",
215 adis->data->status_error_msgs[i]);
216 }
217 }
218
219 return -EIO;
220}
221EXPORT_SYMBOL_GPL(adis_check_status);
222
223/**
224 * adis_reset() - Reset the device
225 * @adis: The adis device
226 *
227 * Returns 0 on success, a negative error code otherwise
228 */
229int adis_reset(struct adis *adis)
230{
231 int ret;
232
233 ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg,
234 ADIS_GLOB_CMD_SW_RESET);
235 if (ret)
236 dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
237
238 return ret;
239}
240EXPORT_SYMBOL_GPL(adis_reset);
241
242static int adis_self_test(struct adis *adis)
243{
244 int ret;
245
246 ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg,
247 adis->data->self_test_mask);
248 if (ret) {
249 dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
250 ret);
251 return ret;
252 }
253
254 msleep(adis->data->startup_delay);
255
256 return adis_check_status(adis);
257}
258
259/**
260 * adis_inital_startup() - Performs device self-test
261 * @adis: The adis device
262 *
263 * Returns 0 if the device is operational, a negative error code otherwise.
264 *
265 * This function should be called early on in the device initialization sequence
266 * to ensure that the device is in a sane and known state and that it is usable.
267 */
268int adis_initial_startup(struct adis *adis)
269{
270 int ret;
271
272 ret = adis_self_test(adis);
273 if (ret) {
274 dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n");
275 adis_reset(adis);
276 msleep(adis->data->startup_delay);
277 ret = adis_self_test(adis);
278 if (ret) {
279 dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n");
280 return ret;
281 }
282 }
283
284 return 0;
285}
286EXPORT_SYMBOL_GPL(adis_initial_startup);
287
288/**
289 * adis_single_conversion() - Performs a single sample conversion
290 * @indio_dev: The IIO device
291 * @chan: The IIO channel
292 * @error_mask: Mask for the error bit
293 * @val: Result of the conversion
294 *
295 * Returns IIO_VAL_INT on success, a negative error code otherwise.
296 *
297 * The function performs a single conversion on a given channel and post
298 * processes the value accordingly to the channel spec. If a error_mask is given
299 * the function will check if the mask is set in the returned raw value. If it
300 * is set the function will perform a self-check. If the device does not report
301 * a error bit in the channels raw value set error_mask to 0.
302 */
303int adis_single_conversion(struct iio_dev *indio_dev,
304 const struct iio_chan_spec *chan, unsigned int error_mask, int *val)
305{
306 struct adis *adis = iio_device_get_drvdata(indio_dev);
307 uint16_t val16;
308 int ret;
309
310 mutex_lock(&indio_dev->mlock);
311
312 ret = adis_read_reg_16(adis, chan->address, &val16);
313 if (ret)
314 goto err_unlock;
315
316 if (val16 & error_mask) {
317 ret = adis_check_status(adis);
318 if (ret)
319 goto err_unlock;
320 }
321
322 if (chan->scan_type.sign == 's')
323 *val = sign_extend32(val16, chan->scan_type.realbits - 1);
324 else
325 *val = val16 & ((1 << chan->scan_type.realbits) - 1);
326
327 ret = IIO_VAL_INT;
328err_unlock:
329 mutex_unlock(&indio_dev->mlock);
330 return ret;
331}
332EXPORT_SYMBOL_GPL(adis_single_conversion);
333
334/**
335 * adis_init() - Initialize adis device structure
336 * @adis: The adis device
337 * @indio_dev: The iio device
338 * @spi: The spi device
339 * @data: Chip specific data
340 *
341 * Returns 0 on success, a negative error code otherwise.
342 *
343 * This function must be called, before any other adis helper function may be
344 * called.
345 */
346int adis_init(struct adis *adis, struct iio_dev *indio_dev,
347 struct spi_device *spi, const struct adis_data *data)
348{
349 mutex_init(&adis->txrx_lock);
350 adis->spi = spi;
351 adis->data = data;
352 iio_device_set_drvdata(indio_dev, adis);
353
354 return adis_enable_irq(adis, false);
355}
356EXPORT_SYMBOL_GPL(adis_init);
357
358MODULE_LICENSE("GPL");
359MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
360MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");