iio: sx9310: Support setting debounce values
authorStephen Boyd <swboyd@chromium.org>
Wed, 7 Oct 2020 01:17:33 +0000 (18:17 -0700)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 10 Oct 2020 16:38:37 +0000 (17:38 +0100)
The rising and falling directions can be debounced in the hardware as
"close" and "far" debounce settings. Add support for these as rising and
falling debounce settings.

Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Cc: Daniel Campello <campello@chromium.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Gwendal Grignou <gwendal@chromium.org>
Cc: Evan Green <evgreen@chromium.org>
Link: https://lore.kernel.org/r/20201007011735.1346994-5-swboyd@chromium.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/proximity/sx9310.c

index 940c415..1809940 100644 (file)
@@ -77,6 +77,8 @@
 #define SX9310_REG_PROX_CTRL10                         0x1a
 #define   SX9310_REG_PROX_CTRL10_HYST_MASK             GENMASK(5, 4)
 #define   SX9310_REG_PROX_CTRL10_HYST_6PCT             (0x01 << 4)
+#define   SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK   GENMASK(3, 2)
+#define   SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK     GENMASK(1, 0)
 #define   SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_2                0x01
 #define SX9310_REG_PROX_CTRL11                         0x1b
 #define SX9310_REG_PROX_CTRL12                         0x1c
@@ -147,6 +149,16 @@ struct sx9310_data {
 };
 
 static const struct iio_event_spec sx9310_events[] = {
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_RISING,
+               .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD),
+       },
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_FALLING,
+               .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD),
+       },
        {
                .type = IIO_EV_TYPE_THRESH,
                .dir = IIO_EV_DIR_EITHER,
@@ -601,6 +613,42 @@ static int sx9310_read_hysteresis(struct sx9310_data *data,
        return IIO_VAL_INT;
 }
 
+static int sx9310_read_far_debounce(struct sx9310_data *data, int *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, &regval);
+       if (ret)
+               return ret;
+
+       regval = FIELD_GET(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, regval);
+       if (regval)
+               *val = 1 << regval;
+       else
+               *val = 0;
+
+       return IIO_VAL_INT;
+}
+
+static int sx9310_read_close_debounce(struct sx9310_data *data, int *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, &regval);
+       if (ret)
+               return ret;
+
+       regval = FIELD_GET(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, regval);
+       if (regval)
+               *val = 1 << regval;
+       else
+               *val = 0;
+
+       return IIO_VAL_INT;
+}
+
 static int sx9310_read_event_val(struct iio_dev *indio_dev,
                                 const struct iio_chan_spec *chan,
                                 enum iio_event_type type,
@@ -615,6 +663,15 @@ static int sx9310_read_event_val(struct iio_dev *indio_dev,
        switch (info) {
        case IIO_EV_INFO_VALUE:
                return sx9310_read_thresh(data, chan, val);
+       case IIO_EV_INFO_PERIOD:
+               switch (dir) {
+               case IIO_EV_DIR_RISING:
+                       return sx9310_read_far_debounce(data, val);
+               case IIO_EV_DIR_FALLING:
+                       return sx9310_read_close_debounce(data, val);
+               default:
+                       return -EINVAL;
+               }
        case IIO_EV_INFO_HYSTERESIS:
                return sx9310_read_hysteresis(data, chan, val);
        default:
@@ -682,6 +739,40 @@ static int sx9310_write_hysteresis(struct sx9310_data *data,
        return ret;
 }
 
+static int sx9310_write_far_debounce(struct sx9310_data *data, int val)
+{
+       int ret;
+       unsigned int regval;
+
+       val = ilog2(val);
+       regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val);
+
+       mutex_lock(&data->mutex);
+       ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
+                                SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK,
+                                regval);
+       mutex_unlock(&data->mutex);
+
+       return ret;
+}
+
+static int sx9310_write_close_debounce(struct sx9310_data *data, int val)
+{
+       int ret;
+       unsigned int regval;
+
+       val = ilog2(val);
+       regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val);
+
+       mutex_lock(&data->mutex);
+       ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
+                                SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK,
+                                regval);
+       mutex_unlock(&data->mutex);
+
+       return ret;
+}
+
 static int sx9310_write_event_val(struct iio_dev *indio_dev,
                                  const struct iio_chan_spec *chan,
                                  enum iio_event_type type,
@@ -696,6 +787,15 @@ static int sx9310_write_event_val(struct iio_dev *indio_dev,
        switch (info) {
        case IIO_EV_INFO_VALUE:
                return sx9310_write_thresh(data, chan, val);
+       case IIO_EV_INFO_PERIOD:
+               switch (dir) {
+               case IIO_EV_DIR_RISING:
+                       return sx9310_write_far_debounce(data, val);
+               case IIO_EV_DIR_FALLING:
+                       return sx9310_write_close_debounce(data, val);
+               default:
+                       return -EINVAL;
+               }
        case IIO_EV_INFO_HYSTERESIS:
                return sx9310_write_hysteresis(data, chan, val);
        default: