diff options
author | Peter Meerwald <pmeerw@pmeerw.net> | 2014-08-19 18:43:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-09-14 13:48:39 -0400 |
commit | b81fbab7f567aaa12aba6532681b426f3e130e11 (patch) | |
tree | a4dfb5e8425bb845589fa66b781889202779f2d9 | |
parent | c7c69e8540895be5d09bf023f1b48db3cab7a78b (diff) |
iio:bma180: Expose temperature channel
8-bit signed; 0 LSB @ 24 °C, 0.5 °C per LSB
Signed-off-by: Peter Meerwald <pmeerw@pmeerw.net>
Cc: Oleksandr Kravchenko <o.v.kravchenko@globallogic.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | drivers/iio/accel/bma180.c | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index aa7566fc031f..91260a071fe9 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c | |||
@@ -29,6 +29,7 @@ | |||
29 | /* Register set */ | 29 | /* Register set */ |
30 | #define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */ | 30 | #define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */ |
31 | #define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */ | 31 | #define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */ |
32 | #define BMA180_TEMP 0x08 | ||
32 | #define BMA180_CTRL_REG0 0x0d | 33 | #define BMA180_CTRL_REG0 0x0d |
33 | #define BMA180_RESET 0x10 | 34 | #define BMA180_RESET 0x10 |
34 | #define BMA180_BW_TCS 0x20 | 35 | #define BMA180_BW_TCS 0x20 |
@@ -84,27 +85,37 @@ struct bma180_data { | |||
84 | char *buff; | 85 | char *buff; |
85 | }; | 86 | }; |
86 | 87 | ||
87 | enum bma180_axis { | 88 | enum bma180_chan { |
88 | AXIS_X, | 89 | AXIS_X, |
89 | AXIS_Y, | 90 | AXIS_Y, |
90 | AXIS_Z, | 91 | AXIS_Z, |
92 | TEMP | ||
91 | }; | 93 | }; |
92 | 94 | ||
93 | static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ | 95 | static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ |
94 | static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; | 96 | static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; |
95 | 97 | ||
96 | static int bma180_get_acc_reg(struct bma180_data *data, enum bma180_axis axis) | 98 | static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan) |
97 | { | 99 | { |
98 | u8 reg = BMA180_ACC_X_LSB + axis * 2; | ||
99 | int ret; | 100 | int ret; |
100 | 101 | ||
101 | if (data->sleep_state) | 102 | if (data->sleep_state) |
102 | return -EBUSY; | 103 | return -EBUSY; |
103 | 104 | ||
104 | ret = i2c_smbus_read_word_data(data->client, reg); | 105 | switch (chan) { |
105 | if (ret < 0) | 106 | case TEMP: |
106 | dev_err(&data->client->dev, | 107 | ret = i2c_smbus_read_byte_data(data->client, BMA180_TEMP); |
107 | "failed to read accel_%c register\n", 'x' + axis); | 108 | if (ret < 0) |
109 | dev_err(&data->client->dev, "failed to read temp register\n"); | ||
110 | break; | ||
111 | default: | ||
112 | ret = i2c_smbus_read_word_data(data->client, | ||
113 | BMA180_ACC_X_LSB + chan * 2); | ||
114 | if (ret < 0) | ||
115 | dev_err(&data->client->dev, | ||
116 | "failed to read accel_%c register\n", | ||
117 | 'x' + chan); | ||
118 | } | ||
108 | 119 | ||
109 | return ret; | 120 | return ret; |
110 | } | 121 | } |
@@ -337,22 +348,35 @@ static int bma180_read_raw(struct iio_dev *indio_dev, | |||
337 | switch (mask) { | 348 | switch (mask) { |
338 | case IIO_CHAN_INFO_RAW: | 349 | case IIO_CHAN_INFO_RAW: |
339 | mutex_lock(&data->mutex); | 350 | mutex_lock(&data->mutex); |
340 | if (iio_buffer_enabled(indio_dev)) | 351 | if (iio_buffer_enabled(indio_dev)) { |
341 | ret = -EBUSY; | 352 | mutex_unlock(&data->mutex); |
342 | else | 353 | return -EBUSY; |
343 | ret = bma180_get_acc_reg(data, chan->scan_index); | 354 | } |
355 | ret = bma180_get_data_reg(data, chan->scan_index); | ||
344 | mutex_unlock(&data->mutex); | 356 | mutex_unlock(&data->mutex); |
345 | if (ret < 0) | 357 | if (ret < 0) |
346 | return ret; | 358 | return ret; |
347 | *val = (s16)ret >> chan->scan_type.shift; | 359 | *val = sign_extend32(ret >> chan->scan_type.shift, |
360 | chan->scan_type.realbits - 1); | ||
348 | return IIO_VAL_INT; | 361 | return IIO_VAL_INT; |
349 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | 362 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
350 | *val = data->bw; | 363 | *val = data->bw; |
351 | return IIO_VAL_INT; | 364 | return IIO_VAL_INT; |
352 | case IIO_CHAN_INFO_SCALE: | 365 | case IIO_CHAN_INFO_SCALE: |
353 | *val = 0; | 366 | switch (chan->type) { |
354 | *val2 = data->scale; | 367 | case IIO_ACCEL: |
355 | return IIO_VAL_INT_PLUS_MICRO; | 368 | *val = 0; |
369 | *val2 = data->scale; | ||
370 | return IIO_VAL_INT_PLUS_MICRO; | ||
371 | case IIO_TEMP: | ||
372 | *val = 500; | ||
373 | return IIO_VAL_INT; | ||
374 | default: | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | case IIO_CHAN_INFO_OFFSET: | ||
378 | *val = 48; /* 0 LSB @ 24 degree C */ | ||
379 | return IIO_VAL_INT; | ||
356 | default: | 380 | default: |
357 | return -EINVAL; | 381 | return -EINVAL; |
358 | } | 382 | } |
@@ -443,7 +467,7 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = { | |||
443 | { }, | 467 | { }, |
444 | }; | 468 | }; |
445 | 469 | ||
446 | #define BMA180_CHANNEL(_axis) { \ | 470 | #define BMA180_ACC_CHANNEL(_axis) { \ |
447 | .type = IIO_ACCEL, \ | 471 | .type = IIO_ACCEL, \ |
448 | .modified = 1, \ | 472 | .modified = 1, \ |
449 | .channel2 = IIO_MOD_##_axis, \ | 473 | .channel2 = IIO_MOD_##_axis, \ |
@@ -460,11 +484,24 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = { | |||
460 | .ext_info = bma180_ext_info, \ | 484 | .ext_info = bma180_ext_info, \ |
461 | } | 485 | } |
462 | 486 | ||
487 | #define BMA180_TEMP_CHANNEL { \ | ||
488 | .type = IIO_TEMP, \ | ||
489 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
490 | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), \ | ||
491 | .scan_index = TEMP, \ | ||
492 | .scan_type = { \ | ||
493 | .sign = 's', \ | ||
494 | .realbits = 8, \ | ||
495 | .storagebits = 16, \ | ||
496 | }, \ | ||
497 | } | ||
498 | |||
463 | static const struct iio_chan_spec bma180_channels[] = { | 499 | static const struct iio_chan_spec bma180_channels[] = { |
464 | BMA180_CHANNEL(X), | 500 | BMA180_ACC_CHANNEL(X), |
465 | BMA180_CHANNEL(Y), | 501 | BMA180_ACC_CHANNEL(Y), |
466 | BMA180_CHANNEL(Z), | 502 | BMA180_ACC_CHANNEL(Z), |
467 | IIO_CHAN_SOFT_TIMESTAMP(3), | 503 | BMA180_TEMP_CHANNEL, |
504 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
468 | }; | 505 | }; |
469 | 506 | ||
470 | static irqreturn_t bma180_trigger_handler(int irq, void *p) | 507 | static irqreturn_t bma180_trigger_handler(int irq, void *p) |
@@ -479,13 +516,14 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p) | |||
479 | 516 | ||
480 | for_each_set_bit(bit, indio_dev->buffer->scan_mask, | 517 | for_each_set_bit(bit, indio_dev->buffer->scan_mask, |
481 | indio_dev->masklength) { | 518 | indio_dev->masklength) { |
482 | ret = bma180_get_acc_reg(data, bit); | 519 | ret = bma180_get_data_reg(data, bit); |
483 | if (ret < 0) { | 520 | if (ret < 0) { |
484 | mutex_unlock(&data->mutex); | 521 | mutex_unlock(&data->mutex); |
485 | goto err; | 522 | goto err; |
486 | } | 523 | } |
487 | ((s16 *)data->buff)[i++] = ret; | 524 | ((s16 *)data->buff)[i++] = ret; |
488 | } | 525 | } |
526 | |||
489 | mutex_unlock(&data->mutex); | 527 | mutex_unlock(&data->mutex); |
490 | 528 | ||
491 | iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns); | 529 | iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns); |