Skip to content

Commit 3e825ec

Browse files
Octavian Purdilajic23
authored andcommitted
iio: bmc150: introduce bmc150_accel_interrupt
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 <[email protected]> Reviewed-by: Srinivas Pandruvada <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 1fad034 commit 3e825ec

File tree

1 file changed

+51
-35
lines changed

1 file changed

+51
-35
lines changed

drivers/iio/accel/bmc150-accel.c

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,24 @@ struct bmc150_accel_chip_info {
147147
const struct bmc150_scale_info scale_table[4];
148148
};
149149

150+
struct bmc150_accel_interrupt {
151+
const struct bmc150_accel_interrupt_info *info;
152+
atomic_t users;
153+
};
154+
155+
enum bmc150_accel_interrupt_id {
156+
BMC150_ACCEL_INT_DATA_READY,
157+
BMC150_ACCEL_INT_ANY_MOTION,
158+
BMC150_ACCEL_INT_WATERMARK,
159+
BMC150_ACCEL_INTERRUPTS,
160+
};
161+
150162
struct bmc150_accel_data {
151163
struct i2c_client *client;
164+
struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
152165
struct iio_trigger *dready_trig;
153166
struct iio_trigger *motion_trig;
167+
atomic_t active_intr;
154168
struct mutex mutex;
155169
s16 buffer[8];
156170
u8 bw_bits;
@@ -421,7 +435,7 @@ static const struct bmc150_accel_interrupt_info {
421435
u8 map_bitmask;
422436
u8 en_reg;
423437
u8 en_bitmask;
424-
} bmc150_accel_interrupts[] = {
438+
} bmc150_accel_interrupts[BMC150_ACCEL_INTERRUPTS] = {
425439
{ /* data ready interrupt */
426440
.map_reg = BMC150_ACCEL_REG_INT_MAP_1,
427441
.map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_DATA,
@@ -438,12 +452,30 @@ static const struct bmc150_accel_interrupt_info {
438452
},
439453
};
440454

441-
static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data,
442-
const struct bmc150_accel_interrupt_info *info,
455+
static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev,
456+
struct bmc150_accel_data *data)
457+
{
458+
int i;
459+
460+
for (i = 0; i < BMC150_ACCEL_INTERRUPTS; i++)
461+
data->interrupts[i].info = &bmc150_accel_interrupts[i];
462+
}
463+
464+
static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
443465
bool state)
444466
{
467+
struct bmc150_accel_interrupt *intr = &data->interrupts[i];
468+
const struct bmc150_accel_interrupt_info *info = intr->info;
445469
int ret;
446470

471+
if (state) {
472+
if (atomic_inc_return(&intr->users) > 1)
473+
return 0;
474+
} else {
475+
if (atomic_dec_return(&intr->users) > 0)
476+
return 0;
477+
}
478+
447479
/*
448480
* We will expect the enable and disable to do operation in
449481
* in reverse order. This will happen here anyway as our
@@ -493,27 +525,18 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data,
493525
goto out_fix_power_state;
494526
}
495527

528+
if (state)
529+
atomic_inc(&data->active_intr);
530+
else
531+
atomic_dec(&data->active_intr);
532+
496533
return 0;
497534

498535
out_fix_power_state:
499536
bmc150_accel_set_power_state(data, false);
500537
return ret;
501538
}
502539

503-
static int bmc150_accel_setup_any_motion_interrupt(
504-
struct bmc150_accel_data *data,
505-
bool status)
506-
{
507-
return bmc150_accel_set_interrupt(data, &bmc150_accel_interrupts[1],
508-
status);
509-
}
510-
511-
static int bmc150_accel_setup_new_data_interrupt(struct bmc150_accel_data *data,
512-
bool status)
513-
{
514-
return bmc150_accel_set_interrupt(data, &bmc150_accel_interrupts[0],
515-
status);
516-
}
517540

518541
static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
519542
{
@@ -753,13 +776,8 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
753776

754777
mutex_lock(&data->mutex);
755778

756-
if (!state && data->motion_trigger_on) {
757-
data->ev_enable_state = 0;
758-
mutex_unlock(&data->mutex);
759-
return 0;
760-
}
761-
762-
ret = bmc150_accel_setup_any_motion_interrupt(data, state);
779+
ret = bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_ANY_MOTION,
780+
state);
763781
if (ret < 0) {
764782
mutex_unlock(&data->mutex);
765783
return ret;
@@ -996,19 +1014,16 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig,
9961014
}
9971015
}
9981016

999-
if (!state && data->ev_enable_state && data->motion_trigger_on) {
1000-
data->motion_trigger_on = false;
1001-
mutex_unlock(&data->mutex);
1002-
return 0;
1003-
}
1004-
10051017
if (data->motion_trig == trig) {
10061018
ret = bmc150_accel_update_slope(data);
10071019
if (!ret)
1008-
ret = bmc150_accel_setup_any_motion_interrupt(data,
1009-
state);
1020+
ret = bmc150_accel_set_interrupt(data,
1021+
BMC150_ACCEL_INT_ANY_MOTION,
1022+
state);
10101023
} else {
1011-
ret = bmc150_accel_setup_new_data_interrupt(data, state);
1024+
ret = bmc150_accel_set_interrupt(data,
1025+
BMC150_ACCEL_INT_DATA_READY,
1026+
state);
10121027
}
10131028
if (ret < 0) {
10141029
mutex_unlock(&data->mutex);
@@ -1206,6 +1221,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
12061221
return ret;
12071222
}
12081223

1224+
bmc150_accel_interrupts_setup(indio_dev, data);
1225+
12091226
data->dready_trig = devm_iio_trigger_alloc(&client->dev,
12101227
"%s-dev%d",
12111228
indio_dev->name,
@@ -1321,8 +1338,7 @@ static int bmc150_accel_resume(struct device *dev)
13211338
struct bmc150_accel_data *data = iio_priv(indio_dev);
13221339

13231340
mutex_lock(&data->mutex);
1324-
if (data->dready_trigger_on || data->motion_trigger_on ||
1325-
data->ev_enable_state)
1341+
if (atomic_read(&data->active_intr))
13261342
bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
13271343
mutex_unlock(&data->mutex);
13281344

0 commit comments

Comments
 (0)