> In preparation for adding support for more event types, use an array > indexed by event ID instead of a scalar value to store enabled events, and > refactor the functions to configure and report events so that their > implementation is not specific for wakeup events. Move the logic to update > the global event interrupt enable flag from st_lsm6dsx_event_setup() to its > calling function, so that it can take into account also event sources > different from the source being configured. While changing the signature of > the st_lsm6dsx_event_setup() function, opportunistically add the currently > unused `axis` parameter, which will be used when adding support for > enabling and disabling events on a per axis basis. Just some nits inline. Fixing them: Acked-by: Lorenzo Bianconi > > Signed-off-by: Francesco Lavra > --- > drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 +- > drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 149 ++++++++++++++----- > 2 files changed, 109 insertions(+), 42 deletions(-) > > diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h > index e727a87413e5..037b3b817e83 100644 > --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h > +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h > @@ -446,7 +446,7 @@ struct st_lsm6dsx_hw { > u8 sip; > > u8 irq_routing; > - u8 enable_event; > + u8 enable_event[ST_LSM6DSX_EVENT_MAX]; > > u8 *buff; > > diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c > index 117ecb080d8e..18a09ed6907c 100644 > --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c > +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c > @@ -1747,11 +1747,16 @@ static int > st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor) > { > struct st_lsm6dsx_hw *hw = sensor->hw; > + int event; > > if (sensor->id != ST_LSM6DSX_ID_ACC) > return 0; > > - return hw->enable_event; > + for (event = 0; event < ST_LSM6DSX_EVENT_MAX; event++) { > + if (hw->enable_event[event]) > + return true; > + } > + return false; > } > > int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor, > @@ -1864,9 +1869,10 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, > return err; > } > > -static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state) > +static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, > + enum st_lsm6dsx_event_id event, int axis, > + bool state) > { > - const struct st_lsm6dsx_reg *reg; > const struct st_lsm6dsx_event_src *src; > u8 enable_mask; > unsigned int data; > @@ -1875,22 +1881,24 @@ static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state) > if (!hw->irq_routing) > return -ENOTSUPP; > > - reg = &hw->settings->event_settings.enable_reg; > - if (reg->addr) { > - data = ST_LSM6DSX_SHIFT_VAL(state, reg->mask); > - err = st_lsm6dsx_update_bits_locked(hw, reg->addr, > - reg->mask, data); > - if (err < 0) > - return err; > - } > - > - /* Enable wakeup interrupt */ > - src = &hw->settings->event_settings.sources[ST_LSM6DSX_EVENT_WAKEUP]; > + /* Enable/disable event interrupt */ > + src = &hw->settings->event_settings.sources[event]; > enable_mask = src->enable_mask; > data = ST_LSM6DSX_SHIFT_VAL(state, enable_mask); > return st_lsm6dsx_update_bits_locked(hw, hw->irq_routing, enable_mask, data); > } > > +static enum st_lsm6dsx_event_id > +st_lsm6dsx_get_event_id(enum iio_event_type type) > +{ > + switch (type) { > + case IIO_EV_TYPE_THRESH: > + return ST_LSM6DSX_EVENT_WAKEUP; > + default: > + return ST_LSM6DSX_EVENT_MAX; > + } > +} > + > static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, > const struct iio_chan_spec *chan, > enum iio_event_type type, > @@ -1898,16 +1906,17 @@ static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, > enum iio_event_info info, > int *val, int *val2) > { > + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); > struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); > struct st_lsm6dsx_hw *hw = sensor->hw; > const struct st_lsm6dsx_reg *reg; > u8 data; > int err; > > - if (type != IIO_EV_TYPE_THRESH) > + if (event == ST_LSM6DSX_EVENT_MAX) > return -EINVAL; > > - reg = &hw->settings->event_settings.sources[ST_LSM6DSX_EVENT_WAKEUP].value; > + reg = &hw->settings->event_settings.sources[event].value; > err = st_lsm6dsx_read_locked(hw, reg->addr, &data, sizeof(data)); > if (err < 0) > return err; > @@ -1926,19 +1935,20 @@ st_lsm6dsx_write_event(struct iio_dev *iio_dev, > enum iio_event_info info, > int val, int val2) > { > + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); > struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); > struct st_lsm6dsx_hw *hw = sensor->hw; > const struct st_lsm6dsx_reg *reg; > unsigned int data; > int err; > > - if (type != IIO_EV_TYPE_THRESH) > + if (event == ST_LSM6DSX_EVENT_MAX) > return -EINVAL; > > if (val < 0 || val > 31) > return -EINVAL; > > - reg = &hw->settings->event_settings.sources[ST_LSM6DSX_EVENT_WAKEUP].value; > + reg = &hw->settings->event_settings.sources[event].value; > data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); > err = st_lsm6dsx_update_bits_locked(hw, reg->addr, > reg->mask, data); > @@ -1954,13 +1964,53 @@ st_lsm6dsx_read_event_config(struct iio_dev *iio_dev, > enum iio_event_type type, > enum iio_event_direction dir) > { > + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); > struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); > struct st_lsm6dsx_hw *hw = sensor->hw; > > - if (type != IIO_EV_TYPE_THRESH) > + if (event == ST_LSM6DSX_EVENT_MAX) > return -EINVAL; > > - return !!(hw->enable_event & BIT(chan->channel2)); > + return !!(hw->enable_event[event] & BIT(chan->channel2)); > +} > + > +/** > + * st_lsm6dsx_check_other_events - Check for enabled sensor events. > + * @hw: Sensor hardware instance. > + * @curr: Current event type. > + * > + * Return: whether any events other than @curr are enabled. > + */ > +static bool st_lsm6dsx_check_other_events(struct st_lsm6dsx_hw *hw, > + enum st_lsm6dsx_event_id curr) > +{ > + enum st_lsm6dsx_event_id other; > + > + for (other = 0; other < ST_LSM6DSX_EVENT_MAX; other++) { > + if (other != curr && hw->enable_event[other]) > + return true; > + } new line here > + return false; > +} > + > +static int st_lsm6dsx_events_enable(struct st_lsm6dsx_sensor *sensor, > + bool state) > +{ > + struct st_lsm6dsx_hw *hw = sensor->hw; > + const struct st_lsm6dsx_reg *reg; > + > + reg = &hw->settings->event_settings.enable_reg; > + if (reg->addr) { > + int err; > + > + err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, > + ST_LSM6DSX_SHIFT_VAL(state, reg->mask)); > + if (err) > + return err; > + } new line here > + if (state || !(hw->fifo_mask & BIT(sensor->id))) > + return __st_lsm6dsx_sensor_set_enable(sensor, state); new line here > + return 0; > } > > static int > @@ -1969,22 +2019,24 @@ st_lsm6dsx_write_event_config(struct iio_dev *iio_dev, > enum iio_event_type type, > enum iio_event_direction dir, bool state) > { > + enum st_lsm6dsx_event_id event = st_lsm6dsx_get_event_id(type); > struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); > struct st_lsm6dsx_hw *hw = sensor->hw; > + int axis = chan->channel2; I think you can drop axis here and just use chan->channel2 directly. > u8 enable_event; > int err; > > - if (type != IIO_EV_TYPE_THRESH) > + if (event == ST_LSM6DSX_EVENT_MAX) > return -EINVAL; > > if (state) { > - enable_event = hw->enable_event | BIT(chan->channel2); > + enable_event = hw->enable_event[event] | BIT(axis); > > /* do not enable events if they are already enabled */ > - if (hw->enable_event) > + if (hw->enable_event[event]) > goto out; > } else { > - enable_event = hw->enable_event & ~BIT(chan->channel2); > + enable_event = hw->enable_event[event] & ~BIT(axis); > > /* only turn off sensor if no events is enabled */ > if (enable_event) > @@ -1992,22 +2044,24 @@ st_lsm6dsx_write_event_config(struct iio_dev *iio_dev, > } > > /* stop here if no changes have been made */ > - if (hw->enable_event == enable_event) > + if (hw->enable_event[event] == enable_event) > return 0; > > - err = st_lsm6dsx_event_setup(hw, state); > + err = st_lsm6dsx_event_setup(hw, event, axis, state); > if (err < 0) > return err; > > mutex_lock(&hw->conf_lock); > - if (enable_event || !(hw->fifo_mask & BIT(sensor->id))) > - err = __st_lsm6dsx_sensor_set_enable(sensor, state); > + if (enable_event) > + err = st_lsm6dsx_events_enable(sensor, true); > + else if (!st_lsm6dsx_check_other_events(hw, event)) > + err = st_lsm6dsx_events_enable(sensor, false); > mutex_unlock(&hw->conf_lock); > if (err < 0) > return err; > > out: > - hw->enable_event = enable_event; > + hw->enable_event[event] = enable_event; > > return 0; > } > @@ -2418,18 +2472,20 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, > } > > static bool > -st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw) > +st_lsm6dsx_report_events(struct st_lsm6dsx_hw *hw, enum st_lsm6dsx_event_id id, > + enum iio_event_type type, enum iio_event_direction dir) > { > + u8 enable_event = hw->enable_event[id]; same here, can you just use hw->enable_event[id] directly? > const struct st_lsm6dsx_event_settings *event_settings; > const struct st_lsm6dsx_event_src *src; > int err, data; > s64 timestamp; > > - if (!hw->enable_event) > + if (!enable_event) > return false; > > event_settings = &hw->settings->event_settings; > - src = &event_settings->sources[ST_LSM6DSX_EVENT_WAKEUP]; > + src = &event_settings->sources[id]; > err = st_lsm6dsx_read_locked(hw, src->status_reg, > &data, sizeof(data)); > if (err < 0) > @@ -2437,38 +2493,49 @@ st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw) > > timestamp = iio_get_time_ns(hw->iio_devs[ST_LSM6DSX_ID_ACC]); > if ((data & src->status_z_mask) && > - (hw->enable_event & BIT(IIO_MOD_Z))) > + (enable_event & BIT(IIO_MOD_Z))) > iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], > IIO_MOD_EVENT_CODE(IIO_ACCEL, > 0, > IIO_MOD_Z, > - IIO_EV_TYPE_THRESH, > - IIO_EV_DIR_EITHER), > + type, > + dir), > timestamp); > > if ((data & src->status_y_mask) && > - (hw->enable_event & BIT(IIO_MOD_Y))) > + (enable_event & BIT(IIO_MOD_Y))) > iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], > IIO_MOD_EVENT_CODE(IIO_ACCEL, > 0, > IIO_MOD_Y, > - IIO_EV_TYPE_THRESH, > - IIO_EV_DIR_EITHER), > + type, > + dir), > timestamp); > > if ((data & src->status_x_mask) && > - (hw->enable_event & BIT(IIO_MOD_X))) > + (enable_event & BIT(IIO_MOD_X))) > iio_push_event(hw->iio_devs[ST_LSM6DSX_ID_ACC], > IIO_MOD_EVENT_CODE(IIO_ACCEL, > 0, > IIO_MOD_X, > - IIO_EV_TYPE_THRESH, > - IIO_EV_DIR_EITHER), > + type, > + dir), > timestamp); > > return data & src->status_mask; > } > > +static bool st_lsm6dsx_report_motion_event(struct st_lsm6dsx_hw *hw) > +{ > + bool events_found; > + > + events_found = st_lsm6dsx_report_events(hw, ST_LSM6DSX_EVENT_WAKEUP, > + IIO_EV_TYPE_THRESH, > + IIO_EV_DIR_EITHER); > + > + return events_found; > +} > + > static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) > { > struct st_lsm6dsx_hw *hw = private; > -- > 2.39.5 >