cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iio_simple_dummy_events.c (7873B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2011 Jonathan Cameron
      4 *
      5 * Event handling elements of industrial I/O reference driver.
      6 */
      7#include <linux/kernel.h>
      8#include <linux/slab.h>
      9#include <linux/interrupt.h>
     10#include <linux/irq.h>
     11
     12#include <linux/iio/iio.h>
     13#include <linux/iio/sysfs.h>
     14#include <linux/iio/events.h>
     15#include "iio_simple_dummy.h"
     16
     17/* Evgen 'fakes' interrupt events for this example */
     18#include "iio_dummy_evgen.h"
     19
     20/**
     21 * iio_simple_dummy_read_event_config() - is event enabled?
     22 * @indio_dev: the device instance data
     23 * @chan: channel for the event whose state is being queried
     24 * @type: type of the event whose state is being queried
     25 * @dir: direction of the vent whose state is being queried
     26 *
     27 * This function would normally query the relevant registers or a cache to
     28 * discover if the event generation is enabled on the device.
     29 */
     30int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev,
     31				       const struct iio_chan_spec *chan,
     32				       enum iio_event_type type,
     33				       enum iio_event_direction dir)
     34{
     35	struct iio_dummy_state *st = iio_priv(indio_dev);
     36
     37	return st->event_en;
     38}
     39
     40/**
     41 * iio_simple_dummy_write_event_config() - set whether event is enabled
     42 * @indio_dev: the device instance data
     43 * @chan: channel for the event whose state is being set
     44 * @type: type of the event whose state is being set
     45 * @dir: direction of the vent whose state is being set
     46 * @state: whether to enable or disable the device.
     47 *
     48 * This function would normally set the relevant registers on the devices
     49 * so that it generates the specified event. Here it just sets up a cached
     50 * value.
     51 */
     52int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
     53					const struct iio_chan_spec *chan,
     54					enum iio_event_type type,
     55					enum iio_event_direction dir,
     56					int state)
     57{
     58	struct iio_dummy_state *st = iio_priv(indio_dev);
     59
     60	/*
     61	 *  Deliberately over the top code splitting to illustrate
     62	 * how this is done when multiple events exist.
     63	 */
     64	switch (chan->type) {
     65	case IIO_VOLTAGE:
     66		switch (type) {
     67		case IIO_EV_TYPE_THRESH:
     68			if (dir == IIO_EV_DIR_RISING)
     69				st->event_en = state;
     70			else
     71				return -EINVAL;
     72			break;
     73		default:
     74			return -EINVAL;
     75		}
     76		break;
     77	case IIO_ACTIVITY:
     78		switch (type) {
     79		case IIO_EV_TYPE_THRESH:
     80			st->event_en = state;
     81			break;
     82		default:
     83			return -EINVAL;
     84		}
     85		break;
     86	case IIO_STEPS:
     87		switch (type) {
     88		case IIO_EV_TYPE_CHANGE:
     89			st->event_en = state;
     90			break;
     91		default:
     92			return -EINVAL;
     93		}
     94		break;
     95	default:
     96		return -EINVAL;
     97	}
     98
     99	return 0;
    100}
    101
    102/**
    103 * iio_simple_dummy_read_event_value() - get value associated with event
    104 * @indio_dev: device instance specific data
    105 * @chan: channel for the event whose value is being read
    106 * @type: type of the event whose value is being read
    107 * @dir: direction of the vent whose value is being read
    108 * @info: info type of the event whose value is being read
    109 * @val: value for the event code.
    110 * @val2: unused
    111 *
    112 * Many devices provide a large set of events of which only a subset may
    113 * be enabled at a time, with value registers whose meaning changes depending
    114 * on the event enabled. This often means that the driver must cache the values
    115 * associated with each possible events so that the right value is in place when
    116 * the enabled event is changed.
    117 */
    118int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
    119				      const struct iio_chan_spec *chan,
    120				      enum iio_event_type type,
    121				      enum iio_event_direction dir,
    122				      enum iio_event_info info,
    123				      int *val, int *val2)
    124{
    125	struct iio_dummy_state *st = iio_priv(indio_dev);
    126
    127	*val = st->event_val;
    128
    129	return IIO_VAL_INT;
    130}
    131
    132/**
    133 * iio_simple_dummy_write_event_value() - set value associate with event
    134 * @indio_dev: device instance specific data
    135 * @chan: channel for the event whose value is being set
    136 * @type: type of the event whose value is being set
    137 * @dir: direction of the vent whose value is being set
    138 * @info: info type of the event whose value is being set
    139 * @val: the value to be set.
    140 * @val2: unused
    141 */
    142int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
    143				       const struct iio_chan_spec *chan,
    144				       enum iio_event_type type,
    145				       enum iio_event_direction dir,
    146				       enum iio_event_info info,
    147				       int val, int val2)
    148{
    149	struct iio_dummy_state *st = iio_priv(indio_dev);
    150
    151	st->event_val = val;
    152
    153	return 0;
    154}
    155
    156static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private)
    157{
    158	struct iio_dev *indio_dev = private;
    159	struct iio_dummy_state *st = iio_priv(indio_dev);
    160
    161	st->event_timestamp = iio_get_time_ns(indio_dev);
    162	return IRQ_WAKE_THREAD;
    163}
    164
    165/**
    166 * iio_simple_dummy_event_handler() - identify and pass on event
    167 * @irq: irq of event line
    168 * @private: pointer to device instance state.
    169 *
    170 * This handler is responsible for querying the device to find out what
    171 * event occurred and for then pushing that event towards userspace.
    172 * Here only one event occurs so we push that directly on with locally
    173 * grabbed timestamp.
    174 */
    175static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private)
    176{
    177	struct iio_dev *indio_dev = private;
    178	struct iio_dummy_state *st = iio_priv(indio_dev);
    179
    180	dev_dbg(&indio_dev->dev, "id %x event %x\n",
    181		st->regs->reg_id, st->regs->reg_data);
    182
    183	switch (st->regs->reg_data) {
    184	case 0:
    185		iio_push_event(indio_dev,
    186			       IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
    187					      IIO_EV_DIR_RISING,
    188					      IIO_EV_TYPE_THRESH, 0, 0, 0),
    189			       st->event_timestamp);
    190		break;
    191	case 1:
    192		if (st->activity_running > st->event_val)
    193			iio_push_event(indio_dev,
    194				       IIO_EVENT_CODE(IIO_ACTIVITY, 0,
    195						      IIO_MOD_RUNNING,
    196						      IIO_EV_DIR_RISING,
    197						      IIO_EV_TYPE_THRESH,
    198						      0, 0, 0),
    199				       st->event_timestamp);
    200		break;
    201	case 2:
    202		if (st->activity_walking < st->event_val)
    203			iio_push_event(indio_dev,
    204				       IIO_EVENT_CODE(IIO_ACTIVITY, 0,
    205						      IIO_MOD_WALKING,
    206						      IIO_EV_DIR_FALLING,
    207						      IIO_EV_TYPE_THRESH,
    208						      0, 0, 0),
    209				       st->event_timestamp);
    210		break;
    211	case 3:
    212		iio_push_event(indio_dev,
    213			       IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
    214					      IIO_EV_DIR_NONE,
    215					      IIO_EV_TYPE_CHANGE, 0, 0, 0),
    216			       st->event_timestamp);
    217		break;
    218	default:
    219		break;
    220	}
    221
    222	return IRQ_HANDLED;
    223}
    224
    225/**
    226 * iio_simple_dummy_events_register() - setup interrupt handling for events
    227 * @indio_dev: device instance data
    228 *
    229 * This function requests the threaded interrupt to handle the events.
    230 * Normally the irq is a hardware interrupt and the number comes
    231 * from board configuration files.  Here we get it from a companion
    232 * module that fakes the interrupt for us. Note that module in
    233 * no way forms part of this example. Just assume that events magically
    234 * appear via the provided interrupt.
    235 */
    236int iio_simple_dummy_events_register(struct iio_dev *indio_dev)
    237{
    238	struct iio_dummy_state *st = iio_priv(indio_dev);
    239	int ret;
    240
    241	/* Fire up event source - normally not present */
    242	st->event_irq = iio_dummy_evgen_get_irq();
    243	if (st->event_irq < 0) {
    244		ret = st->event_irq;
    245		goto error_ret;
    246	}
    247	st->regs = iio_dummy_evgen_get_regs(st->event_irq);
    248
    249	ret = request_threaded_irq(st->event_irq,
    250				   &iio_simple_dummy_get_timestamp,
    251				   &iio_simple_dummy_event_handler,
    252				   IRQF_ONESHOT,
    253				   "iio_simple_event",
    254				   indio_dev);
    255	if (ret < 0)
    256		goto error_free_evgen;
    257	return 0;
    258
    259error_free_evgen:
    260	iio_dummy_evgen_release_irq(st->event_irq);
    261error_ret:
    262	return ret;
    263}
    264
    265/**
    266 * iio_simple_dummy_events_unregister() - tidy up interrupt handling on remove
    267 * @indio_dev: device instance data
    268 */
    269void iio_simple_dummy_events_unregister(struct iio_dev *indio_dev)
    270{
    271	struct iio_dummy_state *st = iio_priv(indio_dev);
    272
    273	free_irq(st->event_irq, indio_dev);
    274	/* Not part of normal driver */
    275	iio_dummy_evgen_release_irq(st->event_irq);
    276}