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