243 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * STMicroelectronics sensors trigger library driver4 *5 * Copyright 2012-2013 STMicroelectronics Inc.6 *7 * Denis Ciocca <denis.ciocca@st.com>8 */9 10#include <linux/kernel.h>11#include <linux/iio/iio.h>12#include <linux/iio/trigger.h>13#include <linux/interrupt.h>14#include <linux/regmap.h>15#include <linux/iio/common/st_sensors.h>16#include "st_sensors_core.h"17 18/**19 * st_sensors_new_samples_available() - check if more samples came in20 * @indio_dev: IIO device reference.21 * @sdata: Sensor data.22 *23 * returns:24 * false - no new samples available or read error25 * true - new samples available26 */27static bool 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 true;35 36 /* No scan mask, no interrupt */37 if (!indio_dev->active_scan_mask)38 return false;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(indio_dev->dev.parent,45 "error checking samples available\n");46 return false;47 }48 49 return !!(status & sdata->sensor_settings->drdy_irq.stat_drdy.mask);50}51 52/**53 * st_sensors_irq_handler() - top half of the IRQ-based triggers54 * @irq: irq number55 * @p: private handler data56 */57static irqreturn_t st_sensors_irq_handler(int irq, void *p)58{59 struct iio_trigger *trig = p;60 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);61 struct st_sensor_data *sdata = iio_priv(indio_dev);62 63 /* Get the time stamp as close in time as possible */64 sdata->hw_timestamp = iio_get_time_ns(indio_dev);65 return IRQ_WAKE_THREAD;66}67 68/**69 * st_sensors_irq_thread() - bottom half of the IRQ-based triggers70 * @irq: irq number71 * @p: private handler data72 */73static irqreturn_t st_sensors_irq_thread(int irq, void *p)74{75 struct iio_trigger *trig = p;76 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);77 struct st_sensor_data *sdata = iio_priv(indio_dev);78 79 /*80 * If this trigger is backed by a hardware interrupt and we have a81 * status register, check if this IRQ came from us. Notice that82 * we will process also if st_sensors_new_samples_available()83 * returns negative: if we can't check status, then poll84 * unconditionally.85 */86 if (sdata->hw_irq_trigger &&87 st_sensors_new_samples_available(indio_dev, sdata)) {88 iio_trigger_poll_nested(p);89 } else {90 dev_dbg(indio_dev->dev.parent, "spurious IRQ\n");91 return IRQ_NONE;92 }93 94 /*95 * If we have proper level IRQs the handler will be re-entered if96 * the line is still active, so return here and come back in through97 * the top half if need be.98 */99 if (!sdata->edge_irq)100 return IRQ_HANDLED;101 102 /*103 * If we are using edge IRQs, new samples arrived while processing104 * the IRQ and those may be missed unless we pick them here, so poll105 * again. If the sensor delivery frequency is very high, this thread106 * turns into a polled loop handler.107 */108 while (sdata->hw_irq_trigger &&109 st_sensors_new_samples_available(indio_dev, sdata)) {110 dev_dbg(indio_dev->dev.parent,111 "more samples came in during polling\n");112 sdata->hw_timestamp = iio_get_time_ns(indio_dev);113 iio_trigger_poll_nested(p);114 }115 116 return IRQ_HANDLED;117}118 119int st_sensors_allocate_trigger(struct iio_dev *indio_dev,120 const struct iio_trigger_ops *trigger_ops)121{122 struct st_sensor_data *sdata = iio_priv(indio_dev);123 struct device *parent = indio_dev->dev.parent;124 unsigned long irq_trig;125 int err;126 127 sdata->trig = devm_iio_trigger_alloc(parent, "%s-trigger",128 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 137 irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq));138 /*139 * If the IRQ is triggered on falling edge, we need to mark the140 * interrupt as active low, if the hardware supports this.141 */142 switch(irq_trig) {143 case IRQF_TRIGGER_FALLING:144 case IRQF_TRIGGER_LOW:145 if (!sdata->sensor_settings->drdy_irq.addr_ihl) {146 dev_err(&indio_dev->dev,147 "falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n");148 if (irq_trig == IRQF_TRIGGER_FALLING)149 irq_trig = IRQF_TRIGGER_RISING;150 if (irq_trig == IRQF_TRIGGER_LOW)151 irq_trig = IRQF_TRIGGER_HIGH;152 } else {153 /* Set up INT active low i.e. falling edge */154 err = st_sensors_write_data_with_mask(indio_dev,155 sdata->sensor_settings->drdy_irq.addr_ihl,156 sdata->sensor_settings->drdy_irq.mask_ihl, 1);157 if (err < 0)158 return err;159 dev_info(&indio_dev->dev,160 "interrupts on the falling edge or active low level\n");161 }162 break;163 case IRQF_TRIGGER_RISING:164 dev_info(&indio_dev->dev,165 "interrupts on the rising edge\n");166 break;167 case IRQF_TRIGGER_HIGH:168 dev_info(&indio_dev->dev,169 "interrupts active high level\n");170 break;171 default:172 /* This is the most preferred mode, if possible */173 dev_err(&indio_dev->dev,174 "unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig);175 irq_trig = IRQF_TRIGGER_RISING;176 }177 178 /* Tell the interrupt handler that we're dealing with edges */179 if (irq_trig == IRQF_TRIGGER_FALLING ||180 irq_trig == IRQF_TRIGGER_RISING) {181 if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) {182 dev_err(&indio_dev->dev,183 "edge IRQ not supported w/o stat register.\n");184 return -EOPNOTSUPP;185 }186 sdata->edge_irq = true;187 } else {188 /*189 * If we're not using edges (i.e. level interrupts) we190 * just mask off the IRQ, handle one interrupt, then191 * if the line is still low, we return to the192 * interrupt handler top half again and start over.193 */194 irq_trig |= IRQF_ONESHOT;195 }196 197 /*198 * If the interrupt pin is Open Drain, by definition this199 * means that the interrupt line may be shared with other200 * peripherals. But to do this we also need to have a status201 * register and mask to figure out if this sensor was firing202 * the IRQ or not, so we can tell the interrupt handle that203 * it was "our" interrupt.204 */205 if (sdata->int_pin_open_drain &&206 sdata->sensor_settings->drdy_irq.stat_drdy.addr)207 irq_trig |= IRQF_SHARED;208 209 err = devm_request_threaded_irq(parent,210 sdata->irq,211 st_sensors_irq_handler,212 st_sensors_irq_thread,213 irq_trig,214 sdata->trig->name,215 sdata->trig);216 if (err) {217 dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n");218 return err;219 }220 221 err = devm_iio_trigger_register(parent, sdata->trig);222 if (err < 0) {223 dev_err(&indio_dev->dev, "failed to register iio trigger.\n");224 return err;225 }226 indio_dev->trig = iio_trigger_get(sdata->trig);227 228 return 0;229}230EXPORT_SYMBOL_NS(st_sensors_allocate_trigger, IIO_ST_SENSORS);231 232int st_sensors_validate_device(struct iio_trigger *trig,233 struct iio_dev *indio_dev)234{235 struct iio_dev *indio = iio_trigger_get_drvdata(trig);236 237 if (indio != indio_dev)238 return -EINVAL;239 240 return 0;241}242EXPORT_SYMBOL_NS(st_sensors_validate_device, IIO_ST_SENSORS);243