blob: c55898543a47d9a2db596e89f59c5416b19bb0b7 [file] [log] [blame]
Denis Ciocca23491b52013-01-25 23:44:00 +00001/*
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
25int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
26{
Linus Walleij6436db32016-03-24 14:18:04 +010027 int i, len;
28 int total = 0;
Denis Ciocca23491b52013-01-25 23:44:00 +000029 struct st_sensor_data *sdata = iio_priv(indio_dev);
Denis CIOCCA607a5682013-06-03 15:58:00 +010030 unsigned int num_data_channels = sdata->num_data_channels;
Denis Ciocca23491b52013-01-25 23:44:00 +000031
Denis CIOCCA607a5682013-06-03 15:58:00 +010032 for (i = 0; i < num_data_channels; i++) {
Linus Walleij6436db32016-03-24 14:18:04 +010033 unsigned int bytes_to_read;
34
Denis Ciocca23491b52013-01-25 23:44:00 +000035 if (test_bit(i, indio_dev->active_scan_mask)) {
Linus Walleij6436db32016-03-24 14:18:04 +010036 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 Ciocca23491b52013-01-25 23:44:00 +000047 }
48 }
Denis CIOCCA607a5682013-06-03 15:58:00 +010049
Linus Walleij6436db32016-03-24 14:18:04 +010050 return total;
Denis Ciocca23491b52013-01-25 23:44:00 +000051}
52EXPORT_SYMBOL(st_sensors_get_buffer_element);
53
54irqreturn_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 Walleij97865fe2016-03-24 14:18:05 +010061 /* 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 Ciocca23491b52013-01-25 23:44:00 +000079 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 Clausenaa4e2422013-09-19 13:59:00 +010083 iio_push_to_buffers_with_timestamp(indio_dev, sdata->buffer_data,
84 pf->timestamp);
Denis Ciocca23491b52013-01-25 23:44:00 +000085
86st_sensors_get_buffer_element_error:
87 iio_trigger_notify_done(indio_dev->trig);
88
89 return IRQ_HANDLED;
90}
91EXPORT_SYMBOL(st_sensors_trigger_handler);
92
93MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
94MODULE_DESCRIPTION("STMicroelectronics ST-sensors buffer");
95MODULE_LICENSE("GPL v2");