aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOctavian Purdila <octavian.purdila@intel.com>2015-03-03 11:17:57 -0500
committerJonathan Cameron <jic23@kernel.org>2015-03-14 14:56:04 -0400
commit3e825ec98d36c8c8073024c95853389a831902e5 (patch)
tree06c2d503f11a0eea8fd2ae7f90dc98dcf44f653d
parent1fad034c636cb57686f778d1c80513acbdaf8ec5 (diff)
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 <octavian.purdila@intel.com> Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/accel/bmc150-accel.c86
1 files changed, 51 insertions, 35 deletions
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 46ac9659e2aa..db95237888ae 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -147,10 +147,24 @@ struct bmc150_accel_chip_info {
147 const struct bmc150_scale_info scale_table[4]; 147 const struct bmc150_scale_info scale_table[4];
148}; 148};
149 149
150struct bmc150_accel_interrupt {
151 const struct bmc150_accel_interrupt_info *info;
152 atomic_t users;
153};
154
155enum 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
150struct bmc150_accel_data { 162struct bmc150_accel_data {
151 struct i2c_client *client; 163 struct i2c_client *client;
164 struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
152 struct iio_trigger *dready_trig; 165 struct iio_trigger *dready_trig;
153 struct iio_trigger *motion_trig; 166 struct iio_trigger *motion_trig;
167 atomic_t active_intr;
154 struct mutex mutex; 168 struct mutex mutex;
155 s16 buffer[8]; 169 s16 buffer[8];
156 u8 bw_bits; 170 u8 bw_bits;
@@ -421,7 +435,7 @@ static const struct bmc150_accel_interrupt_info {
421 u8 map_bitmask; 435 u8 map_bitmask;
422 u8 en_reg; 436 u8 en_reg;
423 u8 en_bitmask; 437 u8 en_bitmask;
424} bmc150_accel_interrupts[] = { 438} bmc150_accel_interrupts[BMC150_ACCEL_INTERRUPTS] = {
425 { /* data ready interrupt */ 439 { /* data ready interrupt */
426 .map_reg = BMC150_ACCEL_REG_INT_MAP_1, 440 .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
427 .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_DATA, 441 .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_DATA,
@@ -438,12 +452,30 @@ static const struct bmc150_accel_interrupt_info {
438 }, 452 },
439}; 453};
440 454
441static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, 455static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev,
442 const struct bmc150_accel_interrupt_info *info, 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
464static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
443 bool state) 465 bool state)
444{ 466{
467 struct bmc150_accel_interrupt *intr = &data->interrupts[i];
468 const struct bmc150_accel_interrupt_info *info = intr->info;
445 int ret; 469 int ret;
446 470
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
447 /* 479 /*
448 * We will expect the enable and disable to do operation in 480 * We will expect the enable and disable to do operation in
449 * in reverse order. This will happen here anyway as our 481 * 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,
493 goto out_fix_power_state; 525 goto out_fix_power_state;
494 } 526 }
495 527
528 if (state)
529 atomic_inc(&data->active_intr);
530 else
531 atomic_dec(&data->active_intr);
532
496 return 0; 533 return 0;
497 534
498out_fix_power_state: 535out_fix_power_state:
@@ -500,20 +537,6 @@ out_fix_power_state:
500 return ret; 537 return ret;
501} 538}
502 539
503static 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
511static 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}
517 540
518static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val) 541static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
519{ 542{
@@ -753,13 +776,8 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
753 776
754 mutex_lock(&data->mutex); 777 mutex_lock(&data->mutex);
755 778
756 if (!state && data->motion_trigger_on) { 779 ret = bmc150_accel_set_interrupt(data, BMC150_ACCEL_INT_ANY_MOTION,
757 data->ev_enable_state = 0; 780 state);
758 mutex_unlock(&data->mutex);
759 return 0;
760 }
761
762 ret = bmc150_accel_setup_any_motion_interrupt(data, state);
763 if (ret < 0) { 781 if (ret < 0) {
764 mutex_unlock(&data->mutex); 782 mutex_unlock(&data->mutex);
765 return ret; 783 return ret;
@@ -996,19 +1014,16 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig,
996 } 1014 }
997 } 1015 }
998 1016
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
1005 if (data->motion_trig == trig) { 1017 if (data->motion_trig == trig) {
1006 ret = bmc150_accel_update_slope(data); 1018 ret = bmc150_accel_update_slope(data);
1007 if (!ret) 1019 if (!ret)
1008 ret = bmc150_accel_setup_any_motion_interrupt(data, 1020 ret = bmc150_accel_set_interrupt(data,
1009 state); 1021 BMC150_ACCEL_INT_ANY_MOTION,
1022 state);
1010 } else { 1023 } 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);
1012 } 1027 }
1013 if (ret < 0) { 1028 if (ret < 0) {
1014 mutex_unlock(&data->mutex); 1029 mutex_unlock(&data->mutex);
@@ -1206,6 +1221,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
1206 return ret; 1221 return ret;
1207 } 1222 }
1208 1223
1224 bmc150_accel_interrupts_setup(indio_dev, data);
1225
1209 data->dready_trig = devm_iio_trigger_alloc(&client->dev, 1226 data->dready_trig = devm_iio_trigger_alloc(&client->dev,
1210 "%s-dev%d", 1227 "%s-dev%d",
1211 indio_dev->name, 1228 indio_dev->name,
@@ -1321,8 +1338,7 @@ static int bmc150_accel_resume(struct device *dev)
1321 struct bmc150_accel_data *data = iio_priv(indio_dev); 1338 struct bmc150_accel_data *data = iio_priv(indio_dev);
1322 1339
1323 mutex_lock(&data->mutex); 1340 mutex_lock(&data->mutex);
1324 if (data->dready_trigger_on || data->motion_trigger_on || 1341 if (atomic_read(&data->active_intr))
1325 data->ev_enable_state)
1326 bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); 1342 bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
1327 mutex_unlock(&data->mutex); 1343 mutex_unlock(&data->mutex);
1328 1344