|
@@ -29,6 +29,7 @@
|
|
|
/* Register set */
|
|
|
#define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */
|
|
|
#define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */
|
|
|
+#define BMA180_TEMP 0x08
|
|
|
#define BMA180_CTRL_REG0 0x0d
|
|
|
#define BMA180_RESET 0x10
|
|
|
#define BMA180_BW_TCS 0x20
|
|
@@ -84,27 +85,37 @@ struct bma180_data {
|
|
|
char *buff;
|
|
|
};
|
|
|
|
|
|
-enum bma180_axis {
|
|
|
+enum bma180_chan {
|
|
|
AXIS_X,
|
|
|
AXIS_Y,
|
|
|
AXIS_Z,
|
|
|
+ TEMP
|
|
|
};
|
|
|
|
|
|
static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */
|
|
|
static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 };
|
|
|
|
|
|
-static int bma180_get_acc_reg(struct bma180_data *data, enum bma180_axis axis)
|
|
|
+static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan)
|
|
|
{
|
|
|
- u8 reg = BMA180_ACC_X_LSB + axis * 2;
|
|
|
int ret;
|
|
|
|
|
|
if (data->sleep_state)
|
|
|
return -EBUSY;
|
|
|
|
|
|
- ret = i2c_smbus_read_word_data(data->client, reg);
|
|
|
- if (ret < 0)
|
|
|
- dev_err(&data->client->dev,
|
|
|
- "failed to read accel_%c register\n", 'x' + axis);
|
|
|
+ switch (chan) {
|
|
|
+ case TEMP:
|
|
|
+ ret = i2c_smbus_read_byte_data(data->client, BMA180_TEMP);
|
|
|
+ if (ret < 0)
|
|
|
+ dev_err(&data->client->dev, "failed to read temp register\n");
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ret = i2c_smbus_read_word_data(data->client,
|
|
|
+ BMA180_ACC_X_LSB + chan * 2);
|
|
|
+ if (ret < 0)
|
|
|
+ dev_err(&data->client->dev,
|
|
|
+ "failed to read accel_%c register\n",
|
|
|
+ 'x' + chan);
|
|
|
+ }
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -337,22 +348,35 @@ static int bma180_read_raw(struct iio_dev *indio_dev,
|
|
|
switch (mask) {
|
|
|
case IIO_CHAN_INFO_RAW:
|
|
|
mutex_lock(&data->mutex);
|
|
|
- if (iio_buffer_enabled(indio_dev))
|
|
|
- ret = -EBUSY;
|
|
|
- else
|
|
|
- ret = bma180_get_acc_reg(data, chan->scan_index);
|
|
|
+ if (iio_buffer_enabled(indio_dev)) {
|
|
|
+ mutex_unlock(&data->mutex);
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+ ret = bma180_get_data_reg(data, chan->scan_index);
|
|
|
mutex_unlock(&data->mutex);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
- *val = (s16)ret >> chan->scan_type.shift;
|
|
|
+ *val = sign_extend32(ret >> chan->scan_type.shift,
|
|
|
+ chan->scan_type.realbits - 1);
|
|
|
return IIO_VAL_INT;
|
|
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
|
|
*val = data->bw;
|
|
|
return IIO_VAL_INT;
|
|
|
case IIO_CHAN_INFO_SCALE:
|
|
|
- *val = 0;
|
|
|
- *val2 = data->scale;
|
|
|
- return IIO_VAL_INT_PLUS_MICRO;
|
|
|
+ switch (chan->type) {
|
|
|
+ case IIO_ACCEL:
|
|
|
+ *val = 0;
|
|
|
+ *val2 = data->scale;
|
|
|
+ return IIO_VAL_INT_PLUS_MICRO;
|
|
|
+ case IIO_TEMP:
|
|
|
+ *val = 500;
|
|
|
+ return IIO_VAL_INT;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ case IIO_CHAN_INFO_OFFSET:
|
|
|
+ *val = 48; /* 0 LSB @ 24 degree C */
|
|
|
+ return IIO_VAL_INT;
|
|
|
default:
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -443,7 +467,7 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
|
|
|
{ },
|
|
|
};
|
|
|
|
|
|
-#define BMA180_CHANNEL(_axis) { \
|
|
|
+#define BMA180_ACC_CHANNEL(_axis) { \
|
|
|
.type = IIO_ACCEL, \
|
|
|
.modified = 1, \
|
|
|
.channel2 = IIO_MOD_##_axis, \
|
|
@@ -460,11 +484,24 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
|
|
|
.ext_info = bma180_ext_info, \
|
|
|
}
|
|
|
|
|
|
+#define BMA180_TEMP_CHANNEL { \
|
|
|
+ .type = IIO_TEMP, \
|
|
|
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
|
|
+ BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), \
|
|
|
+ .scan_index = TEMP, \
|
|
|
+ .scan_type = { \
|
|
|
+ .sign = 's', \
|
|
|
+ .realbits = 8, \
|
|
|
+ .storagebits = 16, \
|
|
|
+ }, \
|
|
|
+}
|
|
|
+
|
|
|
static const struct iio_chan_spec bma180_channels[] = {
|
|
|
- BMA180_CHANNEL(X),
|
|
|
- BMA180_CHANNEL(Y),
|
|
|
- BMA180_CHANNEL(Z),
|
|
|
- IIO_CHAN_SOFT_TIMESTAMP(3),
|
|
|
+ BMA180_ACC_CHANNEL(X),
|
|
|
+ BMA180_ACC_CHANNEL(Y),
|
|
|
+ BMA180_ACC_CHANNEL(Z),
|
|
|
+ BMA180_TEMP_CHANNEL,
|
|
|
+ IIO_CHAN_SOFT_TIMESTAMP(4),
|
|
|
};
|
|
|
|
|
|
static irqreturn_t bma180_trigger_handler(int irq, void *p)
|
|
@@ -479,13 +516,14 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p)
|
|
|
|
|
|
for_each_set_bit(bit, indio_dev->buffer->scan_mask,
|
|
|
indio_dev->masklength) {
|
|
|
- ret = bma180_get_acc_reg(data, bit);
|
|
|
+ ret = bma180_get_data_reg(data, bit);
|
|
|
if (ret < 0) {
|
|
|
mutex_unlock(&data->mutex);
|
|
|
goto err;
|
|
|
}
|
|
|
((s16 *)data->buff)[i++] = ret;
|
|
|
}
|
|
|
+
|
|
|
mutex_unlock(&data->mutex);
|
|
|
|
|
|
iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns);
|