root/drivers/iio/common/st_sensors/st_sensors_trigger.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. st_sensors_new_samples_available
  2. st_sensors_irq_handler
  3. st_sensors_irq_thread
  4. st_sensors_allocate_trigger
  5. st_sensors_deallocate_trigger
  6. st_sensors_validate_device

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * STMicroelectronics sensors trigger library driver
   4  *
   5  * Copyright 2012-2013 STMicroelectronics Inc.
   6  *
   7  * Denis Ciocca <denis.ciocca@st.com>
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/module.h>
  12 #include <linux/slab.h>
  13 #include <linux/iio/iio.h>
  14 #include <linux/iio/trigger.h>
  15 #include <linux/interrupt.h>
  16 #include <linux/regmap.h>
  17 #include <linux/iio/common/st_sensors.h>
  18 #include "st_sensors_core.h"
  19 
  20 /**
  21  * st_sensors_new_samples_available() - check if more samples came in
  22  * returns:
  23  * 0 - no new samples available
  24  * 1 - new samples available
  25  * negative - error or unknown
  26  */
  27 static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
  28                                             struct st_sensor_data *sdata)
  29 {
  30         int ret, status;
  31 
  32         /* How would I know if I can't check it? */
  33         if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr)
  34                 return -EINVAL;
  35 
  36         /* No scan mask, no interrupt */
  37         if (!indio_dev->active_scan_mask)
  38                 return 0;
  39 
  40         ret = regmap_read(sdata->regmap,
  41                           sdata->sensor_settings->drdy_irq.stat_drdy.addr,
  42                           &status);
  43         if (ret < 0) {
  44                 dev_err(sdata->dev,
  45                         "error checking samples available\n");
  46                 return ret;
  47         }
  48 
  49         if (status & sdata->sensor_settings->drdy_irq.stat_drdy.mask)
  50                 return 1;
  51 
  52         return 0;
  53 }
  54 
  55 /**
  56  * st_sensors_irq_handler() - top half of the IRQ-based triggers
  57  * @irq: irq number
  58  * @p: private handler data
  59  */
  60 static irqreturn_t st_sensors_irq_handler(int irq, void *p)
  61 {
  62         struct iio_trigger *trig = p;
  63         struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
  64         struct st_sensor_data *sdata = iio_priv(indio_dev);
  65 
  66         /* Get the time stamp as close in time as possible */
  67         sdata->hw_timestamp = iio_get_time_ns(indio_dev);
  68         return IRQ_WAKE_THREAD;
  69 }
  70 
  71 /**
  72  * st_sensors_irq_thread() - bottom half of the IRQ-based triggers
  73  * @irq: irq number
  74  * @p: private handler data
  75  */
  76 static irqreturn_t st_sensors_irq_thread(int irq, void *p)
  77 {
  78         struct iio_trigger *trig = p;
  79         struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
  80         struct st_sensor_data *sdata = iio_priv(indio_dev);
  81 
  82         /*
  83          * If this trigger is backed by a hardware interrupt and we have a
  84          * status register, check if this IRQ came from us. Notice that
  85          * we will process also if st_sensors_new_samples_available()
  86          * returns negative: if we can't check status, then poll
  87          * unconditionally.
  88          */
  89         if (sdata->hw_irq_trigger &&
  90             st_sensors_new_samples_available(indio_dev, sdata)) {
  91                 iio_trigger_poll_chained(p);
  92         } else {
  93                 dev_dbg(sdata->dev, "spurious IRQ\n");
  94                 return IRQ_NONE;
  95         }
  96 
  97         /*
  98          * If we have proper level IRQs the handler will be re-entered if
  99          * the line is still active, so return here and come back in through
 100          * the top half if need be.
 101          */
 102         if (!sdata->edge_irq)
 103                 return IRQ_HANDLED;
 104 
 105         /*
 106          * If we are using edge IRQs, new samples arrived while processing
 107          * the IRQ and those may be missed unless we pick them here, so poll
 108          * again. If the sensor delivery frequency is very high, this thread
 109          * turns into a polled loop handler.
 110          */
 111         while (sdata->hw_irq_trigger &&
 112                st_sensors_new_samples_available(indio_dev, sdata)) {
 113                 dev_dbg(sdata->dev, "more samples came in during polling\n");
 114                 sdata->hw_timestamp = iio_get_time_ns(indio_dev);
 115                 iio_trigger_poll_chained(p);
 116         }
 117 
 118         return IRQ_HANDLED;
 119 }
 120 
 121 int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
 122                                 const struct iio_trigger_ops *trigger_ops)
 123 {
 124         struct st_sensor_data *sdata = iio_priv(indio_dev);
 125         unsigned long irq_trig;
 126         int err;
 127 
 128         sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name);
 129         if (sdata->trig == NULL) {
 130                 dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n");
 131                 return -ENOMEM;
 132         }
 133 
 134         iio_trigger_set_drvdata(sdata->trig, indio_dev);
 135         sdata->trig->ops = trigger_ops;
 136         sdata->trig->dev.parent = sdata->dev;
 137 
 138         irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq));
 139         /*
 140          * If the IRQ is triggered on falling edge, we need to mark the
 141          * interrupt as active low, if the hardware supports this.
 142          */
 143         switch(irq_trig) {
 144         case IRQF_TRIGGER_FALLING:
 145         case IRQF_TRIGGER_LOW:
 146                 if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
 147                         dev_err(&indio_dev->dev,
 148                                 "falling/low specified for IRQ "
 149                                 "but hardware supports only rising/high: "
 150                                 "will request rising/high\n");
 151                         if (irq_trig == IRQF_TRIGGER_FALLING)
 152                                 irq_trig = IRQF_TRIGGER_RISING;
 153                         if (irq_trig == IRQF_TRIGGER_LOW)
 154                                 irq_trig = IRQF_TRIGGER_HIGH;
 155                 } else {
 156                         /* Set up INT active low i.e. falling edge */
 157                         err = st_sensors_write_data_with_mask(indio_dev,
 158                                 sdata->sensor_settings->drdy_irq.addr_ihl,
 159                                 sdata->sensor_settings->drdy_irq.mask_ihl, 1);
 160                         if (err < 0)
 161                                 goto iio_trigger_free;
 162                         dev_info(&indio_dev->dev,
 163                                  "interrupts on the falling edge or "
 164                                  "active low level\n");
 165                 }
 166                 break;
 167         case IRQF_TRIGGER_RISING:
 168                 dev_info(&indio_dev->dev,
 169                          "interrupts on the rising edge\n");
 170                 break;
 171         case IRQF_TRIGGER_HIGH:
 172                 dev_info(&indio_dev->dev,
 173                          "interrupts active high level\n");
 174                 break;
 175         default:
 176                 /* This is the most preferred mode, if possible */
 177                 dev_err(&indio_dev->dev,
 178                         "unsupported IRQ trigger specified (%lx), enforce "
 179                         "rising edge\n", irq_trig);
 180                 irq_trig = IRQF_TRIGGER_RISING;
 181         }
 182 
 183         /* Tell the interrupt handler that we're dealing with edges */
 184         if (irq_trig == IRQF_TRIGGER_FALLING ||
 185             irq_trig == IRQF_TRIGGER_RISING)
 186                 sdata->edge_irq = true;
 187         else
 188                 /*
 189                  * If we're not using edges (i.e. level interrupts) we
 190                  * just mask off the IRQ, handle one interrupt, then
 191                  * if the line is still low, we return to the
 192                  * interrupt handler top half again and start over.
 193                  */
 194                 irq_trig |= IRQF_ONESHOT;
 195 
 196         /*
 197          * If the interrupt pin is Open Drain, by definition this
 198          * means that the interrupt line may be shared with other
 199          * peripherals. But to do this we also need to have a status
 200          * register and mask to figure out if this sensor was firing
 201          * the IRQ or not, so we can tell the interrupt handle that
 202          * it was "our" interrupt.
 203          */
 204         if (sdata->int_pin_open_drain &&
 205             sdata->sensor_settings->drdy_irq.stat_drdy.addr)
 206                 irq_trig |= IRQF_SHARED;
 207 
 208         err = request_threaded_irq(sdata->irq,
 209                                    st_sensors_irq_handler,
 210                                    st_sensors_irq_thread,
 211                                    irq_trig,
 212                                    sdata->trig->name,
 213                                    sdata->trig);
 214         if (err) {
 215                 dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n");
 216                 goto iio_trigger_free;
 217         }
 218 
 219         err = iio_trigger_register(sdata->trig);
 220         if (err < 0) {
 221                 dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
 222                 goto iio_trigger_register_error;
 223         }
 224         indio_dev->trig = iio_trigger_get(sdata->trig);
 225 
 226         return 0;
 227 
 228 iio_trigger_register_error:
 229         free_irq(sdata->irq, sdata->trig);
 230 iio_trigger_free:
 231         iio_trigger_free(sdata->trig);
 232         return err;
 233 }
 234 EXPORT_SYMBOL(st_sensors_allocate_trigger);
 235 
 236 void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
 237 {
 238         struct st_sensor_data *sdata = iio_priv(indio_dev);
 239 
 240         iio_trigger_unregister(sdata->trig);
 241         free_irq(sdata->irq, sdata->trig);
 242         iio_trigger_free(sdata->trig);
 243 }
 244 EXPORT_SYMBOL(st_sensors_deallocate_trigger);
 245 
 246 int st_sensors_validate_device(struct iio_trigger *trig,
 247                                struct iio_dev *indio_dev)
 248 {
 249         struct iio_dev *indio = iio_trigger_get_drvdata(trig);
 250 
 251         if (indio != indio_dev)
 252                 return -EINVAL;
 253 
 254         return 0;
 255 }
 256 EXPORT_SYMBOL(st_sensors_validate_device);
 257 
 258 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
 259 MODULE_DESCRIPTION("STMicroelectronics ST-sensors trigger");
 260 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */