Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 1 | /* |
| 2 | * STMicroelectronics sensors buffer library driver |
| 3 | * |
| 4 | * Copyright 2012-2013 STMicroelectronics Inc. |
| 5 | * |
| 6 | * Denis Ciocca <denis.ciocca@st.com> |
| 7 | * |
| 8 | * Licensed under the GPL-2. |
| 9 | */ |
| 10 | |
| 11 | #include <linux/kernel.h> |
| 12 | #include <linux/module.h> |
| 13 | #include <linux/slab.h> |
| 14 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/trigger.h> |
| 16 | #include <linux/interrupt.h> |
| 17 | #include <linux/iio/buffer.h> |
| 18 | #include <linux/iio/trigger_consumer.h> |
| 19 | #include <linux/iio/triggered_buffer.h> |
| 20 | #include <linux/irqreturn.h> |
| 21 | |
| 22 | #include <linux/iio/common/st_sensors.h> |
| 23 | |
| 24 | |
| 25 | int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) |
| 26 | { |
Linus Walleij | 6436db3 | 2016-03-24 14:18:04 +0100 | [diff] [blame] | 27 | int i, len; |
| 28 | int total = 0; |
Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 29 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
Denis CIOCCA | 607a568 | 2013-06-03 15:58:00 +0100 | [diff] [blame] | 30 | unsigned int num_data_channels = sdata->num_data_channels; |
Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 31 | |
Denis CIOCCA | 607a568 | 2013-06-03 15:58:00 +0100 | [diff] [blame] | 32 | for (i = 0; i < num_data_channels; i++) { |
Linus Walleij | 6436db3 | 2016-03-24 14:18:04 +0100 | [diff] [blame] | 33 | unsigned int bytes_to_read; |
| 34 | |
Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 35 | if (test_bit(i, indio_dev->active_scan_mask)) { |
Linus Walleij | 6436db3 | 2016-03-24 14:18:04 +0100 | [diff] [blame] | 36 | bytes_to_read = indio_dev->channels[i].scan_type.storagebits >> 3; |
| 37 | len = sdata->tf->read_multiple_byte(&sdata->tb, |
| 38 | sdata->dev, indio_dev->channels[i].address, |
| 39 | bytes_to_read, |
| 40 | buf + total, sdata->multiread_bit); |
| 41 | |
| 42 | if (len < bytes_to_read) |
| 43 | return -EIO; |
| 44 | |
| 45 | /* Advance the buffer pointer */ |
| 46 | total += len; |
Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 47 | } |
| 48 | } |
Denis CIOCCA | 607a568 | 2013-06-03 15:58:00 +0100 | [diff] [blame] | 49 | |
Linus Walleij | 6436db3 | 2016-03-24 14:18:04 +0100 | [diff] [blame] | 50 | return total; |
Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 51 | } |
| 52 | EXPORT_SYMBOL(st_sensors_get_buffer_element); |
| 53 | |
| 54 | irqreturn_t st_sensors_trigger_handler(int irq, void *p) |
| 55 | { |
| 56 | int len; |
| 57 | struct iio_poll_func *pf = p; |
| 58 | struct iio_dev *indio_dev = pf->indio_dev; |
| 59 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 60 | |
Linus Walleij | 97865fe | 2016-03-24 14:18:05 +0100 | [diff] [blame] | 61 | /* If we have a status register, check if this IRQ came from us */ |
| 62 | if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) { |
| 63 | u8 status; |
| 64 | |
| 65 | len = sdata->tf->read_byte(&sdata->tb, sdata->dev, |
| 66 | sdata->sensor_settings->drdy_irq.addr_stat_drdy, |
| 67 | &status); |
| 68 | if (len < 0) |
| 69 | dev_err(sdata->dev, "could not read channel status\n"); |
| 70 | |
| 71 | /* |
| 72 | * If this was not caused by any channels on this sensor, |
| 73 | * return IRQ_NONE |
| 74 | */ |
| 75 | if (!(status & (u8)indio_dev->active_scan_mask[0])) |
| 76 | return IRQ_NONE; |
| 77 | } |
| 78 | |
Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 79 | len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data); |
| 80 | if (len < 0) |
| 81 | goto st_sensors_get_buffer_element_error; |
| 82 | |
Lars-Peter Clausen | aa4e242 | 2013-09-19 13:59:00 +0100 | [diff] [blame] | 83 | iio_push_to_buffers_with_timestamp(indio_dev, sdata->buffer_data, |
| 84 | pf->timestamp); |
Denis Ciocca | 23491b5 | 2013-01-25 23:44:00 +0000 | [diff] [blame] | 85 | |
| 86 | st_sensors_get_buffer_element_error: |
| 87 | iio_trigger_notify_done(indio_dev->trig); |
| 88 | |
| 89 | return IRQ_HANDLED; |
| 90 | } |
| 91 | EXPORT_SYMBOL(st_sensors_trigger_handler); |
| 92 | |
| 93 | MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); |
| 94 | MODULE_DESCRIPTION("STMicroelectronics ST-sensors buffer"); |
| 95 | MODULE_LICENSE("GPL v2"); |