From: Jonathan Cameron <jic23@kernel.org>
To: Octavian Purdila <octavian.purdila@intel.com>, linux-iio@vger.kernel.org
Subject: Re: [PATCH v2 08/11] iio: bmc150: introduce bmc150_accel_interrupt
Date: Sun, 04 Jan 2015 16:36:04 +0000 [thread overview]
Message-ID: <54A96BF4.303@kernel.org> (raw)
In-Reply-To: <1419122556-8100-9-git-send-email-octavian.purdila@intel.com>
On 21/12/14 00:42, 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@intel.com>
This is probably the cleanest way of doing this, but an alternative is
to register an interrupt chip and then you can have each interrupt source
(internal to the device) have it's own interrupt and register as if
it had direct access (rather than having to read what interrupt occured
first). This is the preferred method these days for MFDs where this
tree structure of interrupts is common.
I think that would result in slightly more code though, so perhaps this
local version of some of that infrastructure is fine.
Jonathan
> ---
> drivers/iio/accel/bmc150-accel.c | 87 +++++++++++++++++++++-------------------
> 1 file changed, 45 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index aaad2fb..7c905f6 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -151,10 +151,19 @@ struct bmc150_accel_interrupt_info {
> u8 en_bitmask;
> };
>
> +struct bmc150_accel_interrupt {
> + struct bmc150_accel_interrupt_info *info;
> + atomic_t users;
> +};
> +
> +#define BMC150_ACCEL_INTERRUPTS 2
> +
> 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;
> @@ -436,7 +445,8 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
> }
> #endif
>
> -static struct bmc150_accel_interrupt_info bmc150_accel_interrupts[] = {
> +static struct bmc150_accel_interrupt_info
Just noticed. Should this not also be const?
> +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,
> @@ -453,12 +463,30 @@ static struct bmc150_accel_interrupt_info bmc150_accel_interrupts[] = {
> },
> };
>
> +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,
> - struct bmc150_accel_interrupt_info *info,
> + struct bmc150_accel_interrupt *intr,
> bool state)
> {
> + 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
> @@ -509,22 +537,12 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data,
> return ret;
> }
>
> - return 0;
> -}
> -
> -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);
> -}
> + if (state)
> + atomic_inc(&data->active_intr);
> + else
> + atomic_dec(&data->active_intr);
>
> -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);
> + return 0;
> }
>
> static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
> @@ -769,23 +787,12 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
> return 0;
>
> 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);
> - if (ret < 0) {
> - mutex_unlock(&data->mutex);
> - return ret;
> - }
> -
> - data->ev_enable_state = state;
> + ret = bmc150_accel_set_interrupt(data, &data->interrupts[1], state);
> + if (!ret)
> + data->ev_enable_state = state;
> mutex_unlock(&data->mutex);
>
> - return 0;
> + return ret;
> }
>
> static int bmc150_accel_validate_trigger(struct iio_dev *indio_dev,
> @@ -1013,16 +1020,12 @@ 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_setup_any_motion_interrupt(data, state);
> + ret = bmc150_accel_set_interrupt(data, &data->interrupts[1],
> + state);
> else
> - ret = bmc150_accel_setup_new_data_interrupt(data, state);
> + ret = bmc150_accel_set_interrupt(data, &data->interrupts[0],
> + state);
> if (ret < 0) {
> mutex_unlock(&data->mutex);
> return ret;
> @@ -1209,6 +1212,7 @@ 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",
> @@ -1325,8 +1329,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);
>
>
next prev parent reply other threads:[~2015-01-04 16:36 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-21 0:42 [PATCH v2 00/11] iio: add support for hardware buffers Octavian Purdila
2014-12-21 0:42 ` [PATCH v2 01/11] iio: buffer: fix custom buffer attributes copy Octavian Purdila
2015-01-04 11:25 ` Jonathan Cameron
2015-01-04 11:34 ` Lars-Peter Clausen
2015-01-04 16:11 ` Jonathan Cameron
2014-12-21 0:42 ` [PATCH v2 02/11] iio: buffer: refactor buffer attributes setup Octavian Purdila
2015-01-04 11:31 ` Jonathan Cameron
2015-01-05 10:48 ` Octavian Purdila
2014-12-21 0:42 ` [PATCH v2 03/11] iio: add watermark logic to iio read and poll Octavian Purdila
2015-01-04 15:44 ` Jonathan Cameron
2015-01-25 21:22 ` Hartmut Knaack
2015-01-26 9:40 ` Octavian Purdila
2014-12-21 0:42 ` [PATCH v2 04/11] iio: add support for hardware fifo Octavian Purdila
2015-01-04 16:07 ` Jonathan Cameron
2015-01-05 11:29 ` Octavian Purdila
2015-02-04 17:08 ` Jonathan Cameron
2015-02-05 21:36 ` Octavian Purdila
2015-02-08 10:53 ` Jonathan Cameron
2015-02-09 13:44 ` Octavian Purdila
2015-01-28 23:46 ` Hartmut Knaack
2015-01-29 11:38 ` Octavian Purdila
2015-01-29 22:49 ` Hartmut Knaack
2015-02-04 17:18 ` Jonathan Cameron
2015-02-04 17:11 ` Jonathan Cameron
2014-12-21 0:42 ` [PATCH v2 05/11] iio: bmc150: refactor slope duration and threshold update Octavian Purdila
2015-01-04 16:21 ` Jonathan Cameron
2015-01-06 18:53 ` Srinivas Pandruvada
2015-01-28 9:22 ` Octavian Purdila
2015-01-28 17:15 ` Srinivas Pandruvada
2014-12-21 0:42 ` [PATCH v2 06/11] iio: bmc150: refactor interrupt enabling Octavian Purdila
2015-01-04 16:27 ` Jonathan Cameron
2015-01-28 10:33 ` Octavian Purdila
2014-12-21 0:42 ` [PATCH v2 07/11] iio: bmc150: exit early if event / trigger state is not changed Octavian Purdila
2015-01-04 16:29 ` Jonathan Cameron
2014-12-21 0:42 ` [PATCH v2 08/11] iio: bmc150: introduce bmc150_accel_interrupt Octavian Purdila
2015-01-04 16:36 ` Jonathan Cameron [this message]
2015-01-28 11:09 ` Octavian Purdila
2015-01-28 13:20 ` Jonathan Cameron
2014-12-21 0:42 ` [PATCH v2 09/11] iio: bmc150: introduce bmc150_accel_trigger Octavian Purdila
2015-01-04 16:39 ` Jonathan Cameron
2014-12-21 0:42 ` [PATCH v2 10/11] iio: bmc150: introduce bmc150_accel_event Octavian Purdila
2015-01-04 16:49 ` Jonathan Cameron
2014-12-21 0:42 ` [PATCH v2 11/11] iio: bmc150: add support for hardware fifo Octavian Purdila
2015-01-04 17:08 ` Jonathan Cameron
2015-01-28 19:26 ` Octavian Purdila
2015-02-04 17:16 ` Jonathan Cameron
2015-02-04 20:18 ` Octavian Purdila
2015-02-05 11:20 ` Jonathan Cameron
2015-02-05 20:04 ` Octavian Purdila
2015-02-06 12:19 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54A96BF4.303@kernel.org \
--to=jic23@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=octavian.purdila@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).