|
@@ -17,6 +17,73 @@
|
|
#include <linux/iio/common/st_sensors.h>
|
|
#include <linux/iio/common/st_sensors.h>
|
|
#include "st_sensors_core.h"
|
|
#include "st_sensors_core.h"
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * st_sensors_irq_handler() - top half of the IRQ-based triggers
|
|
|
|
+ * @irq: irq number
|
|
|
|
+ * @p: private handler data
|
|
|
|
+ */
|
|
|
|
+irqreturn_t st_sensors_irq_handler(int irq, void *p)
|
|
|
|
+{
|
|
|
|
+ struct iio_trigger *trig = p;
|
|
|
|
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
|
|
|
|
+ struct st_sensor_data *sdata = iio_priv(indio_dev);
|
|
|
|
+
|
|
|
|
+ /* Get the time stamp as close in time as possible */
|
|
|
|
+ sdata->hw_timestamp = iio_get_time_ns();
|
|
|
|
+ return IRQ_WAKE_THREAD;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * st_sensors_irq_thread() - bottom half of the IRQ-based triggers
|
|
|
|
+ * @irq: irq number
|
|
|
|
+ * @p: private handler data
|
|
|
|
+ */
|
|
|
|
+irqreturn_t st_sensors_irq_thread(int irq, void *p)
|
|
|
|
+{
|
|
|
|
+ struct iio_trigger *trig = p;
|
|
|
|
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
|
|
|
|
+ struct st_sensor_data *sdata = iio_priv(indio_dev);
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If this trigger is backed by a hardware interrupt and we have a
|
|
|
|
+ * status register, check if this IRQ came from us
|
|
|
|
+ */
|
|
|
|
+ if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) {
|
|
|
|
+ u8 status;
|
|
|
|
+
|
|
|
|
+ ret = sdata->tf->read_byte(&sdata->tb, sdata->dev,
|
|
|
|
+ sdata->sensor_settings->drdy_irq.addr_stat_drdy,
|
|
|
|
+ &status);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(sdata->dev, "could not read channel status\n");
|
|
|
|
+ goto out_poll;
|
|
|
|
+ }
|
|
|
|
+ /*
|
|
|
|
+ * the lower bits of .active_scan_mask[0] is directly mapped
|
|
|
|
+ * to the channels on the sensor: either bit 0 for
|
|
|
|
+ * one-dimensional sensors, or e.g. x,y,z for accelerometers,
|
|
|
|
+ * gyroscopes or magnetometers. No sensor use more than 3
|
|
|
|
+ * channels, so cut the other status bits here.
|
|
|
|
+ */
|
|
|
|
+ status &= 0x07;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If this was not caused by any channels on this sensor,
|
|
|
|
+ * return IRQ_NONE
|
|
|
|
+ */
|
|
|
|
+ if (!indio_dev->active_scan_mask)
|
|
|
|
+ return IRQ_NONE;
|
|
|
|
+ if (!(status & (u8)indio_dev->active_scan_mask[0]))
|
|
|
|
+ return IRQ_NONE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+out_poll:
|
|
|
|
+ /* It's our IRQ: proceed to handle the register polling */
|
|
|
|
+ iio_trigger_poll_chained(p);
|
|
|
|
+ return IRQ_HANDLED;
|
|
|
|
+}
|
|
|
|
+
|
|
int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
|
int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
|
const struct iio_trigger_ops *trigger_ops)
|
|
const struct iio_trigger_ops *trigger_ops)
|
|
{
|
|
{
|
|
@@ -77,9 +144,12 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
|
sdata->sensor_settings->drdy_irq.addr_stat_drdy)
|
|
sdata->sensor_settings->drdy_irq.addr_stat_drdy)
|
|
irq_trig |= IRQF_SHARED;
|
|
irq_trig |= IRQF_SHARED;
|
|
|
|
|
|
- err = request_threaded_irq(irq,
|
|
|
|
- iio_trigger_generic_data_rdy_poll,
|
|
|
|
- NULL,
|
|
|
|
|
|
+ /* Let's create an interrupt thread masking the hard IRQ here */
|
|
|
|
+ irq_trig |= IRQF_ONESHOT;
|
|
|
|
+
|
|
|
|
+ err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
|
|
|
|
+ st_sensors_irq_handler,
|
|
|
|
+ st_sensors_irq_thread,
|
|
irq_trig,
|
|
irq_trig,
|
|
sdata->trig->name,
|
|
sdata->trig->name,
|
|
sdata->trig);
|
|
sdata->trig);
|
|
@@ -119,6 +189,18 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(st_sensors_deallocate_trigger);
|
|
EXPORT_SYMBOL(st_sensors_deallocate_trigger);
|
|
|
|
|
|
|
|
+int st_sensors_validate_device(struct iio_trigger *trig,
|
|
|
|
+ struct iio_dev *indio_dev)
|
|
|
|
+{
|
|
|
|
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
|
|
|
|
+
|
|
|
|
+ if (indio != indio_dev)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(st_sensors_validate_device);
|
|
|
|
+
|
|
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
|
|
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
|
|
MODULE_DESCRIPTION("STMicroelectronics ST-sensors trigger");
|
|
MODULE_DESCRIPTION("STMicroelectronics ST-sensors trigger");
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_LICENSE("GPL v2");
|