Commit | Line | Data |
---|---|---|
fda8d26e | 1 | // SPDX-License-Identifier: GPL-2.0-only |
24742ac6 | 2 | /* |
617156fb | 3 | * ADXRS450/ADXRS453 Digital Output Gyroscope Driver |
24742ac6 MH |
4 | * |
5 | * Copyright 2011 Analog Devices Inc. | |
24742ac6 MH |
6 | */ |
7 | ||
8 | #include <linux/interrupt.h> | |
9 | #include <linux/irq.h> | |
24742ac6 MH |
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/list.h> | |
99c97852 | 18 | #include <linux/module.h> |
24742ac6 | 19 | |
06458e27 JC |
20 | #include <linux/iio/iio.h> |
21 | #include <linux/iio/sysfs.h> | |
24742ac6 | 22 | |
53ac8500 LPC |
23 | #define ADXRS450_STARTUP_DELAY 50 /* ms */ |
24 | ||
25 | /* The MSB for the spi commands */ | |
26 | #define ADXRS450_SENSOR_DATA (0x20 << 24) | |
27 | #define ADXRS450_WRITE_DATA (0x40 << 24) | |
28 | #define ADXRS450_READ_DATA (0x80 << 24) | |
29 | ||
30 | #define ADXRS450_RATE1 0x00 /* Rate Registers */ | |
31 | #define ADXRS450_TEMP1 0x02 /* Temperature Registers */ | |
32 | #define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */ | |
33 | #define ADXRS450_HICST1 0x06 /* High CST Memory Registers */ | |
34 | #define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */ | |
35 | #define ADXRS450_FAULT1 0x0A /* Fault Registers */ | |
36 | #define ADXRS450_PID1 0x0C /* Part ID Register 1 */ | |
37 | #define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */ | |
38 | #define ADXRS450_SNL 0x10 | |
39 | #define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */ | |
40 | /* Check bits */ | |
41 | #define ADXRS450_P 0x01 | |
42 | #define ADXRS450_CHK 0x02 | |
43 | #define ADXRS450_CST 0x04 | |
44 | #define ADXRS450_PWR 0x08 | |
45 | #define ADXRS450_POR 0x10 | |
46 | #define ADXRS450_NVM 0x20 | |
47 | #define ADXRS450_Q 0x40 | |
48 | #define ADXRS450_PLL 0x80 | |
49 | #define ADXRS450_UV 0x100 | |
50 | #define ADXRS450_OV 0x200 | |
51 | #define ADXRS450_AMP 0x400 | |
52 | #define ADXRS450_FAIL 0x800 | |
53 | ||
54 | #define ADXRS450_WRERR_MASK (0x7 << 29) | |
55 | ||
56 | #define ADXRS450_MAX_RX 4 | |
57 | #define ADXRS450_MAX_TX 4 | |
58 | ||
59 | #define ADXRS450_GET_ST(a) ((a >> 26) & 0x3) | |
60 | ||
61 | enum { | |
62 | ID_ADXRS450, | |
63 | ID_ADXRS453, | |
64 | }; | |
65 | ||
66 | /** | |
67 | * struct adxrs450_state - device instance specific data | |
68 | * @us: actual spi_device | |
69 | * @buf_lock: mutex to protect tx and rx | |
70 | * @tx: transmit buffer | |
71 | * @rx: receive buffer | |
72 | **/ | |
73 | struct adxrs450_state { | |
74 | struct spi_device *us; | |
75 | struct mutex buf_lock; | |
966d2f4e | 76 | __be32 tx __aligned(IIO_DMA_MINALIGN); |
53ac8500 LPC |
77 | __be32 rx; |
78 | ||
79 | }; | |
24742ac6 MH |
80 | |
81 | /** | |
82 | * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair | |
d5e69c83 | 83 | * @indio_dev: device associated with child of actual iio_dev |
1439b6e8 LPC |
84 | * @reg_address: the address of the lower of the two registers, which should be |
85 | * an even address, the second register's address is reg_address + 1. | |
24742ac6 MH |
86 | * @val: somewhere to pass back the value read |
87 | **/ | |
58ea7784 JC |
88 | static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, |
89 | u8 reg_address, | |
90 | u16 *val) | |
24742ac6 | 91 | { |
ba61bb18 | 92 | struct adxrs450_state *st = iio_priv(indio_dev); |
1a87e4fb | 93 | u32 tx; |
24742ac6 | 94 | int ret; |
6a6df2d9 LPC |
95 | struct spi_transfer xfers[] = { |
96 | { | |
1a87e4fb | 97 | .tx_buf = &st->tx, |
6a6df2d9 | 98 | .bits_per_word = 8, |
1a87e4fb | 99 | .len = sizeof(st->tx), |
6a6df2d9 LPC |
100 | .cs_change = 1, |
101 | }, { | |
1a87e4fb | 102 | .rx_buf = &st->rx, |
6a6df2d9 | 103 | .bits_per_word = 8, |
1a87e4fb | 104 | .len = sizeof(st->rx), |
6a6df2d9 LPC |
105 | }, |
106 | }; | |
31f6a29a | 107 | |
24742ac6 | 108 | mutex_lock(&st->buf_lock); |
1a87e4fb | 109 | tx = ADXRS450_READ_DATA | (reg_address << 17); |
24742ac6 | 110 | |
1a87e4fb LPC |
111 | if (!(hweight32(tx) & 1)) |
112 | tx |= ADXRS450_P; | |
232b1648 | 113 | |
1a87e4fb | 114 | st->tx = cpu_to_be32(tx); |
35734fbd | 115 | ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); |
24742ac6 MH |
116 | if (ret) { |
117 | dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n", | |
118 | reg_address); | |
119 | goto error_ret; | |
120 | } | |
121 | ||
1a87e4fb | 122 | *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF; |
24742ac6 MH |
123 | |
124 | error_ret: | |
125 | mutex_unlock(&st->buf_lock); | |
126 | return ret; | |
127 | } | |
128 | ||
129 | /** | |
130 | * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair | |
d5e69c83 | 131 | * @indio_dev: device associated with child of actual actual iio_dev |
1439b6e8 LPC |
132 | * @reg_address: the address of the lower of the two registers,which should be |
133 | * an even address, the second register's address is reg_address + 1. | |
24742ac6 MH |
134 | * @val: value to be written. |
135 | **/ | |
58ea7784 JC |
136 | static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev, |
137 | u8 reg_address, | |
138 | u16 val) | |
24742ac6 | 139 | { |
ba61bb18 | 140 | struct adxrs450_state *st = iio_priv(indio_dev); |
1a87e4fb | 141 | u32 tx; |
24742ac6 | 142 | int ret; |
24742ac6 MH |
143 | |
144 | mutex_lock(&st->buf_lock); | |
1a87e4fb | 145 | tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1); |
232b1648 | 146 | |
1a87e4fb LPC |
147 | if (!(hweight32(tx) & 1)) |
148 | tx |= ADXRS450_P; | |
232b1648 | 149 | |
1a87e4fb LPC |
150 | st->tx = cpu_to_be32(tx); |
151 | ret = spi_write(st->us, &st->tx, sizeof(st->tx)); | |
24742ac6 MH |
152 | if (ret) |
153 | dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n", | |
cb449687 | 154 | reg_address); |
619036e2 | 155 | usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */ |
24742ac6 MH |
156 | mutex_unlock(&st->buf_lock); |
157 | return ret; | |
158 | } | |
159 | ||
160 | /** | |
161 | * adxrs450_spi_sensor_data() - read 2 bytes sensor data | |
d5e69c83 | 162 | * @indio_dev: device associated with child of actual iio_dev |
24742ac6 MH |
163 | * @val: somewhere to pass back the value read |
164 | **/ | |
58ea7784 | 165 | static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) |
24742ac6 | 166 | { |
ba61bb18 | 167 | struct adxrs450_state *st = iio_priv(indio_dev); |
24742ac6 | 168 | int ret; |
6a6df2d9 LPC |
169 | struct spi_transfer xfers[] = { |
170 | { | |
1a87e4fb | 171 | .tx_buf = &st->tx, |
6a6df2d9 | 172 | .bits_per_word = 8, |
1a87e4fb | 173 | .len = sizeof(st->tx), |
6a6df2d9 LPC |
174 | .cs_change = 1, |
175 | }, { | |
1a87e4fb | 176 | .rx_buf = &st->rx, |
6a6df2d9 | 177 | .bits_per_word = 8, |
1a87e4fb | 178 | .len = sizeof(st->rx), |
6a6df2d9 LPC |
179 | }, |
180 | }; | |
24742ac6 MH |
181 | |
182 | mutex_lock(&st->buf_lock); | |
1a87e4fb | 183 | st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA); |
24742ac6 | 184 | |
35734fbd | 185 | ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); |
24742ac6 MH |
186 | if (ret) { |
187 | dev_err(&st->us->dev, "Problem while reading sensor data\n"); | |
188 | goto error_ret; | |
189 | } | |
190 | ||
1a87e4fb | 191 | *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF; |
caca8c89 | 192 | |
24742ac6 MH |
193 | error_ret: |
194 | mutex_unlock(&st->buf_lock); | |
195 | return ret; | |
196 | } | |
197 | ||
198 | /** | |
199 | * adxrs450_spi_initial() - use for initializing procedure. | |
200 | * @st: device instance specific data | |
201 | * @val: somewhere to pass back the value read | |
d5e69c83 | 202 | * @chk: Whether to perform fault check |
24742ac6 MH |
203 | **/ |
204 | static int adxrs450_spi_initial(struct adxrs450_state *st, | |
205 | u32 *val, char chk) | |
206 | { | |
24742ac6 | 207 | int ret; |
1a87e4fb | 208 | u32 tx; |
24742ac6 | 209 | struct spi_transfer xfers = { |
1a87e4fb LPC |
210 | .tx_buf = &st->tx, |
211 | .rx_buf = &st->rx, | |
24742ac6 | 212 | .bits_per_word = 8, |
1a87e4fb | 213 | .len = sizeof(st->tx), |
24742ac6 MH |
214 | }; |
215 | ||
216 | mutex_lock(&st->buf_lock); | |
1a87e4fb | 217 | tx = ADXRS450_SENSOR_DATA; |
24742ac6 | 218 | if (chk) |
1a87e4fb LPC |
219 | tx |= (ADXRS450_CHK | ADXRS450_P); |
220 | st->tx = cpu_to_be32(tx); | |
14543a00 | 221 | ret = spi_sync_transfer(st->us, &xfers, 1); |
24742ac6 MH |
222 | if (ret) { |
223 | dev_err(&st->us->dev, "Problem while reading initializing data\n"); | |
224 | goto error_ret; | |
225 | } | |
226 | ||
1a87e4fb | 227 | *val = be32_to_cpu(st->rx); |
24742ac6 MH |
228 | |
229 | error_ret: | |
230 | mutex_unlock(&st->buf_lock); | |
231 | return ret; | |
232 | } | |
233 | ||
24742ac6 | 234 | /* Recommended Startup Sequence by spec */ |
ba61bb18 | 235 | static int adxrs450_initial_setup(struct iio_dev *indio_dev) |
24742ac6 MH |
236 | { |
237 | u32 t; | |
238 | u16 data; | |
239 | int ret; | |
ba61bb18 | 240 | struct adxrs450_state *st = iio_priv(indio_dev); |
24742ac6 MH |
241 | |
242 | msleep(ADXRS450_STARTUP_DELAY*2); | |
243 | ret = adxrs450_spi_initial(st, &t, 1); | |
244 | if (ret) | |
245 | return ret; | |
1810b3bb | 246 | if (t != 0x01) |
457b71df | 247 | dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n"); |
24742ac6 MH |
248 | |
249 | msleep(ADXRS450_STARTUP_DELAY); | |
250 | ret = adxrs450_spi_initial(st, &t, 0); | |
251 | if (ret) | |
252 | return ret; | |
253 | ||
254 | msleep(ADXRS450_STARTUP_DELAY); | |
255 | ret = adxrs450_spi_initial(st, &t, 0); | |
256 | if (ret) | |
257 | return ret; | |
258 | if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { | |
259 | dev_err(&st->us->dev, "The second response is not correct!\n"); | |
260 | return -EIO; | |
261 | ||
262 | } | |
263 | ret = adxrs450_spi_initial(st, &t, 0); | |
264 | if (ret) | |
265 | return ret; | |
266 | if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) { | |
267 | dev_err(&st->us->dev, "The third response is not correct!\n"); | |
268 | return -EIO; | |
269 | ||
270 | } | |
58ea7784 | 271 | ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data); |
24742ac6 MH |
272 | if (ret) |
273 | return ret; | |
274 | if (data & 0x0fff) { | |
275 | dev_err(&st->us->dev, "The device is not in normal status!\n"); | |
276 | return -EINVAL; | |
277 | } | |
24742ac6 MH |
278 | |
279 | return 0; | |
280 | } | |
281 | ||
58ea7784 JC |
282 | static int adxrs450_write_raw(struct iio_dev *indio_dev, |
283 | struct iio_chan_spec const *chan, | |
284 | int val, | |
285 | int val2, | |
286 | long mask) | |
287 | { | |
288 | int ret; | |
289 | switch (mask) { | |
c8a9f805 | 290 | case IIO_CHAN_INFO_CALIBBIAS: |
9a26578c LPC |
291 | if (val < -0x400 || val >= 0x400) |
292 | return -EINVAL; | |
58ea7784 | 293 | ret = adxrs450_spi_write_reg_16(indio_dev, |
9a26578c | 294 | ADXRS450_DNC1, val); |
58ea7784 JC |
295 | break; |
296 | default: | |
297 | ret = -EINVAL; | |
298 | break; | |
299 | } | |
300 | return ret; | |
301 | } | |
302 | ||
303 | static int adxrs450_read_raw(struct iio_dev *indio_dev, | |
304 | struct iio_chan_spec const *chan, | |
305 | int *val, | |
306 | int *val2, | |
307 | long mask) | |
308 | { | |
309 | int ret; | |
037bad9a | 310 | s16 t; |
90b9b227 | 311 | |
58ea7784 | 312 | switch (mask) { |
fbaff213 | 313 | case IIO_CHAN_INFO_RAW: |
58ea7784 | 314 | switch (chan->type) { |
41ea040c | 315 | case IIO_ANGL_VEL: |
037bad9a JC |
316 | ret = adxrs450_spi_sensor_data(indio_dev, &t); |
317 | if (ret) | |
58ea7784 | 318 | break; |
037bad9a | 319 | *val = t; |
58ea7784 JC |
320 | ret = IIO_VAL_INT; |
321 | break; | |
322 | case IIO_TEMP: | |
037bad9a | 323 | ret = adxrs450_spi_read_reg_16(indio_dev, |
90b9b227 | 324 | ADXRS450_TEMP1, &t); |
037bad9a | 325 | if (ret) |
58ea7784 | 326 | break; |
90b9b227 | 327 | *val = (t >> 6) + 225; |
58ea7784 JC |
328 | ret = IIO_VAL_INT; |
329 | break; | |
330 | default: | |
331 | ret = -EINVAL; | |
332 | break; | |
333 | } | |
334 | break; | |
90b9b227 MH |
335 | case IIO_CHAN_INFO_SCALE: |
336 | switch (chan->type) { | |
337 | case IIO_ANGL_VEL: | |
338 | *val = 0; | |
339 | *val2 = 218166; | |
340 | return IIO_VAL_INT_PLUS_NANO; | |
341 | case IIO_TEMP: | |
342 | *val = 200; | |
343 | *val2 = 0; | |
344 | return IIO_VAL_INT; | |
345 | default: | |
346 | return -EINVAL; | |
347 | } | |
c8a9f805 | 348 | case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: |
037bad9a JC |
349 | ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); |
350 | if (ret) | |
58ea7784 | 351 | break; |
037bad9a | 352 | *val = t; |
58ea7784 JC |
353 | ret = IIO_VAL_INT; |
354 | break; | |
9631135d MH |
355 | case IIO_CHAN_INFO_CALIBBIAS: |
356 | ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t); | |
357 | if (ret) | |
358 | break; | |
c62b89c7 | 359 | *val = sign_extend32(t, 9); |
9631135d MH |
360 | ret = IIO_VAL_INT; |
361 | break; | |
58ea7784 JC |
362 | default: |
363 | ret = -EINVAL; | |
364 | break; | |
365 | } | |
366 | ||
367 | return ret; | |
368 | } | |
24742ac6 | 369 | |
617156fb MH |
370 | static const struct iio_chan_spec adxrs450_channels[2][2] = { |
371 | [ID_ADXRS450] = { | |
372 | { | |
373 | .type = IIO_ANGL_VEL, | |
374 | .modified = 1, | |
375 | .channel2 = IIO_MOD_Z, | |
98bfb6e3 JC |
376 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
377 | BIT(IIO_CHAN_INFO_CALIBBIAS) | | |
378 | BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) | | |
379 | BIT(IIO_CHAN_INFO_SCALE), | |
617156fb MH |
380 | }, { |
381 | .type = IIO_TEMP, | |
382 | .indexed = 1, | |
383 | .channel = 0, | |
98bfb6e3 JC |
384 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
385 | BIT(IIO_CHAN_INFO_SCALE), | |
617156fb MH |
386 | } |
387 | }, | |
388 | [ID_ADXRS453] = { | |
389 | { | |
390 | .type = IIO_ANGL_VEL, | |
391 | .modified = 1, | |
392 | .channel2 = IIO_MOD_Z, | |
98bfb6e3 JC |
393 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
394 | BIT(IIO_CHAN_INFO_SCALE) | | |
395 | BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW), | |
617156fb MH |
396 | }, { |
397 | .type = IIO_TEMP, | |
398 | .indexed = 1, | |
399 | .channel = 0, | |
98bfb6e3 JC |
400 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
401 | BIT(IIO_CHAN_INFO_SCALE), | |
617156fb MH |
402 | } |
403 | }, | |
24742ac6 MH |
404 | }; |
405 | ||
6fe8135f | 406 | static const struct iio_info adxrs450_info = { |
58ea7784 JC |
407 | .read_raw = &adxrs450_read_raw, |
408 | .write_raw = &adxrs450_write_raw, | |
6fe8135f JC |
409 | }; |
410 | ||
4ae1c61f | 411 | static int adxrs450_probe(struct spi_device *spi) |
24742ac6 | 412 | { |
d2fffd6c | 413 | int ret; |
ba61bb18 JC |
414 | struct adxrs450_state *st; |
415 | struct iio_dev *indio_dev; | |
24742ac6 | 416 | |
ba61bb18 | 417 | /* setup the industrialio driver allocated elements */ |
6694cf96 SK |
418 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
419 | if (!indio_dev) | |
420 | return -ENOMEM; | |
ba61bb18 | 421 | st = iio_priv(indio_dev); |
24742ac6 MH |
422 | st->us = spi; |
423 | mutex_init(&st->buf_lock); | |
ba61bb18 JC |
424 | /* This is only used for removal purposes */ |
425 | spi_set_drvdata(spi, indio_dev); | |
24742ac6 | 426 | |
ba61bb18 JC |
427 | indio_dev->info = &adxrs450_info; |
428 | indio_dev->modes = INDIO_DIRECT_MODE; | |
617156fb MH |
429 | indio_dev->channels = |
430 | adxrs450_channels[spi_get_device_id(spi)->driver_data]; | |
58ea7784 JC |
431 | indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels); |
432 | indio_dev->name = spi->dev.driver->name; | |
24742ac6 | 433 | |
9bcbf02a | 434 | ret = devm_iio_device_register(&spi->dev, indio_dev); |
24742ac6 | 435 | if (ret) |
6694cf96 | 436 | return ret; |
24742ac6 MH |
437 | |
438 | /* Get the device into a sane initial state */ | |
ba61bb18 | 439 | ret = adxrs450_initial_setup(indio_dev); |
24742ac6 | 440 | if (ret) |
9bcbf02a | 441 | return ret; |
24742ac6 MH |
442 | |
443 | return 0; | |
444 | } | |
445 | ||
617156fb MH |
446 | static const struct spi_device_id adxrs450_id[] = { |
447 | {"adxrs450", ID_ADXRS450}, | |
448 | {"adxrs453", ID_ADXRS453}, | |
449 | {} | |
450 | }; | |
451 | MODULE_DEVICE_TABLE(spi, adxrs450_id); | |
452 | ||
24742ac6 MH |
453 | static struct spi_driver adxrs450_driver = { |
454 | .driver = { | |
455 | .name = "adxrs450", | |
24742ac6 MH |
456 | }, |
457 | .probe = adxrs450_probe, | |
617156fb | 458 | .id_table = adxrs450_id, |
24742ac6 | 459 | }; |
ae6ae6fe | 460 | module_spi_driver(adxrs450_driver); |
24742ac6 MH |
461 | |
462 | MODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>"); | |
617156fb | 463 | MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver"); |
24742ac6 | 464 | MODULE_LICENSE("GPL v2"); |