diff options
Diffstat (limited to 'drivers/staging/iio/imu/adis16400_core.c')
-rw-r--r-- | drivers/staging/iio/imu/adis16400_core.c | 424 |
1 files changed, 223 insertions, 201 deletions
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 33c5f3c018f..6f43cc9bb72 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | #define DRIVER_NAME "adis16400" | 39 | #define DRIVER_NAME "adis16400" |
40 | 40 | ||
41 | static int adis16400_check_status(struct device *dev); | 41 | static int adis16400_check_status(struct iio_dev *indio_dev); |
42 | 42 | ||
43 | /* At the moment the spi framework doesn't allow global setting of cs_change. | 43 | /* At the moment the spi framework doesn't allow global setting of cs_change. |
44 | * It's in the likely to be added comment at the top of spi.h. | 44 | * It's in the likely to be added comment at the top of spi.h. |
@@ -51,12 +51,11 @@ static int adis16400_check_status(struct device *dev); | |||
51 | * @reg_address: the address of the register to be written | 51 | * @reg_address: the address of the register to be written |
52 | * @val: the value to write | 52 | * @val: the value to write |
53 | **/ | 53 | **/ |
54 | static int adis16400_spi_write_reg_8(struct device *dev, | 54 | static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev, |
55 | u8 reg_address, | 55 | u8 reg_address, |
56 | u8 val) | 56 | u8 val) |
57 | { | 57 | { |
58 | int ret; | 58 | int ret; |
59 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
60 | struct adis16400_state *st = iio_dev_get_devdata(indio_dev); | 59 | struct adis16400_state *st = iio_dev_get_devdata(indio_dev); |
61 | 60 | ||
62 | mutex_lock(&st->buf_lock); | 61 | mutex_lock(&st->buf_lock); |
@@ -76,13 +75,12 @@ static int adis16400_spi_write_reg_8(struct device *dev, | |||
76 | * is assumed to have address one greater. | 75 | * is assumed to have address one greater. |
77 | * @val: value to be written | 76 | * @val: value to be written |
78 | **/ | 77 | **/ |
79 | static int adis16400_spi_write_reg_16(struct device *dev, | 78 | static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev, |
80 | u8 lower_reg_address, | 79 | u8 lower_reg_address, |
81 | u16 value) | 80 | u16 value) |
82 | { | 81 | { |
83 | int ret; | 82 | int ret; |
84 | struct spi_message msg; | 83 | struct spi_message msg; |
85 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
86 | struct adis16400_state *st = iio_dev_get_devdata(indio_dev); | 84 | struct adis16400_state *st = iio_dev_get_devdata(indio_dev); |
87 | struct spi_transfer xfers[] = { | 85 | struct spi_transfer xfers[] = { |
88 | { | 86 | { |
@@ -114,17 +112,16 @@ static int adis16400_spi_write_reg_16(struct device *dev, | |||
114 | 112 | ||
115 | /** | 113 | /** |
116 | * adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register | 114 | * adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register |
117 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | 115 | * @indio_dev: iio device |
118 | * @reg_address: the address of the lower of the two registers. Second register | 116 | * @reg_address: the address of the lower of the two registers. Second register |
119 | * is assumed to have address one greater. | 117 | * is assumed to have address one greater. |
120 | * @val: somewhere to pass back the value read | 118 | * @val: somewhere to pass back the value read |
121 | **/ | 119 | **/ |
122 | static int adis16400_spi_read_reg_16(struct device *dev, | 120 | static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev, |
123 | u8 lower_reg_address, | 121 | u8 lower_reg_address, |
124 | u16 *val) | 122 | u16 *val) |
125 | { | 123 | { |
126 | struct spi_message msg; | 124 | struct spi_message msg; |
127 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
128 | struct adis16400_state *st = iio_dev_get_devdata(indio_dev); | 125 | struct adis16400_state *st = iio_dev_get_devdata(indio_dev); |
129 | int ret; | 126 | int ret; |
130 | struct spi_transfer xfers[] = { | 127 | struct spi_transfer xfers[] = { |
@@ -163,100 +160,15 @@ error_ret: | |||
163 | return ret; | 160 | return ret; |
164 | } | 161 | } |
165 | 162 | ||
166 | static ssize_t adis16400_spi_read_signed(struct device *dev, | ||
167 | struct device_attribute *attr, | ||
168 | char *buf, | ||
169 | unsigned bits) | ||
170 | { | ||
171 | int ret; | ||
172 | s16 val = 0; | ||
173 | unsigned shift = 16 - bits; | ||
174 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
175 | |||
176 | ret = adis16400_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); | ||
177 | if (ret) | ||
178 | return ret; | ||
179 | |||
180 | if (val & ADIS16400_ERROR_ACTIVE) | ||
181 | adis16400_check_status(dev); | ||
182 | val = ((s16)(val << shift) >> shift); | ||
183 | return sprintf(buf, "%d\n", val); | ||
184 | } | ||
185 | |||
186 | static ssize_t adis16400_read_12bit_unsigned(struct device *dev, | ||
187 | struct device_attribute *attr, | ||
188 | char *buf) | ||
189 | { | ||
190 | int ret; | ||
191 | u16 val = 0; | ||
192 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
193 | |||
194 | ret = adis16400_spi_read_reg_16(dev, this_attr->address, &val); | ||
195 | if (ret) | ||
196 | return ret; | ||
197 | |||
198 | if (val & ADIS16400_ERROR_ACTIVE) | ||
199 | adis16400_check_status(dev); | ||
200 | |||
201 | return sprintf(buf, "%u\n", val & 0x0FFF); | ||
202 | } | ||
203 | |||
204 | static ssize_t adis16400_read_14bit_signed(struct device *dev, | ||
205 | struct device_attribute *attr, | ||
206 | char *buf) | ||
207 | { | ||
208 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
209 | ssize_t ret; | ||
210 | |||
211 | /* Take the iio_dev status lock */ | ||
212 | mutex_lock(&indio_dev->mlock); | ||
213 | ret = adis16400_spi_read_signed(dev, attr, buf, 14); | ||
214 | mutex_unlock(&indio_dev->mlock); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static ssize_t adis16400_read_12bit_signed(struct device *dev, | ||
220 | struct device_attribute *attr, | ||
221 | char *buf) | ||
222 | { | ||
223 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
224 | ssize_t ret; | ||
225 | |||
226 | /* Take the iio_dev status lock */ | ||
227 | mutex_lock(&indio_dev->mlock); | ||
228 | ret = adis16400_spi_read_signed(dev, attr, buf, 12); | ||
229 | mutex_unlock(&indio_dev->mlock); | ||
230 | |||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | static ssize_t adis16400_write_16bit(struct device *dev, | ||
235 | struct device_attribute *attr, | ||
236 | const char *buf, | ||
237 | size_t len) | ||
238 | { | ||
239 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
240 | int ret; | ||
241 | long val; | ||
242 | |||
243 | ret = strict_strtol(buf, 10, &val); | ||
244 | if (ret) | ||
245 | goto error_ret; | ||
246 | ret = adis16400_spi_write_reg_16(dev, this_attr->address, val); | ||
247 | |||
248 | error_ret: | ||
249 | return ret ? ret : len; | ||
250 | } | ||
251 | |||
252 | static ssize_t adis16400_read_frequency(struct device *dev, | 163 | static ssize_t adis16400_read_frequency(struct device *dev, |
253 | struct device_attribute *attr, | 164 | struct device_attribute *attr, |
254 | char *buf) | 165 | char *buf) |
255 | { | 166 | { |
167 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
256 | int ret, len = 0; | 168 | int ret, len = 0; |
257 | u16 t; | 169 | u16 t; |
258 | int sps; | 170 | int sps; |
259 | ret = adis16400_spi_read_reg_16(dev, | 171 | ret = adis16400_spi_read_reg_16(indio_dev, |
260 | ADIS16400_SMPL_PRD, | 172 | ADIS16400_SMPL_PRD, |
261 | &t); | 173 | &t); |
262 | if (ret) | 174 | if (ret) |
@@ -293,7 +205,7 @@ static ssize_t adis16400_write_frequency(struct device *dev, | |||
293 | else | 205 | else |
294 | st->us->max_speed_hz = ADIS16400_SPI_FAST; | 206 | st->us->max_speed_hz = ADIS16400_SPI_FAST; |
295 | 207 | ||
296 | ret = adis16400_spi_write_reg_8(dev, | 208 | ret = adis16400_spi_write_reg_8(indio_dev, |
297 | ADIS16400_SMPL_PRD, | 209 | ADIS16400_SMPL_PRD, |
298 | t); | 210 | t); |
299 | 211 | ||
@@ -302,14 +214,14 @@ static ssize_t adis16400_write_frequency(struct device *dev, | |||
302 | return ret ? ret : len; | 214 | return ret ? ret : len; |
303 | } | 215 | } |
304 | 216 | ||
305 | static int adis16400_reset(struct device *dev) | 217 | static int adis16400_reset(struct iio_dev *indio_dev) |
306 | { | 218 | { |
307 | int ret; | 219 | int ret; |
308 | ret = adis16400_spi_write_reg_8(dev, | 220 | ret = adis16400_spi_write_reg_8(indio_dev, |
309 | ADIS16400_GLOB_CMD, | 221 | ADIS16400_GLOB_CMD, |
310 | ADIS16400_GLOB_CMD_SW_RESET); | 222 | ADIS16400_GLOB_CMD_SW_RESET); |
311 | if (ret) | 223 | if (ret) |
312 | dev_err(dev, "problem resetting device"); | 224 | dev_err(&indio_dev->dev, "problem resetting device"); |
313 | 225 | ||
314 | return ret; | 226 | return ret; |
315 | } | 227 | } |
@@ -318,22 +230,24 @@ static ssize_t adis16400_write_reset(struct device *dev, | |||
318 | struct device_attribute *attr, | 230 | struct device_attribute *attr, |
319 | const char *buf, size_t len) | 231 | const char *buf, size_t len) |
320 | { | 232 | { |
233 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
234 | |||
321 | if (len < 1) | 235 | if (len < 1) |
322 | return -1; | 236 | return -1; |
323 | switch (buf[0]) { | 237 | switch (buf[0]) { |
324 | case '1': | 238 | case '1': |
325 | case 'y': | 239 | case 'y': |
326 | case 'Y': | 240 | case 'Y': |
327 | return adis16400_reset(dev); | 241 | return adis16400_reset(indio_dev); |
328 | } | 242 | } |
329 | return -1; | 243 | return -1; |
330 | } | 244 | } |
331 | 245 | ||
332 | int adis16400_set_irq(struct device *dev, bool enable) | 246 | int adis16400_set_irq(struct iio_dev *indio_dev, bool enable) |
333 | { | 247 | { |
334 | int ret; | 248 | int ret; |
335 | u16 msc; | 249 | u16 msc; |
336 | ret = adis16400_spi_read_reg_16(dev, ADIS16400_MSC_CTRL, &msc); | 250 | ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_MSC_CTRL, &msc); |
337 | if (ret) | 251 | if (ret) |
338 | goto error_ret; | 252 | goto error_ret; |
339 | 253 | ||
@@ -343,7 +257,7 @@ int adis16400_set_irq(struct device *dev, bool enable) | |||
343 | else | 257 | else |
344 | msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN; | 258 | msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN; |
345 | 259 | ||
346 | ret = adis16400_spi_write_reg_16(dev, ADIS16400_MSC_CTRL, msc); | 260 | ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_MSC_CTRL, msc); |
347 | if (ret) | 261 | if (ret) |
348 | goto error_ret; | 262 | goto error_ret; |
349 | 263 | ||
@@ -352,41 +266,45 @@ error_ret: | |||
352 | } | 266 | } |
353 | 267 | ||
354 | /* Power down the device */ | 268 | /* Power down the device */ |
355 | static int adis16400_stop_device(struct device *dev) | 269 | static int adis16400_stop_device(struct iio_dev *indio_dev) |
356 | { | 270 | { |
357 | int ret; | 271 | int ret; |
358 | u16 val = ADIS16400_SLP_CNT_POWER_OFF; | 272 | u16 val = ADIS16400_SLP_CNT_POWER_OFF; |
359 | 273 | ||
360 | ret = adis16400_spi_write_reg_16(dev, ADIS16400_SLP_CNT, val); | 274 | ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_SLP_CNT, val); |
361 | if (ret) | 275 | if (ret) |
362 | dev_err(dev, "problem with turning device off: SLP_CNT"); | 276 | dev_err(&indio_dev->dev, |
277 | "problem with turning device off: SLP_CNT"); | ||
363 | 278 | ||
364 | return ret; | 279 | return ret; |
365 | } | 280 | } |
366 | 281 | ||
367 | static int adis16400_self_test(struct device *dev) | 282 | static int adis16400_self_test(struct iio_dev *indio_dev) |
368 | { | 283 | { |
369 | int ret; | 284 | int ret; |
370 | ret = adis16400_spi_write_reg_16(dev, | 285 | ret = adis16400_spi_write_reg_16(indio_dev, |
371 | ADIS16400_MSC_CTRL, | 286 | ADIS16400_MSC_CTRL, |
372 | ADIS16400_MSC_CTRL_MEM_TEST); | 287 | ADIS16400_MSC_CTRL_MEM_TEST); |
373 | if (ret) { | 288 | if (ret) { |
374 | dev_err(dev, "problem starting self test"); | 289 | dev_err(&indio_dev->dev, "problem starting self test"); |
375 | goto err_ret; | 290 | goto err_ret; |
376 | } | 291 | } |
292 | |||
377 | msleep(ADIS16400_MTEST_DELAY); | 293 | msleep(ADIS16400_MTEST_DELAY); |
378 | adis16400_check_status(dev); | 294 | adis16400_check_status(indio_dev); |
379 | 295 | ||
380 | err_ret: | 296 | err_ret: |
381 | return ret; | 297 | return ret; |
382 | } | 298 | } |
383 | 299 | ||
384 | static int adis16400_check_status(struct device *dev) | 300 | static int adis16400_check_status(struct iio_dev *indio_dev) |
385 | { | 301 | { |
386 | u16 status; | 302 | u16 status; |
387 | int ret; | 303 | int ret; |
304 | struct device *dev = &indio_dev->dev; | ||
388 | 305 | ||
389 | ret = adis16400_spi_read_reg_16(dev, ADIS16400_DIAG_STAT, &status); | 306 | ret = adis16400_spi_read_reg_16(indio_dev, |
307 | ADIS16400_DIAG_STAT, &status); | ||
390 | 308 | ||
391 | if (ret < 0) { | 309 | if (ret < 0) { |
392 | dev_err(dev, "Reading status failed\n"); | 310 | dev_err(dev, "Reading status failed\n"); |
@@ -440,33 +358,34 @@ static int adis16400_initial_setup(struct adis16400_state *st) | |||
440 | spi_setup(st->us); | 358 | spi_setup(st->us); |
441 | 359 | ||
442 | /* Disable IRQ */ | 360 | /* Disable IRQ */ |
443 | ret = adis16400_set_irq(dev, false); | 361 | ret = adis16400_set_irq(st->indio_dev, false); |
444 | if (ret) { | 362 | if (ret) { |
445 | dev_err(dev, "disable irq failed"); | 363 | dev_err(dev, "disable irq failed"); |
446 | goto err_ret; | 364 | goto err_ret; |
447 | } | 365 | } |
448 | 366 | ||
449 | /* Do self test */ | 367 | /* Do self test */ |
450 | ret = adis16400_self_test(dev); | 368 | ret = adis16400_self_test(st->indio_dev); |
451 | if (ret) { | 369 | if (ret) { |
452 | dev_err(dev, "self test failure"); | 370 | dev_err(dev, "self test failure"); |
453 | goto err_ret; | 371 | goto err_ret; |
454 | } | 372 | } |
455 | 373 | ||
456 | /* Read status register to check the result */ | 374 | /* Read status register to check the result */ |
457 | ret = adis16400_check_status(dev); | 375 | ret = adis16400_check_status(st->indio_dev); |
458 | if (ret) { | 376 | if (ret) { |
459 | adis16400_reset(dev); | 377 | adis16400_reset(st->indio_dev); |
460 | dev_err(dev, "device not playing ball -> reset"); | 378 | dev_err(dev, "device not playing ball -> reset"); |
461 | msleep(ADIS16400_STARTUP_DELAY); | 379 | msleep(ADIS16400_STARTUP_DELAY); |
462 | ret = adis16400_check_status(dev); | 380 | ret = adis16400_check_status(st->indio_dev); |
463 | if (ret) { | 381 | if (ret) { |
464 | dev_err(dev, "giving up"); | 382 | dev_err(dev, "giving up"); |
465 | goto err_ret; | 383 | goto err_ret; |
466 | } | 384 | } |
467 | } | 385 | } |
468 | 386 | ||
469 | ret = adis16400_spi_read_reg_16(dev, ADIS16400_PRODUCT_ID, &prod_id); | 387 | ret = adis16400_spi_read_reg_16(st->indio_dev, |
388 | ADIS16400_PRODUCT_ID, &prod_id); | ||
470 | if (ret) | 389 | if (ret) |
471 | goto err_ret; | 390 | goto err_ret; |
472 | 391 | ||
@@ -478,7 +397,8 @@ static int adis16400_initial_setup(struct adis16400_state *st) | |||
478 | prod_id, st->us->chip_select, st->us->irq); | 397 | prod_id, st->us->chip_select, st->us->irq); |
479 | 398 | ||
480 | /* use high spi speed if possible */ | 399 | /* use high spi speed if possible */ |
481 | ret = adis16400_spi_read_reg_16(dev, ADIS16400_SMPL_PRD, &smp_prd); | 400 | ret = adis16400_spi_read_reg_16(st->indio_dev, |
401 | ADIS16400_SMPL_PRD, &smp_prd); | ||
482 | if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) { | 402 | if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) { |
483 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; | 403 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; |
484 | spi_setup(st->us); | 404 | spi_setup(st->us); |
@@ -490,58 +410,6 @@ err_ret: | |||
490 | return ret; | 410 | return ret; |
491 | } | 411 | } |
492 | 412 | ||
493 | #define ADIS16400_DEV_ATTR_CALIBBIAS(_channel, _reg) \ | ||
494 | IIO_DEV_ATTR_##_channel##_CALIBBIAS(S_IWUSR | S_IRUGO, \ | ||
495 | adis16400_read_12bit_signed, \ | ||
496 | adis16400_write_16bit, \ | ||
497 | _reg) | ||
498 | |||
499 | static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_X, ADIS16400_XGYRO_OFF); | ||
500 | static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Y, ADIS16400_YGYRO_OFF); | ||
501 | static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Z, ADIS16400_ZGYRO_OFF); | ||
502 | |||
503 | static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_X, ADIS16400_XACCL_OFF); | ||
504 | static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Y, ADIS16400_YACCL_OFF); | ||
505 | static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Z, ADIS16400_ZACCL_OFF); | ||
506 | |||
507 | |||
508 | static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16400_read_14bit_signed, | ||
509 | ADIS16400_SUPPLY_OUT); | ||
510 | static IIO_CONST_ATTR_IN_NAMED_SCALE(0, supply, "0.002418 V"); | ||
511 | |||
512 | static IIO_DEV_ATTR_GYRO_X(adis16400_read_14bit_signed, | ||
513 | ADIS16400_XGYRO_OUT); | ||
514 | static IIO_DEV_ATTR_GYRO_Y(adis16400_read_14bit_signed, | ||
515 | ADIS16400_YGYRO_OUT); | ||
516 | static IIO_DEV_ATTR_GYRO_Z(adis16400_read_14bit_signed, | ||
517 | ADIS16400_ZGYRO_OUT); | ||
518 | static IIO_CONST_ATTR(gyro_scale, "0.0008726646"); | ||
519 | |||
520 | static IIO_DEV_ATTR_ACCEL_X(adis16400_read_14bit_signed, | ||
521 | ADIS16400_XACCL_OUT); | ||
522 | static IIO_DEV_ATTR_ACCEL_Y(adis16400_read_14bit_signed, | ||
523 | ADIS16400_YACCL_OUT); | ||
524 | static IIO_DEV_ATTR_ACCEL_Z(adis16400_read_14bit_signed, | ||
525 | ADIS16400_ZACCL_OUT); | ||
526 | static IIO_CONST_ATTR(accel_scale, "0.0326561445"); | ||
527 | |||
528 | static IIO_DEV_ATTR_MAGN_X(adis16400_read_14bit_signed, | ||
529 | ADIS16400_XMAGN_OUT); | ||
530 | static IIO_DEV_ATTR_MAGN_Y(adis16400_read_14bit_signed, | ||
531 | ADIS16400_YMAGN_OUT); | ||
532 | static IIO_DEV_ATTR_MAGN_Z(adis16400_read_14bit_signed, | ||
533 | ADIS16400_ZMAGN_OUT); | ||
534 | static IIO_CONST_ATTR(magn_scale, "0.0005 Gs"); | ||
535 | |||
536 | |||
537 | static IIO_DEV_ATTR_TEMP_RAW(adis16400_read_12bit_signed); | ||
538 | static IIO_CONST_ATTR_TEMP_OFFSET("198.16 K"); | ||
539 | static IIO_CONST_ATTR_TEMP_SCALE("0.14 K"); | ||
540 | |||
541 | static IIO_DEV_ATTR_IN_RAW(1, adis16400_read_12bit_unsigned, | ||
542 | ADIS16400_AUX_ADC); | ||
543 | static IIO_CONST_ATTR(in1_scale, "0.000806 V"); | ||
544 | |||
545 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | 413 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, |
546 | adis16400_read_frequency, | 414 | adis16400_read_frequency, |
547 | adis16400_write_frequency); | 415 | adis16400_write_frequency); |
@@ -552,32 +420,184 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638"); | |||
552 | 420 | ||
553 | static IIO_CONST_ATTR_NAME("adis16400"); | 421 | static IIO_CONST_ATTR_NAME("adis16400"); |
554 | 422 | ||
423 | enum adis16400_chan { | ||
424 | in_supply, | ||
425 | gyro_x, | ||
426 | gyro_y, | ||
427 | gyro_z, | ||
428 | accel_x, | ||
429 | accel_y, | ||
430 | accel_z, | ||
431 | magn_x, | ||
432 | magn_y, | ||
433 | magn_z, | ||
434 | temp, | ||
435 | in1 | ||
436 | }; | ||
437 | |||
438 | static u8 adis16400_addresses[12][2] = { | ||
439 | [in_supply] = { ADIS16400_SUPPLY_OUT, 0 }, | ||
440 | [gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF }, | ||
441 | [gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF }, | ||
442 | [gyro_z] = { ADIS16400_ZGYRO_OUT, ADIS16400_ZGYRO_OFF }, | ||
443 | [accel_x] = { ADIS16400_XACCL_OUT, ADIS16400_XACCL_OFF }, | ||
444 | [accel_y] = { ADIS16400_YACCL_OUT, ADIS16400_YACCL_OFF }, | ||
445 | [accel_z] = { ADIS16400_ZACCL_OUT, ADIS16400_ZACCL_OFF }, | ||
446 | [magn_x] = { ADIS16400_XMAGN_OUT, 0 }, | ||
447 | [magn_y] = { ADIS16400_YMAGN_OUT, 0 }, | ||
448 | [magn_z] = { ADIS16400_ZMAGN_OUT, 0 }, | ||
449 | [temp] = { ADIS16400_TEMP_OUT, 0 }, | ||
450 | [in1] = { ADIS16400_AUX_ADC , 0 }, | ||
451 | }; | ||
452 | |||
453 | static int adis16400_write_raw(struct iio_dev *indio_dev, | ||
454 | struct iio_chan_spec const *chan, | ||
455 | int val, | ||
456 | int val2, | ||
457 | long mask) | ||
458 | { | ||
459 | int ret; | ||
460 | switch (mask) { | ||
461 | case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): | ||
462 | mutex_lock(&indio_dev->mlock); | ||
463 | ret = adis16400_spi_write_reg_16(indio_dev, | ||
464 | adis16400_addresses[chan->address][1], | ||
465 | val); | ||
466 | mutex_unlock(&indio_dev->mlock); | ||
467 | return ret; | ||
468 | default: | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | } | ||
472 | |||
473 | static int adis16400_read_raw(struct iio_dev *indio_dev, | ||
474 | struct iio_chan_spec const *chan, | ||
475 | int *val, | ||
476 | int *val2, | ||
477 | long mask) | ||
478 | { | ||
479 | int ret; | ||
480 | s16 val16; | ||
481 | int shift; | ||
482 | |||
483 | switch (mask) { | ||
484 | case 0: | ||
485 | mutex_lock(&indio_dev->mlock); | ||
486 | ret = adis16400_spi_read_reg_16(indio_dev, | ||
487 | adis16400_addresses[chan->address][0], | ||
488 | &val16); | ||
489 | if (ret) { | ||
490 | mutex_unlock(&indio_dev->mlock); | ||
491 | return ret; | ||
492 | } | ||
493 | val16 &= (1 << chan->scan_type.realbits) - 1; | ||
494 | if (chan->scan_type.sign == 's') { | ||
495 | shift = 16 - chan->scan_type.realbits; | ||
496 | val16 = (s16)(val16 << shift) >> shift; | ||
497 | } | ||
498 | *val = val16; | ||
499 | mutex_unlock(&indio_dev->mlock); | ||
500 | return IIO_VAL_INT; | ||
501 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
502 | case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): | ||
503 | switch (chan->type) { | ||
504 | case IIO_GYRO: | ||
505 | *val = 0; | ||
506 | *val2 = 873; | ||
507 | return IIO_VAL_INT_PLUS_MICRO; | ||
508 | case IIO_IN: | ||
509 | *val = 0; | ||
510 | if (chan->channel == 0) | ||
511 | *val2 = 2418; | ||
512 | else | ||
513 | *val2 = 806; | ||
514 | return IIO_VAL_INT_PLUS_MICRO; | ||
515 | case IIO_ACCEL: | ||
516 | *val = 0; | ||
517 | *val2 = 32656; | ||
518 | return IIO_VAL_INT_PLUS_MICRO; | ||
519 | case IIO_MAGN: | ||
520 | *val = 0; | ||
521 | *val2 = 500; | ||
522 | return IIO_VAL_INT_PLUS_MICRO; | ||
523 | case IIO_TEMP: | ||
524 | *val = 0; | ||
525 | *val2 = 140000; | ||
526 | return IIO_VAL_INT_PLUS_MICRO; | ||
527 | default: | ||
528 | return -EINVAL; | ||
529 | } | ||
530 | case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): | ||
531 | mutex_lock(&indio_dev->mlock); | ||
532 | ret = adis16400_spi_read_reg_16(indio_dev, | ||
533 | adis16400_addresses[chan->address][1], | ||
534 | &val16); | ||
535 | if (ret) { | ||
536 | mutex_unlock(&indio_dev->mlock); | ||
537 | return ret; | ||
538 | } | ||
539 | val16 = ((val16 & 0xFFF) << 4) >> 4; | ||
540 | *val = val16; | ||
541 | return IIO_VAL_INT; | ||
542 | case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): | ||
543 | /* currently only temperature */ | ||
544 | *val = 198; | ||
545 | *val2 = 160000; | ||
546 | return IIO_VAL_INT_PLUS_MICRO; | ||
547 | default: | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | } | ||
551 | |||
552 | static struct iio_chan_spec adis16400_channels[] = { | ||
553 | IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 0, 0, | ||
554 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
555 | in_supply, ADIS16400_SCAN_SUPPLY, | ||
556 | IIO_ST('u', 14, 16, 0), 0), | ||
557 | IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_X, | ||
558 | (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | | ||
559 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
560 | gyro_x, ADIS16400_SCAN_GYRO_X, IIO_ST('s', 14, 16, 0), 0), | ||
561 | IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Y, | ||
562 | (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | | ||
563 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
564 | gyro_y, ADIS16400_SCAN_GYRO_Y, IIO_ST('s', 14, 16, 0), 0), | ||
565 | IIO_CHAN(IIO_GYRO, 1, 0, 0, NULL, 0, IIO_MOD_Z, | ||
566 | (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | | ||
567 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
568 | gyro_z, ADIS16400_SCAN_GYRO_Z, IIO_ST('s', 14, 16, 0), 0), | ||
569 | IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, | ||
570 | (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | | ||
571 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
572 | accel_x, ADIS16400_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), | ||
573 | IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, | ||
574 | (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | | ||
575 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
576 | accel_y, ADIS16400_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), | ||
577 | IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, | ||
578 | (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | | ||
579 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
580 | accel_z, ADIS16400_SCAN_ACC_Z, IIO_ST('s', 14, 16, 0), 0), | ||
581 | IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_X, | ||
582 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
583 | magn_x, ADIS16400_SCAN_MAGN_X, IIO_ST('s', 14, 16, 0), 0), | ||
584 | IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Y, | ||
585 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
586 | magn_y, ADIS16400_SCAN_MAGN_Y, IIO_ST('s', 14, 16, 0), 0), | ||
587 | IIO_CHAN(IIO_MAGN, 1, 0, 0, NULL, 0, IIO_MOD_Z, | ||
588 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
589 | magn_z, ADIS16400_SCAN_MAGN_Z, IIO_ST('s', 14, 16, 0), 0), | ||
590 | IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, | ||
591 | (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | | ||
592 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
593 | temp, ADIS16400_SCAN_TEMP, IIO_ST('s', 12, 16, 0), 0), | ||
594 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, | ||
595 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
596 | in1, ADIS16400_SCAN_ADC_0, IIO_ST('s', 12, 16, 0), 0), | ||
597 | IIO_CHAN_SOFT_TIMESTAMP(12) | ||
598 | }; | ||
599 | |||
555 | static struct attribute *adis16400_attributes[] = { | 600 | static struct attribute *adis16400_attributes[] = { |
556 | &iio_dev_attr_gyro_x_calibbias.dev_attr.attr, | ||
557 | &iio_dev_attr_gyro_y_calibbias.dev_attr.attr, | ||
558 | &iio_dev_attr_gyro_z_calibbias.dev_attr.attr, | ||
559 | &iio_dev_attr_accel_x_calibbias.dev_attr.attr, | ||
560 | &iio_dev_attr_accel_y_calibbias.dev_attr.attr, | ||
561 | &iio_dev_attr_accel_z_calibbias.dev_attr.attr, | ||
562 | &iio_dev_attr_in0_supply_raw.dev_attr.attr, | ||
563 | &iio_const_attr_in0_supply_scale.dev_attr.attr, | ||
564 | &iio_dev_attr_gyro_x_raw.dev_attr.attr, | ||
565 | &iio_dev_attr_gyro_y_raw.dev_attr.attr, | ||
566 | &iio_dev_attr_gyro_z_raw.dev_attr.attr, | ||
567 | &iio_const_attr_gyro_scale.dev_attr.attr, | ||
568 | &iio_dev_attr_accel_x_raw.dev_attr.attr, | ||
569 | &iio_dev_attr_accel_y_raw.dev_attr.attr, | ||
570 | &iio_dev_attr_accel_z_raw.dev_attr.attr, | ||
571 | &iio_const_attr_accel_scale.dev_attr.attr, | ||
572 | &iio_dev_attr_magn_x_raw.dev_attr.attr, | ||
573 | &iio_dev_attr_magn_y_raw.dev_attr.attr, | ||
574 | &iio_dev_attr_magn_z_raw.dev_attr.attr, | ||
575 | &iio_const_attr_magn_scale.dev_attr.attr, | ||
576 | &iio_dev_attr_temp_raw.dev_attr.attr, | ||
577 | &iio_const_attr_temp_offset.dev_attr.attr, | ||
578 | &iio_const_attr_temp_scale.dev_attr.attr, | ||
579 | &iio_dev_attr_in1_raw.dev_attr.attr, | ||
580 | &iio_const_attr_in1_scale.dev_attr.attr, | ||
581 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | 601 | &iio_dev_attr_sampling_frequency.dev_attr.attr, |
582 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 602 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
583 | &iio_dev_attr_reset.dev_attr.attr, | 603 | &iio_dev_attr_reset.dev_attr.attr, |
@@ -622,6 +642,10 @@ static int __devinit adis16400_probe(struct spi_device *spi) | |||
622 | 642 | ||
623 | st->indio_dev->dev.parent = &spi->dev; | 643 | st->indio_dev->dev.parent = &spi->dev; |
624 | st->indio_dev->attrs = &adis16400_attribute_group; | 644 | st->indio_dev->attrs = &adis16400_attribute_group; |
645 | st->indio_dev->channels = adis16400_channels; | ||
646 | st->indio_dev->num_channels = ARRAY_SIZE(adis16400_channels); | ||
647 | st->indio_dev->read_raw = &adis16400_read_raw; | ||
648 | st->indio_dev->write_raw = &adis16400_write_raw; | ||
625 | st->indio_dev->dev_data = (void *)(st); | 649 | st->indio_dev->dev_data = (void *)(st); |
626 | st->indio_dev->driver_module = THIS_MODULE; | 650 | st->indio_dev->driver_module = THIS_MODULE; |
627 | st->indio_dev->modes = INDIO_DIRECT_MODE; | 651 | st->indio_dev->modes = INDIO_DIRECT_MODE; |
@@ -682,12 +706,10 @@ static int adis16400_remove(struct spi_device *spi) | |||
682 | struct adis16400_state *st = spi_get_drvdata(spi); | 706 | struct adis16400_state *st = spi_get_drvdata(spi); |
683 | struct iio_dev *indio_dev = st->indio_dev; | 707 | struct iio_dev *indio_dev = st->indio_dev; |
684 | 708 | ||
685 | ret = adis16400_stop_device(&(indio_dev->dev)); | 709 | ret = adis16400_stop_device(indio_dev); |
686 | if (ret) | 710 | if (ret) |
687 | goto err_ret; | 711 | goto err_ret; |
688 | 712 | ||
689 | flush_scheduled_work(); | ||
690 | |||
691 | adis16400_remove_trigger(indio_dev); | 713 | adis16400_remove_trigger(indio_dev); |
692 | iio_ring_buffer_unregister(st->indio_dev->ring); | 714 | iio_ring_buffer_unregister(st->indio_dev->ring); |
693 | adis16400_unconfigure_ring(indio_dev); | 715 | adis16400_unconfigure_ring(indio_dev); |