diff options
author | Jonathan Cameron <jic23@cam.ac.uk> | 2011-05-18 14:41:17 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-19 16:13:06 -0700 |
commit | 461be806744d0c83babcfa5d63993b43bd801c46 (patch) | |
tree | 7961bb86e325cd4dc18cb9be484ac2839f88d5ea /drivers/staging/iio/accel/lis3l02dq_core.c | |
parent | aaf370db7dad574e166f64cd9ad4129f12198145 (diff) |
staging:iio:accel:lis3l02dq make threshold interrupt threaded.
We have moved the timestamp acquisition into the bottom half. It may
technically be less accurate but for this device I very much doubt
anyone cares!
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/iio/accel/lis3l02dq_core.c')
-rw-r--r-- | drivers/staging/iio/accel/lis3l02dq_core.c | 159 |
1 files changed, 73 insertions, 86 deletions
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 2b70a6756e90..6c5f8a60832e 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -422,10 +422,72 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private) struct iio_sw_ring_helper_state *h = iio_dev_get_devdata(indio_dev); struct lis3l02dq_state *st = lis3l02dq_h_to_s(h); + u8 t; + + s64 timestamp = iio_get_time_ns(); + + lis3l02dq_spi_read_reg_8(st->help.indio_dev, + LIS3L02DQ_REG_WAKE_UP_SRC_ADDR, + &t); - disable_irq_nosync(irq); - st->thresh_timestamp = iio_get_time_ns(); - schedule_work(&st->work_thresh); + if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH) + iio_push_event(st->help.indio_dev, 0, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + 0, + IIO_EV_MOD_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + + if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW) + iio_push_event(st->help.indio_dev, 0, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + 0, + IIO_EV_MOD_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + + if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH) + iio_push_event(st->help.indio_dev, 0, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + 0, + IIO_EV_MOD_Y, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + + if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW) + iio_push_event(st->help.indio_dev, 0, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + 0, + IIO_EV_MOD_Y, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + + if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH) + iio_push_event(st->help.indio_dev, 0, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + 0, + IIO_EV_MOD_X, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + + if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW) + iio_push_event(st->help.indio_dev, 0, + IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, + 0, + IIO_EV_MOD_X, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + + /* Ack and allow for new interrupts */ + lis3l02dq_spi_read_reg_8(st->help.indio_dev, + LIS3L02DQ_REG_WAKE_UP_ACK_ADDR, + &t); return IRQ_HANDLED; } @@ -550,11 +612,13 @@ static int lis3l02dq_write_event_config(struct iio_dev *indio_dev, if (changed) { if (!(control & LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT)) { - ret = request_irq(st->us->irq, - &lis3l02dq_event_handler, - IRQF_TRIGGER_RISING, - "lis3l02dq_event", - indio_dev); + ret = request_threaded_irq(st->us->irq, + NULL, + &lis3l02dq_event_handler, + IRQF_TRIGGER_RISING | + IRQF_ONESHOT, + "lis3l02dq_event", + indio_dev); if (ret) goto error_ret; } @@ -583,83 +647,6 @@ error_ret: return ret; } -/* Unforunately it appears the interrupt won't clear unless you read from the - * src register. - */ -static void lis3l02dq_thresh_handler_bh_no_check(struct work_struct *work_s) -{ - struct lis3l02dq_state *st - = container_of(work_s, - struct lis3l02dq_state, work_thresh); - u8 t; - - lis3l02dq_spi_read_reg_8(st->help.indio_dev, - LIS3L02DQ_REG_WAKE_UP_SRC_ADDR, - &t); - - if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH) - iio_push_event(st->help.indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, - 0, - IIO_EV_MOD_Z, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - st->thresh_timestamp); - - if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW) - iio_push_event(st->help.indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, - 0, - IIO_EV_MOD_Z, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - st->thresh_timestamp); - - if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH) - iio_push_event(st->help.indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, - 0, - IIO_EV_MOD_Y, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - st->thresh_timestamp); - - if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW) - iio_push_event(st->help.indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, - 0, - IIO_EV_MOD_Y, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - st->thresh_timestamp); - - if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH) - iio_push_event(st->help.indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, - 0, - IIO_EV_MOD_X, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - st->thresh_timestamp); - - if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW) - iio_push_event(st->help.indio_dev, 0, - IIO_MOD_EVENT_CODE(IIO_EV_CLASS_ACCEL, - 0, - IIO_EV_MOD_X, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - st->thresh_timestamp); - /* reenable the irq */ - enable_irq(st->us->irq); - /* Ack and allow for new interrupts */ - lis3l02dq_spi_read_reg_8(st->help.indio_dev, - LIS3L02DQ_REG_WAKE_UP_ACK_ADDR, - &t); - - return; -} - static IIO_CONST_ATTR_NAME("lis3l02dq"); static struct attribute *lis3l02dq_attributes[] = { @@ -681,7 +668,7 @@ static int __devinit lis3l02dq_probe(struct spi_device *spi) ret = -ENOMEM; goto error_ret; } - INIT_WORK(&st->work_thresh, lis3l02dq_thresh_handler_bh_no_check); + /* this is only used tor removal purposes */ spi_set_drvdata(spi, st); |