iio:bma180: Expose temperature channel
authorPeter Meerwald <pmeerw@pmeerw.net>
Tue, 19 Aug 2014 22:43:00 +0000 (23:43 +0100)
committerJonathan Cameron <jic23@kernel.org>
Sun, 14 Sep 2014 17:48:39 +0000 (18:48 +0100)
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>
drivers/iio/accel/bma180.c

index aa7566fc031fb416213ccd1f64346f79cc552ef7..91260a071fe96067e095b643a2f96dbe95c30354 100644 (file)
@@ -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);