iio: st_sensors: verify interrupt event to status
authorLinus Walleij <linus.walleij@linaro.org>
Thu, 24 Mar 2016 13:18:05 +0000 (14:18 +0100)
committerJonathan Cameron <jic23@kernel.org>
Tue, 19 Apr 2016 18:58:12 +0000 (19:58 +0100)
This makes all ST sensor drivers check that they actually have
new data available for the requested channel(s) before claiming
an IRQ, by reading the status register (which is conveniently
the same for all ST sensors) and check that the channel has new
data before proceeding to read it and fill the buffer.

This way sensors can share an interrupt line: it can be flaged
as shared and then the sensor that did not fire will return
NO_IRQ, and the sensor that fired will handle the IRQ and
return IRQ_HANDLED.

Cc: Giuseppe Barba <giuseppe.barba@st.com>
Cc: Denis Ciocca <denis.ciocca@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/accel/st_accel_core.c
drivers/iio/common/st_sensors/st_sensors_buffer.c
drivers/iio/gyro/st_gyro_core.c
drivers/iio/magnetometer/st_magn_core.c
drivers/iio/pressure/st_pressure_core.c
include/linux/iio/common/st_sensors.h

index fee32e3d7a05845b5c9c511116ebbc055883502a..9fb6d35fce5b493e56bda4c7efff0b1e319d8366 100644 (file)
@@ -332,6 +332,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                        .mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
                        .addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR,
                        .mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
                .bootime = 2,
@@ -397,6 +398,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                        .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
                        .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
                        .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
                .bootime = 2,
@@ -474,6 +476,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                        .mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
                        .addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR,
                        .mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                        .ig1 = {
                                .en_addr = ST_ACCEL_3_IG1_EN_ADDR,
                                .en_mask = ST_ACCEL_3_IG1_EN_MASK,
@@ -532,6 +535,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                .drdy_irq = {
                        .addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
                        .mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
                .bootime = 2, /* guess */
@@ -583,6 +587,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                        .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
                        .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
                        .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
                .bootime = 2, /* guess */
index 2ce0d2a3f85572ed2e0b9faf1790818e9e8235e9..c55898543a47d9a2db596e89f59c5416b19bb0b7 100644 (file)
@@ -58,6 +58,24 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
        struct iio_dev *indio_dev = pf->indio_dev;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
+       /* If we have a status register, check if this IRQ came from us */
+       if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) {
+               u8 status;
+
+               len = sdata->tf->read_byte(&sdata->tb, sdata->dev,
+                          sdata->sensor_settings->drdy_irq.addr_stat_drdy,
+                          &status);
+               if (len < 0)
+                       dev_err(sdata->dev, "could not read channel status\n");
+
+               /*
+                * If this was not caused by any channels on this sensor,
+                * return IRQ_NONE
+                */
+               if (!(status & (u8)indio_dev->active_scan_mask[0]))
+                       return IRQ_NONE;
+       }
+
        len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data);
        if (len < 0)
                goto st_sensors_get_buffer_element_error;
index 110f95b6e52fa1a085523ba438b470be861edb35..be9057e89dc3d83eb92f170822c748d0ef48f79d 100644 (file)
@@ -190,6 +190,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
                         * drain settings, but only for INT1 and not
                         * for the DRDY line on INT2.
                         */
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
                .bootime = 2,
@@ -258,6 +259,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
                         * drain settings, but only for INT1 and not
                         * for the DRDY line on INT2.
                         */
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
                .bootime = 2,
@@ -322,6 +324,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
                         * drain settings, but only for INT1 and not
                         * for the DRDY line on INT2.
                         */
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_GYRO_3_MULTIREAD_BIT,
                .bootime = 2,
index 501f858df4137ea905eb78ea5b72badadcab4ce3..62036d2a9956aa426cdde5ce71906e4e82663510 100644 (file)
@@ -484,6 +484,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
                        .mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
                        .addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR,
                        .mask_ihl = ST_MAGN_3_IHL_IRQ_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
                .bootime = 2,
index 172393ad34aff04f9b4909a73e3a16985f82c109..1cd37eaa4a57b0445cd75204f9fc98543a6d2219 100644 (file)
@@ -226,6 +226,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
                        .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
                        .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR,
                        .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
                .bootime = 2,
@@ -312,6 +313,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
                        .mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
                        .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR,
                        .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK,
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
                },
                .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
                .bootime = 2,
index 6670c3d25c58c8d0c1b0e1c0260dc3e52f57bc46..d8da075bfda09e14332e5416c2d82258a7d9e5c2 100644 (file)
@@ -37,6 +37,7 @@
 #define ST_SENSORS_DEFAULT_AXIS_ADDR           0x20
 #define ST_SENSORS_DEFAULT_AXIS_MASK           0x07
 #define ST_SENSORS_DEFAULT_AXIS_N_BIT          3
+#define ST_SENSORS_DEFAULT_STAT_ADDR           0x27
 
 #define ST_SENSORS_MAX_NAME                    17
 #define ST_SENSORS_MAX_4WAI                    7
@@ -121,6 +122,7 @@ struct st_sensor_bdu {
  * @mask_int2: mask to enable/disable IRQ on INT2 pin.
  * @addr_ihl: address to enable/disable active low on the INT lines.
  * @mask_ihl: mask to enable/disable active low on the INT lines.
+ * @addr_stat_drdy: address to read status of DRDY (data ready) interrupt
  * struct ig1 - represents the Interrupt Generator 1 of sensors.
  * @en_addr: address of the enable ig1 register.
  * @en_mask: mask to write the on/off value for enable.
@@ -131,6 +133,7 @@ struct st_sensor_data_ready_irq {
        u8 mask_int2;
        u8 addr_ihl;
        u8 mask_ihl;
+       u8 addr_stat_drdy;
        struct {
                u8 en_addr;
                u8 en_mask;