Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2011 Jonathan Cameron
0004  *
0005  * Event handling elements of industrial I/O reference driver.
0006  */
0007 #include <linux/kernel.h>
0008 #include <linux/slab.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/irq.h>
0011 
0012 #include <linux/iio/iio.h>
0013 #include <linux/iio/sysfs.h>
0014 #include <linux/iio/events.h>
0015 #include "iio_simple_dummy.h"
0016 
0017 /* Evgen 'fakes' interrupt events for this example */
0018 #include "iio_dummy_evgen.h"
0019 
0020 /**
0021  * iio_simple_dummy_read_event_config() - is event enabled?
0022  * @indio_dev: the device instance data
0023  * @chan: channel for the event whose state is being queried
0024  * @type: type of the event whose state is being queried
0025  * @dir: direction of the vent whose state is being queried
0026  *
0027  * This function would normally query the relevant registers or a cache to
0028  * discover if the event generation is enabled on the device.
0029  */
0030 int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev,
0031                        const struct iio_chan_spec *chan,
0032                        enum iio_event_type type,
0033                        enum iio_event_direction dir)
0034 {
0035     struct iio_dummy_state *st = iio_priv(indio_dev);
0036 
0037     return st->event_en;
0038 }
0039 
0040 /**
0041  * iio_simple_dummy_write_event_config() - set whether event is enabled
0042  * @indio_dev: the device instance data
0043  * @chan: channel for the event whose state is being set
0044  * @type: type of the event whose state is being set
0045  * @dir: direction of the vent whose state is being set
0046  * @state: whether to enable or disable the device.
0047  *
0048  * This function would normally set the relevant registers on the devices
0049  * so that it generates the specified event. Here it just sets up a cached
0050  * value.
0051  */
0052 int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
0053                     const struct iio_chan_spec *chan,
0054                     enum iio_event_type type,
0055                     enum iio_event_direction dir,
0056                     int state)
0057 {
0058     struct iio_dummy_state *st = iio_priv(indio_dev);
0059 
0060     /*
0061      *  Deliberately over the top code splitting to illustrate
0062      * how this is done when multiple events exist.
0063      */
0064     switch (chan->type) {
0065     case IIO_VOLTAGE:
0066         switch (type) {
0067         case IIO_EV_TYPE_THRESH:
0068             if (dir == IIO_EV_DIR_RISING)
0069                 st->event_en = state;
0070             else
0071                 return -EINVAL;
0072             break;
0073         default:
0074             return -EINVAL;
0075         }
0076         break;
0077     case IIO_ACTIVITY:
0078         switch (type) {
0079         case IIO_EV_TYPE_THRESH:
0080             st->event_en = state;
0081             break;
0082         default:
0083             return -EINVAL;
0084         }
0085         break;
0086     case IIO_STEPS:
0087         switch (type) {
0088         case IIO_EV_TYPE_CHANGE:
0089             st->event_en = state;
0090             break;
0091         default:
0092             return -EINVAL;
0093         }
0094         break;
0095     default:
0096         return -EINVAL;
0097     }
0098 
0099     return 0;
0100 }
0101 
0102 /**
0103  * iio_simple_dummy_read_event_value() - get value associated with event
0104  * @indio_dev: device instance specific data
0105  * @chan: channel for the event whose value is being read
0106  * @type: type of the event whose value is being read
0107  * @dir: direction of the vent whose value is being read
0108  * @info: info type of the event whose value is being read
0109  * @val: value for the event code.
0110  * @val2: unused
0111  *
0112  * Many devices provide a large set of events of which only a subset may
0113  * be enabled at a time, with value registers whose meaning changes depending
0114  * on the event enabled. This often means that the driver must cache the values
0115  * associated with each possible events so that the right value is in place when
0116  * the enabled event is changed.
0117  */
0118 int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
0119                       const struct iio_chan_spec *chan,
0120                       enum iio_event_type type,
0121                       enum iio_event_direction dir,
0122                       enum iio_event_info info,
0123                       int *val, int *val2)
0124 {
0125     struct iio_dummy_state *st = iio_priv(indio_dev);
0126 
0127     *val = st->event_val;
0128 
0129     return IIO_VAL_INT;
0130 }
0131 
0132 /**
0133  * iio_simple_dummy_write_event_value() - set value associate with event
0134  * @indio_dev: device instance specific data
0135  * @chan: channel for the event whose value is being set
0136  * @type: type of the event whose value is being set
0137  * @dir: direction of the vent whose value is being set
0138  * @info: info type of the event whose value is being set
0139  * @val: the value to be set.
0140  * @val2: unused
0141  */
0142 int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
0143                        const struct iio_chan_spec *chan,
0144                        enum iio_event_type type,
0145                        enum iio_event_direction dir,
0146                        enum iio_event_info info,
0147                        int val, int val2)
0148 {
0149     struct iio_dummy_state *st = iio_priv(indio_dev);
0150 
0151     st->event_val = val;
0152 
0153     return 0;
0154 }
0155 
0156 static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private)
0157 {
0158     struct iio_dev *indio_dev = private;
0159     struct iio_dummy_state *st = iio_priv(indio_dev);
0160 
0161     st->event_timestamp = iio_get_time_ns(indio_dev);
0162     return IRQ_WAKE_THREAD;
0163 }
0164 
0165 /**
0166  * iio_simple_dummy_event_handler() - identify and pass on event
0167  * @irq: irq of event line
0168  * @private: pointer to device instance state.
0169  *
0170  * This handler is responsible for querying the device to find out what
0171  * event occurred and for then pushing that event towards userspace.
0172  * Here only one event occurs so we push that directly on with locally
0173  * grabbed timestamp.
0174  */
0175 static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private)
0176 {
0177     struct iio_dev *indio_dev = private;
0178     struct iio_dummy_state *st = iio_priv(indio_dev);
0179 
0180     dev_dbg(&indio_dev->dev, "id %x event %x\n",
0181         st->regs->reg_id, st->regs->reg_data);
0182 
0183     switch (st->regs->reg_data) {
0184     case 0:
0185         iio_push_event(indio_dev,
0186                    IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
0187                           IIO_EV_DIR_RISING,
0188                           IIO_EV_TYPE_THRESH, 0, 0, 0),
0189                    st->event_timestamp);
0190         break;
0191     case 1:
0192         if (st->activity_running > st->event_val)
0193             iio_push_event(indio_dev,
0194                        IIO_EVENT_CODE(IIO_ACTIVITY, 0,
0195                               IIO_MOD_RUNNING,
0196                               IIO_EV_DIR_RISING,
0197                               IIO_EV_TYPE_THRESH,
0198                               0, 0, 0),
0199                        st->event_timestamp);
0200         break;
0201     case 2:
0202         if (st->activity_walking < st->event_val)
0203             iio_push_event(indio_dev,
0204                        IIO_EVENT_CODE(IIO_ACTIVITY, 0,
0205                               IIO_MOD_WALKING,
0206                               IIO_EV_DIR_FALLING,
0207                               IIO_EV_TYPE_THRESH,
0208                               0, 0, 0),
0209                        st->event_timestamp);
0210         break;
0211     case 3:
0212         iio_push_event(indio_dev,
0213                    IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
0214                           IIO_EV_DIR_NONE,
0215                           IIO_EV_TYPE_CHANGE, 0, 0, 0),
0216                    st->event_timestamp);
0217         break;
0218     default:
0219         break;
0220     }
0221 
0222     return IRQ_HANDLED;
0223 }
0224 
0225 /**
0226  * iio_simple_dummy_events_register() - setup interrupt handling for events
0227  * @indio_dev: device instance data
0228  *
0229  * This function requests the threaded interrupt to handle the events.
0230  * Normally the irq is a hardware interrupt and the number comes
0231  * from board configuration files.  Here we get it from a companion
0232  * module that fakes the interrupt for us. Note that module in
0233  * no way forms part of this example. Just assume that events magically
0234  * appear via the provided interrupt.
0235  */
0236 int iio_simple_dummy_events_register(struct iio_dev *indio_dev)
0237 {
0238     struct iio_dummy_state *st = iio_priv(indio_dev);
0239     int ret;
0240 
0241     /* Fire up event source - normally not present */
0242     st->event_irq = iio_dummy_evgen_get_irq();
0243     if (st->event_irq < 0) {
0244         ret = st->event_irq;
0245         goto error_ret;
0246     }
0247     st->regs = iio_dummy_evgen_get_regs(st->event_irq);
0248 
0249     ret = request_threaded_irq(st->event_irq,
0250                    &iio_simple_dummy_get_timestamp,
0251                    &iio_simple_dummy_event_handler,
0252                    IRQF_ONESHOT,
0253                    "iio_simple_event",
0254                    indio_dev);
0255     if (ret < 0)
0256         goto error_free_evgen;
0257     return 0;
0258 
0259 error_free_evgen:
0260     iio_dummy_evgen_release_irq(st->event_irq);
0261 error_ret:
0262     return ret;
0263 }
0264 
0265 /**
0266  * iio_simple_dummy_events_unregister() - tidy up interrupt handling on remove
0267  * @indio_dev: device instance data
0268  */
0269 void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev)
0270 {
0271     struct iio_dummy_state *st = iio_priv(indio_dev);
0272 
0273     free_irq(st->event_irq, indio_dev);
0274     /* Not part of normal driver */
0275     iio_dummy_evgen_release_irq(st->event_irq);
0276 }