On Sun, 2015-03-08 at 11:22 +0000, Jonathan Cameron wrote: > On 03/03/15 16:17, Octavian Purdila wrote: > > Since both triggers and events can share an interrupt, add a data > > structure that tracks the users of an interrupt so that it enables or > > disables it only for the first users and respectively last user. > > > > This will allows us to easily add more events or triggers. > > > > The patch also adds an interrupt enabled counter, so that we can > > easily know if we need to put the device in normal mode when the > > resume callback is issued. > > > > Signed-off-by: Octavian Purdila <octavian.purdila@xxxxxxxxx> > As I stated before I'd like an Ack from Srinivas on this > (obviously Srinivas, if you've handed the driver maintenance over > to Octavian just let me know and I'll stop pestering you ;) Reviewed-by:: Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx> I prefer to test before Acks. Since Octavian is adding Fifo support and many changes, If Octavian wants he can take over the maintenance of this driver. Thanks, Srinivas > > Jonathan > > --- > > drivers/iio/accel/bmc150-accel.c | 86 ++++++++++++++++++++++++---------------- > > 1 file changed, 51 insertions(+), 35 deletions(-) > > > > diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c > > index 74ee54e..70497c3 100644 > > --- a/drivers/iio/accel/bmc150-accel.c > > +++ b/drivers/iio/accel/bmc150-accel.c > > @@ -147,10 +147,24 @@ struct bmc150_accel_chip_info { > > const struct bmc150_scale_info scale_table[4]; > > }; > > > > +struct bmc150_accel_interrupt { > > + const struct bmc150_accel_interrupt_info *info; > > + atomic_t users; > > +}; > > + > > +enum bmc150_accel_interrupt_id { > > + BMC150_ACCEL_INT_DATA_READY, > > + BMC150_ACCEL_INT_ANY_MOTION, > > + BMC150_ACCEL_INT_WATERMARK, > > + BMC150_ACCEL_INTERRUPTS, > > +}; > > + > > struct bmc150_accel_data { > > struct i2c_client *client; > > + struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; > > struct iio_trigger *dready_trig; > > struct iio_trigger *motion_trig; > > + atomic_t active_intr; > > struct mutex mutex; > > s16 buffer[8]; > > u8 bw_bits; > > @@ -421,7 +435,7 @@ static const struct bmc150_accel_interrupt_info { > > u8 map_bitmask; > > u8 en_reg; > > u8 en_bitmask; > > -} bmc150_accel_interrupts[] = { > > +} bmc150_accel_interrupts[BMC150_ACCEL_INTERRUPTS] = { > > { /* data ready interrupt */ > > .map_reg = BMC150_ACCEL_REG_INT_MAP_1, > > .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_DATA, > > @@ -438,12 +452,30 @@ static const struct bmc150_accel_interrupt_info { > > }, > > }; > > > > -static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, > > - const struct bmc150_accel_interrupt_info *info, > > +static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev, > > + struct bmc150_accel_data *data) > > +{ > > + int i; > > + > > + for (i = 0; i < BMC150_ACCEL_INTERRUPTS; i++) > > + data->interrupts[i].info = &bmc150_accel_interrupts[i]; > > +} > > + > > +static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i, > > bool state) > > { > > + struct bmc150_accel_interrupt *intr = &data->interrupts[i]; > > + const struct bmc150_accel_interrupt_info *info = intr->info; > > int ret; > > > > + if (state) { > > + if (atomic_inc_return(&intr->users) > 1) > > + return 0; > > + } else { > > + if (atomic_dec_return(&intr->users) > 0) > > + return 0; > > + } > > + > > /* > > * We will expect the enable and disable to do operation in > > * in reverse order. This will happen here anyway as our > > @@ -493,6 +525,11 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, > > goto out_fix_power_state; > > } > > > > + if (state) > > + atomic_inc(&data->active_intr); > > + else > > + atomic_dec(&data->active_intr); > > + > > return 0; > > > > out_fix_power_state: > > @@ -500,20 +537,6 @@ out_fix_power_state: > > return ret; > > } > > > > -static int bmc150_accel_setup_any_motion_interrupt( > > - struct bmc150_accel_data *data, > > - bool status) > > -{ > > - return bmc150_accel_set_interrupt(data, &bmc150_accel_interrupts[1], > > - status); > > -} > > - > > -static int bmc150_accel_setup_new_data_interrupt(struct bmc150_accel_data *data, > > - bool status) > > -{ > > - return bmc150_accel_set_interrupt(data, &bmc150_accel_interrupts[0], > > - status); > > -} > > > > static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val) > > { > > @@ -753,13 +776,8 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev, > > > > mutex_lock(&data->mutex); > > > > - if (!state && data->motion_trigger_on) { > > - data->ev_enable_state = 0; > > - mutex_unlock(&data->mutex); > > - return 0; > > - } > > - > > - ret = bmc150_accel_setup_any_motion_interrupt(data, state); > > + ret = bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_ANY_MOTION, > > + state); > > if (ret < 0) { > > mutex_unlock(&data->mutex); > > return ret; > > @@ -996,19 +1014,16 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig, > > } > > } > > > > - if (!state && data->ev_enable_state && data->motion_trigger_on) { > > - data->motion_trigger_on = false; > > - mutex_unlock(&data->mutex); > > - return 0; > > - } > > - > > if (data->motion_trig == trig) { > > ret = bmc150_accel_update_slope(data); > > if (!ret) > > - ret = bmc150_accel_setup_any_motion_interrupt(data, > > - state); > > + ret = bmc150_accel_set_interrupt(data, > > + BMC150_ACCEL_INT_ANY_MOTION, > > + state); > > } else { > > - ret = bmc150_accel_setup_new_data_interrupt(data, state); > > + ret = bmc150_accel_set_interrupt(data, > > + BMC150_ACCEL_INT_DATA_READY, > > + state); > > } > > if (ret < 0) { > > mutex_unlock(&data->mutex); > > @@ -1206,6 +1221,8 @@ static int bmc150_accel_probe(struct i2c_client *client, > > return ret; > > } > > > > + bmc150_accel_interrupts_setup(indio_dev, data); > > + > > data->dready_trig = devm_iio_trigger_alloc(&client->dev, > > "%s-dev%d", > > indio_dev->name, > > @@ -1321,8 +1338,7 @@ static int bmc150_accel_resume(struct device *dev) > > struct bmc150_accel_data *data = iio_priv(indio_dev); > > > > mutex_lock(&data->mutex); > > - if (data->dready_trigger_on || data->motion_trigger_on || > > - data->ev_enable_state) > > + if (atomic_read(&data->active_intr)) > > bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); > > mutex_unlock(&data->mutex); > > > > > -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html