iio: accel: bma400: Add separate channel for step counter
authorJagath Jog J <jagathjog1996@gmail.com>
Thu, 5 May 2022 13:30:16 +0000 (19:00 +0530)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 11 Jun 2022 13:35:26 +0000 (14:35 +0100)
Added channel for step counter which can be enable or disable
through the sysfs interface.

Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
Link: https://lore.kernel.org/r/20220505133021.22362-6-jagathjog1996@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/accel/bma400.h
drivers/iio/accel/bma400_core.c

index 907e1a6..32c08f8 100644 (file)
@@ -53,6 +53,8 @@
 #define BMA400_STEP_CNT1_REG        0x16
 #define BMA400_STEP_CNT3_REG        0x17
 #define BMA400_STEP_STAT_REG        0x18
+#define BMA400_STEP_INT_MSK         BIT(0)
+#define BMA400_STEP_RAW_LEN         0x03
 
 /*
  * Read-write configuration registers
index 67e102c..d9402c6 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/mutex.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <asm/unaligned.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
@@ -74,6 +77,7 @@ struct bma400_data {
        int oversampling_ratio;
        int scale;
        struct iio_trigger *trig;
+       int steps_enabled;
        /* Correct time stamp alignment */
        struct {
                __le16 buff[3];
@@ -209,6 +213,12 @@ static const struct iio_chan_spec bma400_channels[] = {
                        .endianness = IIO_LE,
                },
        },
+       {
+               .type = IIO_STEPS,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+                                     BIT(IIO_CHAN_INFO_ENABLE),
+               .scan_index = -1, /* No buffer support */
+       },
        IIO_CHAN_SOFT_TIMESTAMP(4),
 };
 
@@ -577,6 +587,40 @@ static int bma400_set_power_mode(struct bma400_data *data,
        return 0;
 }
 
+static int bma400_enable_steps(struct bma400_data *data, int val)
+{
+       int ret;
+
+       if (data->steps_enabled == val)
+               return 0;
+
+       ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG1_REG,
+                                BMA400_STEP_INT_MSK,
+                                FIELD_PREP(BMA400_STEP_INT_MSK, val ? 1 : 0));
+       if (ret)
+               return ret;
+       data->steps_enabled = val;
+       return ret;
+}
+
+static int bma400_get_steps_reg(struct bma400_data *data, int *val)
+{
+       u8 *steps_raw;
+       int ret;
+
+       steps_raw = kmalloc(BMA400_STEP_RAW_LEN, GFP_KERNEL);
+       if (!steps_raw)
+               return -ENOMEM;
+
+       ret = regmap_bulk_read(data->regmap, BMA400_STEP_CNT0_REG,
+                              steps_raw, BMA400_STEP_RAW_LEN);
+       if (ret)
+               return ret;
+       *val = get_unaligned_le24(steps_raw);
+       kfree(steps_raw);
+       return IIO_VAL_INT;
+}
+
 static void bma400_init_tables(void)
 {
        int raw;
@@ -716,10 +760,17 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_PROCESSED:
-               mutex_lock(&data->mutex);
-               ret = bma400_get_temp_reg(data, val, val2);
-               mutex_unlock(&data->mutex);
-               return ret;
+               switch (chan->type) {
+               case IIO_TEMP:
+                       mutex_lock(&data->mutex);
+                       ret = bma400_get_temp_reg(data, val, val2);
+                       mutex_unlock(&data->mutex);
+                       return ret;
+               case IIO_STEPS:
+                       return bma400_get_steps_reg(data, val);
+               default:
+                       return -EINVAL;
+               }
        case IIO_CHAN_INFO_RAW:
                mutex_lock(&data->mutex);
                ret = bma400_get_accel_reg(data, chan, val);
@@ -760,6 +811,9 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
 
                *val = data->oversampling_ratio;
                return IIO_VAL_INT;
+       case IIO_CHAN_INFO_ENABLE:
+               *val = data->steps_enabled;
+               return IIO_VAL_INT;
        default:
                return -EINVAL;
        }
@@ -825,6 +879,11 @@ static int bma400_write_raw(struct iio_dev *indio_dev,
                ret = bma400_set_accel_oversampling_ratio(data, val);
                mutex_unlock(&data->mutex);
                return ret;
+       case IIO_CHAN_INFO_ENABLE:
+               mutex_lock(&data->mutex);
+               ret = bma400_enable_steps(data, val);
+               mutex_unlock(&data->mutex);
+               return ret;
        default:
                return -EINVAL;
        }
@@ -841,6 +900,8 @@ static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
                return IIO_VAL_INT;
+       case IIO_CHAN_INFO_ENABLE:
+               return IIO_VAL_INT;
        default:
                return -EINVAL;
        }