Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging:iio:dummy Add event support + fake event generator

The event generator is not very pretty but does the job and
allows this driver to look a lot more like a normal driver
than it otherwise would.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Jonathan Cameron and committed by
Greg Kroah-Hartman
e6477000 3a84331d

+543 -26
+17 -3
drivers/staging/iio/Kconfig
··· 70 70 source "drivers/staging/iio/resolver/Kconfig" 71 71 source "drivers/staging/iio/trigger/Kconfig" 72 72 73 + config IIO_DUMMY_EVGEN 74 + tristate 75 + 73 76 config IIO_SIMPLE_DUMMY 74 77 tristate "An example driver with no hardware requirements" 78 + select IIO_SIMPLE_DUMMY_EVGEN if IIO_SIMPLE_DUMMY_EVENTS 75 79 help 76 - Driver intended mainly as documentation for how to write 77 - a driver. May also be useful for testing userspace code 78 - without hardward. 80 + Driver intended mainly as documentation for how to write 81 + a driver. May also be useful for testing userspace code 82 + without hardward. 79 83 84 + if IIO_SIMPLE_DUMMY 85 + 86 + config IIO_SIMPLE_DUMMY_EVENTS 87 + boolean "Event generation support" 88 + select IIO_DUMMY_EVGEN 89 + help 90 + Add some dummy events to the simple dummy driver. 91 + 92 + 93 + endif # IIO_SIMPLE_DUMMY 80 94 81 95 endif # IIO
+5 -1
drivers/staging/iio/Makefile
··· 10 10 obj-$(CONFIG_IIO_SW_RING) += ring_sw.o 11 11 obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o 12 12 13 - obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_simple_dummy.o 13 + obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o 14 + iio_dummy-y := iio_simple_dummy.o 15 + iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o 16 + 17 + obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o 14 18 15 19 obj-y += accel/ 16 20 obj-y += adc/
+217
drivers/staging/iio/iio_dummy_evgen.c
··· 1 + /** 2 + * Copyright (c) 2011 Jonathan Cameron 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * Companion module to the iio simple dummy example driver. 9 + * The purpose of this is to generate 'fake' event interrupts thus 10 + * allowing that driver's code to be as close as possible to that of 11 + * a normal driver talking to hardware. The approach used here 12 + * is not intended to be general and just happens to work for this 13 + * particular use case. 14 + */ 15 + 16 + #include <linux/kernel.h> 17 + #include <linux/slab.h> 18 + #include <linux/interrupt.h> 19 + #include <linux/irq.h> 20 + #include <linux/mutex.h> 21 + #include <linux/module.h> 22 + #include <linux/sysfs.h> 23 + 24 + #include "iio_dummy_evgen.h" 25 + #include "iio.h" 26 + #include "sysfs.h" 27 + 28 + /* Fiddly bit of faking and irq without hardware */ 29 + #define IIO_EVENTGEN_NO 10 30 + /** 31 + * struct iio_dummy_evgen - evgen state 32 + * @chip: irq chip we are faking 33 + * @base: base of irq range 34 + * @enabled: mask of which irqs are enabled 35 + * @inuse: mask of which irqs actually have anyone connected 36 + * @lock: protect the evgen state 37 + */ 38 + struct iio_dummy_eventgen { 39 + struct irq_chip chip; 40 + int base; 41 + bool enabled[IIO_EVENTGEN_NO]; 42 + bool inuse[IIO_EVENTGEN_NO]; 43 + struct mutex lock; 44 + }; 45 + 46 + /* We can only ever have one instance of this 'device' */ 47 + static struct iio_dummy_eventgen *iio_evgen; 48 + static const char *iio_evgen_name = "iio_dummy_evgen"; 49 + 50 + static void iio_dummy_event_irqmask(struct irq_data *d) 51 + { 52 + struct irq_chip *chip = irq_data_get_irq_chip(d); 53 + struct iio_dummy_eventgen *evgen = 54 + container_of(chip, struct iio_dummy_eventgen, chip); 55 + 56 + evgen->enabled[d->irq - evgen->base] = false; 57 + } 58 + 59 + static void iio_dummy_event_irqunmask(struct irq_data *d) 60 + { 61 + struct irq_chip *chip = irq_data_get_irq_chip(d); 62 + struct iio_dummy_eventgen *evgen = 63 + container_of(chip, struct iio_dummy_eventgen, chip); 64 + 65 + evgen->enabled[d->irq - evgen->base] = true; 66 + } 67 + 68 + static int iio_dummy_evgen_create(void) 69 + { 70 + int ret, i; 71 + 72 + iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL); 73 + if (iio_evgen == NULL) 74 + return -ENOMEM; 75 + 76 + iio_evgen->base = irq_alloc_descs(-1, 0, IIO_EVENTGEN_NO, 0); 77 + if (iio_evgen->base < 0) { 78 + ret = iio_evgen->base; 79 + kfree(iio_evgen); 80 + return ret; 81 + } 82 + iio_evgen->chip.name = iio_evgen_name; 83 + iio_evgen->chip.irq_mask = &iio_dummy_event_irqmask; 84 + iio_evgen->chip.irq_unmask = &iio_dummy_event_irqunmask; 85 + for (i = 0; i < IIO_EVENTGEN_NO; i++) { 86 + irq_set_chip(iio_evgen->base + i, &iio_evgen->chip); 87 + irq_set_handler(iio_evgen->base + i, &handle_simple_irq); 88 + irq_modify_status(iio_evgen->base + i, 89 + IRQ_NOREQUEST | IRQ_NOAUTOEN, 90 + IRQ_NOPROBE); 91 + } 92 + mutex_init(&iio_evgen->lock); 93 + return 0; 94 + } 95 + 96 + /** 97 + * iio_dummy_evgen_get_irq() - get an evgen provided irq for a device 98 + * 99 + * This function will give a free allocated irq to a client device. 100 + * That irq can then be caused to 'fire' by using the associated sysfs file. 101 + */ 102 + int iio_dummy_evgen_get_irq(void) 103 + { 104 + int i, ret = 0; 105 + mutex_lock(&iio_evgen->lock); 106 + for (i = 0; i < IIO_EVENTGEN_NO; i++) 107 + if (iio_evgen->inuse[i] == false) { 108 + ret = iio_evgen->base + i; 109 + iio_evgen->inuse[i] = true; 110 + break; 111 + } 112 + mutex_unlock(&iio_evgen->lock); 113 + if (i == IIO_EVENTGEN_NO) 114 + return -ENOMEM; 115 + return ret; 116 + } 117 + EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq); 118 + 119 + /** 120 + * iio_dummy_evgen_release_irq() - give the irq back. 121 + * @irq: irq being returned to the pool 122 + * 123 + * Used by client driver instances to give the irqs back when they disconnect 124 + */ 125 + int iio_dummy_evgen_release_irq(int irq) 126 + { 127 + mutex_lock(&iio_evgen->lock); 128 + iio_evgen->inuse[irq - iio_evgen->base] = false; 129 + mutex_unlock(&iio_evgen->lock); 130 + 131 + return 0; 132 + } 133 + EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq); 134 + 135 + static void iio_dummy_evgen_free(void) 136 + { 137 + irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO); 138 + kfree(iio_evgen); 139 + } 140 + 141 + static void iio_evgen_release(struct device *dev) 142 + { 143 + iio_dummy_evgen_free(); 144 + } 145 + 146 + static ssize_t iio_evgen_poke(struct device *dev, 147 + struct device_attribute *attr, 148 + const char *buf, 149 + size_t len) 150 + { 151 + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 152 + 153 + if (iio_evgen->enabled[this_attr->address]) 154 + handle_nested_irq(iio_evgen->base + this_attr->address); 155 + 156 + return len; 157 + } 158 + 159 + static IIO_DEVICE_ATTR(poke_ev0, S_IWUSR, NULL, &iio_evgen_poke, 0); 160 + static IIO_DEVICE_ATTR(poke_ev1, S_IWUSR, NULL, &iio_evgen_poke, 1); 161 + static IIO_DEVICE_ATTR(poke_ev2, S_IWUSR, NULL, &iio_evgen_poke, 2); 162 + static IIO_DEVICE_ATTR(poke_ev3, S_IWUSR, NULL, &iio_evgen_poke, 3); 163 + static IIO_DEVICE_ATTR(poke_ev4, S_IWUSR, NULL, &iio_evgen_poke, 4); 164 + static IIO_DEVICE_ATTR(poke_ev5, S_IWUSR, NULL, &iio_evgen_poke, 5); 165 + static IIO_DEVICE_ATTR(poke_ev6, S_IWUSR, NULL, &iio_evgen_poke, 6); 166 + static IIO_DEVICE_ATTR(poke_ev7, S_IWUSR, NULL, &iio_evgen_poke, 7); 167 + static IIO_DEVICE_ATTR(poke_ev8, S_IWUSR, NULL, &iio_evgen_poke, 8); 168 + static IIO_DEVICE_ATTR(poke_ev9, S_IWUSR, NULL, &iio_evgen_poke, 9); 169 + 170 + static struct attribute *iio_evgen_attrs[] = { 171 + &iio_dev_attr_poke_ev0.dev_attr.attr, 172 + &iio_dev_attr_poke_ev1.dev_attr.attr, 173 + &iio_dev_attr_poke_ev2.dev_attr.attr, 174 + &iio_dev_attr_poke_ev3.dev_attr.attr, 175 + &iio_dev_attr_poke_ev4.dev_attr.attr, 176 + &iio_dev_attr_poke_ev5.dev_attr.attr, 177 + &iio_dev_attr_poke_ev6.dev_attr.attr, 178 + &iio_dev_attr_poke_ev7.dev_attr.attr, 179 + &iio_dev_attr_poke_ev8.dev_attr.attr, 180 + &iio_dev_attr_poke_ev9.dev_attr.attr, 181 + NULL, 182 + }; 183 + 184 + static const struct attribute_group iio_evgen_group = { 185 + .attrs = iio_evgen_attrs, 186 + }; 187 + 188 + static const struct attribute_group *iio_evgen_groups[] = { 189 + &iio_evgen_group, 190 + NULL 191 + }; 192 + 193 + static struct device iio_evgen_dev = { 194 + .bus = &iio_bus_type, 195 + .groups = iio_evgen_groups, 196 + .release = &iio_evgen_release, 197 + }; 198 + static __init int iio_dummy_evgen_init(void) 199 + { 200 + int ret = iio_dummy_evgen_create(); 201 + if (ret < 0) 202 + return ret; 203 + device_initialize(&iio_evgen_dev); 204 + dev_set_name(&iio_evgen_dev, "iio_evgen"); 205 + return device_add(&iio_evgen_dev); 206 + } 207 + module_init(iio_dummy_evgen_init); 208 + 209 + static __exit void iio_dummy_evgen_exit(void) 210 + { 211 + device_unregister(&iio_evgen_dev); 212 + } 213 + module_exit(iio_dummy_evgen_exit); 214 + 215 + MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); 216 + MODULE_DESCRIPTION("IIO dummy driver"); 217 + MODULE_LICENSE("GPL v2");
+2
drivers/staging/iio/iio_dummy_evgen.h
··· 1 + int iio_dummy_evgen_get_irq(void); 2 + int iio_dummy_evgen_release_irq(int irq);
+31 -22
drivers/staging/iio/iio_simple_dummy.c
··· 20 20 #include <linux/moduleparam.h> 21 21 22 22 #include "iio.h" 23 + #include "sysfs.h" 24 + #include "iio_simple_dummy.h" 23 25 24 26 /* 25 27 * A few elements needed to fake a bus for this driver ··· 55 53 { 733, 13, 0x9 }, /* 733.00013 */ 56 54 }; 57 55 58 - /** 59 - * struct iio_dummy_state - device instance specific state. 60 - * @dac_val: cache for dac value 61 - * @single_ended_adc_val: cache for single ended adc value 62 - * @differential_adc_val: cache for differential adc value 63 - * @accel_val: cache for acceleration value 64 - * @accel_calibbias: cache for acceleration calibbias 65 - * @accel_calibscale: cache for acceleration calibscale 66 - * @lock: lock to ensure state is consistent 67 - */ 68 - struct iio_dummy_state { 69 - int dac_val; 70 - int single_ended_adc_val; 71 - int differential_adc_val[2]; 72 - int accel_val; 73 - int accel_calibbias; 74 - const struct iio_dummy_accel_calibscale *accel_calibscale; 75 - struct mutex lock; 76 - }; 77 - 78 56 /* 79 57 * iio_dummy_channels - Description of available channels 80 58 * ··· 83 101 */ 84 102 (1 << IIO_CHAN_INFO_SCALE_SEPARATE), 85 103 104 + #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 105 + /* 106 + * simple event - triggered when value rises above 107 + * a threshold 108 + */ 109 + .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, 110 + IIO_EV_DIR_RISING), 111 + #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 86 112 }, 87 113 /* Differential ADC channel in_voltage1-voltage2_raw etc*/ 88 114 { ··· 286 296 .driver_module = THIS_MODULE, 287 297 .read_raw = &iio_dummy_read_raw, 288 298 .write_raw = &iio_dummy_write_raw, 299 + #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 300 + .read_event_config = &iio_simple_dummy_read_event_config, 301 + .write_event_config = &iio_simple_dummy_write_event_config, 302 + .read_event_value = &iio_simple_dummy_read_event_value, 303 + .write_event_value = &iio_simple_dummy_write_event_value, 304 + #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 289 305 }; 290 306 291 307 /** ··· 388 392 /* Specify that device provides sysfs type interfaces */ 389 393 indio_dev->modes = INDIO_DIRECT_MODE; 390 394 391 - ret = iio_device_register(indio_dev); 395 + ret = iio_simple_dummy_events_register(indio_dev); 392 396 if (ret < 0) 393 397 goto error_free_device; 398 + ret = iio_device_register(indio_dev); 399 + if (ret < 0) 400 + goto error_unregister_events; 394 401 395 402 return 0; 403 + error_unregister_events: 404 + iio_simple_dummy_events_unregister(indio_dev); 396 405 error_free_device: 397 406 /* Note free device should only be called, before registration 398 407 * has succeeded. */ ··· 414 413 */ 415 414 static int iio_dummy_remove(int index) 416 415 { 416 + int ret; 417 417 /* 418 418 * Get a pointer to the device instance iio_dev structure 419 419 * from the bus subsystem. E.g. ··· 423 421 */ 424 422 struct iio_dev *indio_dev = iio_dummy_devs[index]; 425 423 424 + 426 425 /* Unregister the device */ 427 426 iio_device_unregister(indio_dev); 428 427 429 428 /* Device specific code to power down etc */ 430 429 430 + 431 + ret = iio_simple_dummy_events_unregister(indio_dev); 432 + if (ret) 433 + goto error_ret; 434 + 431 435 /* Free all structures */ 432 436 iio_free_device(indio_dev); 433 437 434 - return 0; 438 + error_ret: 439 + return ret; 435 440 } 436 441 437 442 /**
+81
drivers/staging/iio/iio_simple_dummy.h
··· 1 + /** 2 + * Copyright (c) 2011 Jonathan Cameron 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * Join together the various functionality of iio_simple_dummy driver 9 + */ 10 + 11 + #include <linux/kernel.h> 12 + 13 + struct iio_dummy_accel_calibscale; 14 + 15 + /** 16 + * struct iio_dummy_state - device instance specific state. 17 + * @dac_val: cache for dac value 18 + * @single_ended_adc_val: cache for single ended adc value 19 + * @differential_adc_val: cache for differential adc value 20 + * @accel_val: cache for acceleration value 21 + * @accel_calibbias: cache for acceleration calibbias 22 + * @accel_calibscale: cache for acceleration calibscale 23 + * @lock: lock to ensure state is consistent 24 + * @event_irq: irq number for event line (faked) 25 + * @event_val: cache for event theshold value 26 + * @event_en: cache of whether event is enabled 27 + */ 28 + struct iio_dummy_state { 29 + int dac_val; 30 + int single_ended_adc_val; 31 + int differential_adc_val[2]; 32 + int accel_val; 33 + int accel_calibbias; 34 + const struct iio_dummy_accel_calibscale *accel_calibscale; 35 + struct mutex lock; 36 + #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 37 + int event_irq; 38 + int event_val; 39 + bool event_en; 40 + #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ 41 + }; 42 + 43 + #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS 44 + 45 + struct iio_dev; 46 + 47 + int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, 48 + u64 event_code); 49 + 50 + int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, 51 + u64 event_code, 52 + int state); 53 + 54 + int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, 55 + u64 event_code, 56 + int *val); 57 + 58 + int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, 59 + u64 event_code, 60 + int val); 61 + 62 + int iio_simple_dummy_events_register(struct iio_dev *indio_dev); 63 + int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev); 64 + 65 + #else /* Stubs for when events are disabled at compile time */ 66 + 67 + static inline int 68 + iio_simple_dummy_events_register(struct iio_dev *indio_dev) 69 + { 70 + return 0; 71 + }; 72 + 73 + static inline int 74 + iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) 75 + { 76 + return 0; 77 + }; 78 + 79 + #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS*/ 80 + 81 +
+190
drivers/staging/iio/iio_simple_dummy_events.c
··· 1 + /** 2 + * Copyright (c) 2011 Jonathan Cameron 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * Event handling elements of industrial I/O reference driver. 9 + */ 10 + #include <linux/kernel.h> 11 + #include <linux/slab.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/irq.h> 14 + 15 + #include "iio.h" 16 + #include "sysfs.h" 17 + #include "iio_simple_dummy.h" 18 + 19 + /* Evgen 'fakes' interrupt events for this example */ 20 + #include "iio_dummy_evgen.h" 21 + 22 + /** 23 + * iio_simple_dummy_read_event_config() - is event enabled? 24 + * @indio_dev: the device instance data 25 + * @event_code: event code of the event 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 + */ 30 + int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev, 31 + u64 event_code) 32 + { 33 + struct iio_dummy_state *st = iio_priv(indio_dev); 34 + 35 + return st->event_en; 36 + } 37 + 38 + /** 39 + * iio_simple_dummy_write_event_config() - set whether event is enabled 40 + * @indio_dev: the device instance data 41 + * @event_code: event code of event being enabled/disabled 42 + * @state: whether to enable or disable the device. 43 + * 44 + * This function would normally set the relevant registers on the devices 45 + * so that it generates the specified event. Here it just sets up a cached 46 + * value. 47 + */ 48 + int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, 49 + u64 event_code, 50 + int state) 51 + { 52 + struct iio_dummy_state *st = iio_priv(indio_dev); 53 + 54 + /* 55 + * Deliberately over the top code splitting to illustrate 56 + * how this is done when multiple events exist. 57 + */ 58 + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { 59 + case IIO_VOLTAGE: 60 + switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) { 61 + case IIO_EV_TYPE_THRESH: 62 + if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == 63 + IIO_EV_DIR_RISING) 64 + st->event_en = state; 65 + else 66 + return -EINVAL; 67 + break; 68 + default: 69 + return -EINVAL; 70 + } 71 + default: 72 + return -EINVAL; 73 + } 74 + 75 + return 0; 76 + } 77 + 78 + /** 79 + * iio_simple_dummy_read_event_value() - get value associated with event 80 + * @indio_dev: device instance specific data 81 + * @event_code: event code for the event whose value is being queried 82 + * @val: value for the event code. 83 + * 84 + * Many devices provide a large set of events of which only a subset may 85 + * be enabled at a time, with value registers whose meaning changes depending 86 + * on the event enabled. This often means that the driver must cache the values 87 + * associated with each possible events so that the right value is in place when 88 + * the enabled event is changed. 89 + */ 90 + int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, 91 + u64 event_code, 92 + int *val) 93 + { 94 + struct iio_dummy_state *st = iio_priv(indio_dev); 95 + 96 + *val = st->event_val; 97 + 98 + return 0; 99 + } 100 + 101 + /** 102 + * iio_simple_dummy_write_event_value() - set value associate with event 103 + * @indio_dev: device instance specific data 104 + * @event_code: event code for the event whose value is being set 105 + * @val: the value to be set. 106 + */ 107 + int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, 108 + u64 event_code, 109 + int val) 110 + { 111 + struct iio_dummy_state *st = iio_priv(indio_dev); 112 + 113 + st->event_val = val; 114 + 115 + return 0; 116 + } 117 + 118 + /** 119 + * iio_simple_dummy_event_handler() - identify and pass on event 120 + * @irq: irq of event line 121 + * @private: pointer to device instance state. 122 + * 123 + * This handler is responsible for querying the device to find out what 124 + * event occured and for then pushing that event towards userspace. 125 + * Here only one event occurs so we push that directly on with locally 126 + * grabbed timestamp. 127 + */ 128 + static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) 129 + { 130 + struct iio_dev *indio_dev = private; 131 + iio_push_event(indio_dev, 132 + IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, 133 + IIO_EV_DIR_RISING, 134 + IIO_EV_TYPE_THRESH, 0, 0, 0), 135 + iio_get_time_ns()); 136 + return IRQ_HANDLED; 137 + } 138 + 139 + /** 140 + * iio_simple_dummy_events_register() - setup interrupt handling for events 141 + * @indio_dev: device instance data 142 + * 143 + * This function requests the threaded interrupt to handle the events. 144 + * Normally the irq is a hardware interrupt and the number comes 145 + * from board configuration files. Here we get it from a companion 146 + * module that fakes the interrupt for us. Note that module in 147 + * no way forms part of this example. Just assume that events magically 148 + * appear via the provided interrupt. 149 + */ 150 + int iio_simple_dummy_events_register(struct iio_dev *indio_dev) 151 + { 152 + struct iio_dummy_state *st = iio_priv(indio_dev); 153 + int ret; 154 + 155 + /* Fire up event source - normally not present */ 156 + st->event_irq = iio_dummy_evgen_get_irq(); 157 + if (st->event_irq < 0) { 158 + ret = st->event_irq; 159 + goto error_ret; 160 + } 161 + ret = request_threaded_irq(st->event_irq, 162 + NULL, 163 + &iio_simple_dummy_event_handler, 164 + IRQF_ONESHOT, 165 + "iio_simple_event", 166 + indio_dev); 167 + if (ret < 0) 168 + goto error_free_evgen; 169 + return 0; 170 + 171 + error_free_evgen: 172 + iio_dummy_evgen_release_irq(st->event_irq); 173 + error_ret: 174 + return ret; 175 + } 176 + 177 + /** 178 + * iio_simple_dummy_events_unregister() - tidy up interrupt handling on remove 179 + * @indio_dev: device instance data 180 + */ 181 + int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev) 182 + { 183 + struct iio_dummy_state *st = iio_priv(indio_dev); 184 + 185 + free_irq(st->event_irq, indio_dev); 186 + /* Not part of normal driver */ 187 + iio_dummy_evgen_release_irq(st->event_irq); 188 + 189 + return 0; 190 + }