From: Octavian Purdila <octavian.purdila@intel.com>
To: linux-iio@vger.kernel.org
Cc: srinivas.pandruvada@intel.com,
Octavian Purdila <octavian.purdila@intel.com>
Subject: [RFC 3/8] iio: bmc150: refactor interrupt enabling
Date: Mon, 17 Nov 2014 19:56:01 +0200 [thread overview]
Message-ID: <1416246966-3083-4-git-send-email-octavian.purdila@intel.com> (raw)
In-Reply-To: <1416246966-3083-1-git-send-email-octavian.purdila@intel.com>
This patch combines the any motion and new data interrupts function
into a single, generic, interrupt enable function. On top of this, we
can later refactor triggers to make it easier to add new triggers.
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
drivers/iio/accel/bmc150-accel.c | 271 +++++++++++++++++----------------------
1 file changed, 115 insertions(+), 156 deletions(-)
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index 5bfb09d..ee4afc4 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -144,6 +144,13 @@ struct bmc150_accel_chip_info {
const struct bmc150_scale_info scale_table[4];
};
+struct bmc150_accel_interrupt_info {
+ u8 map_reg;
+ u8 map_bitmask;
+ u8 en_reg;
+ u8 en_bitmask;
+};
+
struct bmc150_accel_data {
struct i2c_client *client;
struct iio_trigger *dready_trig;
@@ -374,137 +381,6 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
return 0;
}
-static int bmc150_accel_setup_any_motion_interrupt(
- struct bmc150_accel_data *data,
- bool status)
-{
- int ret;
-
- /* Enable/Disable INT1 mapping */
- ret = i2c_smbus_read_byte_data(data->client,
- BMC150_ACCEL_REG_INT_MAP_0);
- if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_int_map_0\n");
- return ret;
- }
- if (status)
- ret |= BMC150_ACCEL_INT_MAP_0_BIT_SLOPE;
- else
- ret &= ~BMC150_ACCEL_INT_MAP_0_BIT_SLOPE;
-
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_MAP_0,
- ret);
- if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_map_0\n");
- return ret;
- }
-
- if (status) {
- /*
- * New data interrupt is always non-latched,
- * which will have higher priority, so no need
- * to set latched mode, we will be flooded anyway with INTR
- */
- if (!data->dready_trigger_on) {
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_LATCH_INT |
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "Error writing reg_int_rst_latch\n");
- return ret;
- }
- }
-
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_EN_0,
- BMC150_ACCEL_INT_EN_BIT_SLP_X |
- BMC150_ACCEL_INT_EN_BIT_SLP_Y |
- BMC150_ACCEL_INT_EN_BIT_SLP_Z);
- } else
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_EN_0,
- 0);
-
- if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_en_0\n");
- return ret;
- }
-
- return 0;
-}
-
-static int bmc150_accel_setup_new_data_interrupt(struct bmc150_accel_data *data,
- bool status)
-{
- int ret;
-
- /* Enable/Disable INT1 mapping */
- ret = i2c_smbus_read_byte_data(data->client,
- BMC150_ACCEL_REG_INT_MAP_1);
- if (ret < 0) {
- dev_err(&data->client->dev, "Error reading reg_int_map_1\n");
- return ret;
- }
- if (status)
- ret |= BMC150_ACCEL_INT_MAP_1_BIT_DATA;
- else
- ret &= ~BMC150_ACCEL_INT_MAP_1_BIT_DATA;
-
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_MAP_1,
- ret);
- if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_map_1\n");
- return ret;
- }
-
- if (status) {
- /*
- * Set non latched mode interrupt and clear any latched
- * interrupt
- */
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_NON_LATCH_INT |
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "Error writing reg_int_rst_latch\n");
- return ret;
- }
-
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_EN_1,
- BMC150_ACCEL_INT_EN_BIT_DATA_EN);
-
- } else {
- /* Restore default interrupt mode */
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_LATCH_INT |
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "Error writing reg_int_rst_latch\n");
- return ret;
- }
-
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_EN_1,
- 0);
- }
-
- if (ret < 0) {
- dev_err(&data->client->dev, "Error writing reg_int_en_1\n");
- return ret;
- }
-
- return 0;
-}
-
static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
int *val2)
{
@@ -559,6 +435,99 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
}
#endif
+static struct bmc150_accel_interrupt_info bmc150_accel_interrupts[] = {
+ { /* data ready interrupt */
+ .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_DATA,
+ .en_reg = BMC150_ACCEL_REG_INT_EN_1,
+ .en_bitmask = BMC150_ACCEL_INT_EN_BIT_DATA_EN,
+ },
+ { /* motion interrupt */
+ .map_reg = BMC150_ACCEL_REG_INT_MAP_0,
+ .map_bitmask = BMC150_ACCEL_INT_MAP_0_BIT_SLOPE,
+ .en_reg = BMC150_ACCEL_REG_INT_EN_0,
+ .en_bitmask = BMC150_ACCEL_INT_EN_BIT_SLP_X |
+ BMC150_ACCEL_INT_EN_BIT_SLP_Y |
+ BMC150_ACCEL_INT_EN_BIT_SLP_Z
+ },
+};
+
+static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data,
+ struct bmc150_accel_interrupt_info *info,
+ bool state)
+{
+ int ret;
+
+ /*
+ * We will expect the enable and disable to do operation in
+ * in reverse order. This will happen here anyway as our
+ * resume operation uses sync mode runtime pm calls, the
+ * suspend operation will be delayed by autosuspend delay
+ * So the disable operation will still happen in reverse of
+ * enable operation. When runtime pm is disabled the mode
+ * is always on so sequence doesn't matter
+ */
+ ret = bmc150_accel_set_power_state(data, state);
+ if (ret < 0)
+ return ret;
+
+
+ /* map the interrupt to the appropriate pins */
+ if (info->map_reg) {
+ ret = i2c_smbus_read_byte_data(data->client, info->map_reg);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_int_map\n");
+ return ret;
+ }
+ if (state)
+ ret |= info->map_bitmask;
+ else
+ ret &= ~info->map_bitmask;
+
+ ret = i2c_smbus_write_byte_data(data->client, info->map_reg,
+ ret);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_int_map\n");
+ return ret;
+ }
+ }
+
+ /* enable/disable the interrupt */
+ ret = i2c_smbus_read_byte_data(data->client, info->en_reg);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_int_en\n");
+ return ret;
+ }
+
+ if (state)
+ ret |= info->en_bitmask;
+ else
+ ret &= ~info->en_bitmask;
+
+ ret = i2c_smbus_write_byte_data(data->client, info->en_reg, ret);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_int_en\n");
+ 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);
+}
+
+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)
{
int ret, i;
@@ -808,22 +777,6 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
return 0;
}
- /*
- * We will expect the enable and disable to do operation in
- * in reverse order. This will happen here anyway as our
- * resume operation uses sync mode runtime pm calls, the
- * suspend operation will be delayed by autosuspend delay
- * So the disable operation will still happen in reverse of
- * enable operation. When runtime pm is disabled the mode
- * is always on so sequence doesn't matter
- */
-
- ret = bmc150_accel_set_power_state(data, state);
- if (ret < 0) {
- mutex_unlock(&data->mutex);
- return ret;
- }
-
ret = bmc150_accel_setup_any_motion_interrupt(data, state);
if (ret < 0) {
mutex_unlock(&data->mutex);
@@ -1055,15 +1008,6 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig,
return 0;
}
- /*
- * Refer to comment in bmc150_accel_write_event_config for
- * enable/disable operation order
- */
- ret = bmc150_accel_set_power_state(data, state);
- if (ret < 0) {
- mutex_unlock(&data->mutex);
- return ret;
- }
if (data->motion_trig == trig)
ret = bmc150_accel_setup_any_motion_interrupt(data, state);
else
@@ -1240,6 +1184,21 @@ static int bmc150_accel_probe(struct i2c_client *client,
if (ret)
return ret;
+ /*
+ * Set latched mode interrupt. While certain interrupts are
+ * non-latched regardless of this settings (e.g. new data) we
+ * want to use latch mode when we can to prevent interrupt
+ * flooding.
+ */
+ ret = i2c_smbus_write_byte_data(data->client,
+ BMC150_ACCEL_REG_INT_RST_LATCH,
+ BMC150_ACCEL_INT_MODE_LATCH_RESET);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
+ return ret;
+ }
+
+
data->dready_trig = devm_iio_trigger_alloc(&client->dev,
"%s-dev%d",
indio_dev->name,
--
1.9.1
next prev parent reply other threads:[~2014-11-17 18:05 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-17 17:55 [RFC 0/8] iio: add support for hardware fifo Octavian Purdila
2014-11-17 17:55 ` [RFC 1/8] " Octavian Purdila
2014-11-18 13:37 ` jic23
2014-11-18 15:21 ` Octavian Purdila
2014-11-17 17:56 ` [RFC 2/8] iio: bmc150: refactor slope duration and threshold update Octavian Purdila
2014-11-23 21:58 ` Hartmut Knaack
2014-11-23 22:16 ` Octavian Purdila
2014-11-17 17:56 ` Octavian Purdila [this message]
2014-11-23 22:02 ` [RFC 3/8] iio: bmc150: refactor interrupt enabling Hartmut Knaack
2014-11-23 22:24 ` Octavian Purdila
2014-11-17 17:56 ` [RFC 4/8] iio: bmc150: exit early if event / trigger state is not changed Octavian Purdila
2014-11-17 17:56 ` [RFC 5/8] iio: bmc150: introduce bmc150_accel_interrupt Octavian Purdila
2014-11-17 17:56 ` [RFC 6/8] iio: bmc150: introduce bmc150_accel_trigger Octavian Purdila
2014-11-23 23:06 ` Hartmut Knaack
2014-11-24 10:42 ` Octavian Purdila
2014-11-24 20:26 ` Hartmut Knaack
2014-11-25 16:06 ` Octavian Purdila
2014-11-17 17:56 ` [RFC 7/8] iio: bmc150: introduce bmc150_accel_event Octavian Purdila
2014-11-17 17:56 ` [RFC 8/8] iio: bmc150: add support for hardware fifo Octavian Purdila
2014-11-18 13:49 ` jic23
2014-11-18 15:31 ` Octavian Purdila
2014-11-24 10:37 ` Hartmut Knaack
2014-11-18 13:24 ` [RFC 0/8] iio: " jic23
2014-11-18 15:03 ` Octavian Purdila
2014-11-18 16:44 ` Lars-Peter Clausen
2014-11-18 17:04 ` Octavian Purdila
2014-11-18 17:23 ` Lars-Peter Clausen
2014-11-18 19:35 ` Octavian Purdila
2014-11-19 11:48 ` Lars-Peter Clausen
2014-11-19 12:33 ` Octavian Purdila
2014-12-12 12:57 ` Jonathan Cameron
2014-11-19 13:32 ` Octavian Purdila
2014-11-26 13:06 ` Octavian Purdila
2014-12-01 21:19 ` Lars-Peter Clausen
2014-12-02 9:13 ` Octavian Purdila
2014-12-12 13:10 ` Jonathan Cameron
2014-12-12 13:04 ` Jonathan Cameron
2014-12-12 12:52 ` Jonathan Cameron
2014-11-18 15:35 ` Pandruvada, Srinivas
2014-11-18 16:41 ` Lars-Peter Clausen
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=1416246966-3083-4-git-send-email-octavian.purdila@intel.com \
--to=octavian.purdila@intel.com \
--cc=linux-iio@vger.kernel.org \
--cc=srinivas.pandruvada@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).