iio: mma8452: Add support for transient event debouncing
Allow the debouce counter for transient events to be configured
using the sysfs attribute events/in_accel_thresh_rising_period
Signed-off-by: Martin Fuzzey <mfuzzey@parkeon.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index f30eb9b..7429df3 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -38,6 +38,7 @@
#define MMA8452_TRANSIENT_SRC_ZTRANSE BIT(5)
#define MMA8452_TRANSIENT_THS 0x1f
#define MMA8452_TRANSIENT_THS_MASK 0x7f
+#define MMA8452_TRANSIENT_COUNT 0x20
#define MMA8452_OFF_X 0x2f
#define MMA8452_OFF_Y 0x30
#define MMA8452_OFF_Z 0x31
@@ -124,6 +125,12 @@
return -EINVAL;
}
+static int mma8452_get_odr_index(struct mma8452_data *data)
+{
+ return (data->ctrl_reg1 & MMA8452_CTRL_DR_MASK) >>
+ MMA8452_CTRL_DR_SHIFT;
+}
+
static const int mma8452_samp_freq[8][2] = {
{800, 0}, {400, 0}, {200, 0}, {100, 0}, {50, 0}, {12, 500000},
{6, 250000}, {1, 560000}
@@ -139,6 +146,18 @@
{0, 9577}, {0, 19154}, {0, 38307}
};
+/* Datasheet table 35 (step time vs sample frequency) */
+static const int mma8452_transient_time_step_us[8] = {
+ 1250,
+ 2500,
+ 5000,
+ 10000,
+ 20000,
+ 20000,
+ 20000,
+ 20000
+};
+
static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -198,8 +217,7 @@
*val2 = mma8452_scales[i][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
- i = (data->ctrl_reg1 & MMA8452_CTRL_DR_MASK) >>
- MMA8452_CTRL_DR_SHIFT;
+ i = mma8452_get_odr_index(data);
*val = mma8452_samp_freq[i][0];
*val2 = mma8452_samp_freq[i][1];
return IIO_VAL_INT_PLUS_MICRO;
@@ -297,15 +315,33 @@
int *val, int *val2)
{
struct mma8452_data *data = iio_priv(indio_dev);
- int ret;
+ int ret, us;
- ret = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_THS);
- if (ret < 0)
- return ret;
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ ret = i2c_smbus_read_byte_data(data->client,
+ MMA8452_TRANSIENT_THS);
+ if (ret < 0)
+ return ret;
- *val = ret & MMA8452_TRANSIENT_THS_MASK;
+ *val = ret & MMA8452_TRANSIENT_THS_MASK;
+ return IIO_VAL_INT;
- return IIO_VAL_INT;
+ case IIO_EV_INFO_PERIOD:
+ ret = i2c_smbus_read_byte_data(data->client,
+ MMA8452_TRANSIENT_COUNT);
+ if (ret < 0)
+ return ret;
+
+ us = ret * mma8452_transient_time_step_us[
+ mma8452_get_odr_index(data)];
+ *val = us / USEC_PER_SEC;
+ *val2 = us % USEC_PER_SEC;
+ return IIO_VAL_INT_PLUS_MICRO;
+
+ default:
+ return -EINVAL;
+ }
}
static int mma8452_write_thresh(struct iio_dev *indio_dev,
@@ -316,9 +352,26 @@
int val, int val2)
{
struct mma8452_data *data = iio_priv(indio_dev);
+ int steps;
- return mma8452_change_config(data, MMA8452_TRANSIENT_THS,
- val & MMA8452_TRANSIENT_THS_MASK);
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ return mma8452_change_config(data, MMA8452_TRANSIENT_THS,
+ val & MMA8452_TRANSIENT_THS_MASK);
+
+ case IIO_EV_INFO_PERIOD:
+ steps = (val * USEC_PER_SEC + val2) /
+ mma8452_transient_time_step_us[
+ mma8452_get_odr_index(data)];
+
+ if (steps > 0xff)
+ return -EINVAL;
+
+ return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
+ steps);
+ default:
+ return -EINVAL;
+ }
}
static int mma8452_read_event_config(struct iio_dev *indio_dev,
@@ -456,7 +509,8 @@
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE)
+ .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_PERIOD)
},
};