linux/drivers/staging/iio/meter/ade7758_trigger.c
<<
>>
Prefs
   1/*
   2 * ADE7758 Poly Phase Multifunction Energy Metering IC driver
   3 *
   4 * Copyright 2010-2011 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2.
   7 */
   8
   9#include <linux/interrupt.h>
  10#include <linux/kernel.h>
  11#include <linux/spi/spi.h>
  12#include <linux/export.h>
  13
  14#include <linux/iio/iio.h>
  15#include <linux/iio/trigger.h>
  16#include "ade7758.h"
  17
  18/**
  19 * ade7758_data_rdy_trig_poll() the event handler for the data rdy trig
  20 **/
  21static irqreturn_t ade7758_data_rdy_trig_poll(int irq, void *private)
  22{
  23        disable_irq_nosync(irq);
  24        iio_trigger_poll(private);
  25
  26        return IRQ_HANDLED;
  27}
  28
  29/**
  30 * ade7758_data_rdy_trigger_set_state() set datardy interrupt state
  31 **/
  32static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig,
  33                                                bool state)
  34{
  35        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
  36
  37        dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
  38        return ade7758_set_irq(&indio_dev->dev, state);
  39}
  40
  41/**
  42 * ade7758_trig_try_reen() try renabling irq for data rdy trigger
  43 * @trig:       the datardy trigger
  44 **/
  45static int ade7758_trig_try_reen(struct iio_trigger *trig)
  46{
  47        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
  48        struct ade7758_state *st = iio_priv(indio_dev);
  49
  50        enable_irq(st->us->irq);
  51        /* irq reenabled so success! */
  52        return 0;
  53}
  54
  55static const struct iio_trigger_ops ade7758_trigger_ops = {
  56        .owner = THIS_MODULE,
  57        .set_trigger_state = &ade7758_data_rdy_trigger_set_state,
  58        .try_reenable = &ade7758_trig_try_reen,
  59};
  60
  61int ade7758_probe_trigger(struct iio_dev *indio_dev)
  62{
  63        struct ade7758_state *st = iio_priv(indio_dev);
  64        int ret;
  65
  66        st->trig = iio_trigger_alloc("%s-dev%d",
  67                                        spi_get_device_id(st->us)->name,
  68                                        indio_dev->id);
  69        if (!st->trig) {
  70                ret = -ENOMEM;
  71                goto error_ret;
  72        }
  73
  74        ret = request_irq(st->us->irq,
  75                          ade7758_data_rdy_trig_poll,
  76                          IRQF_TRIGGER_LOW,
  77                          spi_get_device_id(st->us)->name,
  78                          st->trig);
  79        if (ret)
  80                goto error_free_trig;
  81
  82        st->trig->dev.parent = &st->us->dev;
  83        st->trig->ops = &ade7758_trigger_ops;
  84        iio_trigger_set_drvdata(st->trig, indio_dev);
  85        ret = iio_trigger_register(st->trig);
  86
  87        /* select default trigger */
  88        indio_dev->trig = iio_trigger_get(st->trig);
  89        if (ret)
  90                goto error_free_irq;
  91
  92        return 0;
  93
  94error_free_irq:
  95        free_irq(st->us->irq, st->trig);
  96error_free_trig:
  97        iio_trigger_free(st->trig);
  98error_ret:
  99        return ret;
 100}
 101
 102void ade7758_remove_trigger(struct iio_dev *indio_dev)
 103{
 104        struct ade7758_state *st = iio_priv(indio_dev);
 105
 106        iio_trigger_unregister(st->trig);
 107        free_irq(st->us->irq, st->trig);
 108        iio_trigger_free(st->trig);
 109}
 110