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