diff options
author | Mårten Lindahl <marten.lindahl@axis.com> | 2023-01-17 22:00:15 +0300 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2023-01-21 21:04:39 +0300 |
commit | 3a52d32a7497fa21b2dcedf5051cca7b46a7921f (patch) | |
tree | 493e287a741df4144a4af0b22b904173acb08171 /drivers/iio | |
parent | 3b5eea320db5d9d2499accfc1884b4f221cd4223 (diff) | |
download | linux-3a52d32a7497fa21b2dcedf5051cca7b46a7921f.tar.xz |
iio: light: vcnl4000: Prepare for more generic setup
In order to allow the chip_spec array reference the function pointers
for interrupts, the code for these functions need to be moved above the
chip_spec array.
This is a prestep to support a more generic setup of interrupts.
Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20230117190017.3789181-2-marten.lindahl@axis.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/light/vcnl4000.c | 256 |
1 files changed, 128 insertions, 128 deletions
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index cc1a2062e76d..11b54b57e592 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -887,6 +887,134 @@ static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev, return sprintf(buf, "%u\n", data->near_level); } +static irqreturn_t vcnl4010_irq_thread(int irq, void *p) +{ + struct iio_dev *indio_dev = p; + struct vcnl4000_data *data = iio_priv(indio_dev); + unsigned long isr; + int ret; + + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); + if (ret < 0) + goto end; + + isr = ret; + + if (isr & VCNL4010_INT_THR) { + if (test_bit(VCNL4010_INT_THR_LOW, &isr)) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE( + IIO_PROXIMITY, + 1, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + iio_get_time_ns(indio_dev)); + } + + if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE( + IIO_PROXIMITY, + 1, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + iio_get_time_ns(indio_dev)); + } + + i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, + isr & VCNL4010_INT_THR); + } + + if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev)) + iio_trigger_poll_chained(indio_dev->trig); + +end: + return IRQ_HANDLED; +} + +static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct vcnl4000_data *data = iio_priv(indio_dev); + const unsigned long *active_scan_mask = indio_dev->active_scan_mask; + u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */ + bool data_read = false; + unsigned long isr; + int val = 0; + int ret; + + ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); + if (ret < 0) + goto end; + + isr = ret; + + if (test_bit(0, active_scan_mask)) { + if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) { + ret = vcnl4000_read_data(data, + VCNL4000_PS_RESULT_HI, + &val); + if (ret < 0) + goto end; + + buffer[0] = val; + data_read = true; + } + } + + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, + isr & VCNL4010_INT_DRDY); + if (ret < 0) + goto end; + + if (!data_read) + goto end; + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_get_time_ns(indio_dev)); + +end: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev) +{ + struct vcnl4000_data *data = iio_priv(indio_dev); + int ret; + int cmd; + + /* Do not enable the buffer if we are already capturing events. */ + if (vcnl4010_is_in_periodic_mode(data)) + return -EBUSY; + + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, + VCNL4010_INT_PROX_EN); + if (ret < 0) + return ret; + + cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; + return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); +} + +static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev) +{ + struct vcnl4000_data *data = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); +} + +static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = { + .postenable = &vcnl4010_buffer_postenable, + .predisable = &vcnl4010_buffer_predisable, +}; + static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = { { .name = "nearlevel", @@ -1030,134 +1158,6 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { }, }; -static irqreturn_t vcnl4010_irq_thread(int irq, void *p) -{ - struct iio_dev *indio_dev = p; - struct vcnl4000_data *data = iio_priv(indio_dev); - unsigned long isr; - int ret; - - ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); - if (ret < 0) - goto end; - - isr = ret; - - if (isr & VCNL4010_INT_THR) { - if (test_bit(VCNL4010_INT_THR_LOW, &isr)) { - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE( - IIO_PROXIMITY, - 1, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_FALLING), - iio_get_time_ns(indio_dev)); - } - - if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) { - iio_push_event(indio_dev, - IIO_UNMOD_EVENT_CODE( - IIO_PROXIMITY, - 1, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_RISING), - iio_get_time_ns(indio_dev)); - } - - i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, - isr & VCNL4010_INT_THR); - } - - if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev)) - iio_trigger_poll_chained(indio_dev->trig); - -end: - return IRQ_HANDLED; -} - -static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct vcnl4000_data *data = iio_priv(indio_dev); - const unsigned long *active_scan_mask = indio_dev->active_scan_mask; - u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */ - bool data_read = false; - unsigned long isr; - int val = 0; - int ret; - - ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR); - if (ret < 0) - goto end; - - isr = ret; - - if (test_bit(0, active_scan_mask)) { - if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) { - ret = vcnl4000_read_data(data, - VCNL4000_PS_RESULT_HI, - &val); - if (ret < 0) - goto end; - - buffer[0] = val; - data_read = true; - } - } - - ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR, - isr & VCNL4010_INT_DRDY); - if (ret < 0) - goto end; - - if (!data_read) - goto end; - - iio_push_to_buffers_with_timestamp(indio_dev, buffer, - iio_get_time_ns(indio_dev)); - -end: - iio_trigger_notify_done(indio_dev->trig); - return IRQ_HANDLED; -} - -static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev) -{ - struct vcnl4000_data *data = iio_priv(indio_dev); - int ret; - int cmd; - - /* Do not enable the buffer if we are already capturing events. */ - if (vcnl4010_is_in_periodic_mode(data)) - return -EBUSY; - - ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, - VCNL4010_INT_PROX_EN); - if (ret < 0) - return ret; - - cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; - return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); -} - -static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev) -{ - struct vcnl4000_data *data = iio_priv(indio_dev); - int ret; - - ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); - if (ret < 0) - return ret; - - return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); -} - -static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = { - .postenable = &vcnl4010_buffer_postenable, - .predisable = &vcnl4010_buffer_predisable, -}; - static const struct iio_trigger_ops vcnl4010_trigger_ops = { .validate_device = iio_trigger_validate_own_device, }; |