Barry Song | a9d26f0 | 2010-05-04 14:43:15 +0100 | [diff] [blame^] | 1 | #include <linux/interrupt.h> |
| 2 | #include <linux/irq.h> |
| 3 | #include <linux/mutex.h> |
| 4 | #include <linux/device.h> |
| 5 | #include <linux/kernel.h> |
| 6 | #include <linux/sysfs.h> |
| 7 | #include <linux/list.h> |
| 8 | #include <linux/spi/spi.h> |
| 9 | |
| 10 | #include "../iio.h" |
| 11 | #include "../sysfs.h" |
| 12 | #include "../trigger.h" |
| 13 | #include "adis16400.h" |
| 14 | |
| 15 | /** |
| 16 | * adis16400_data_rdy_trig_poll() the event handler for the data rdy trig |
| 17 | **/ |
| 18 | static int adis16400_data_rdy_trig_poll(struct iio_dev *dev_info, |
| 19 | int index, |
| 20 | s64 timestamp, |
| 21 | int no_test) |
| 22 | { |
| 23 | struct adis16400_state *st = iio_dev_get_devdata(dev_info); |
| 24 | struct iio_trigger *trig = st->trig; |
| 25 | |
| 26 | trig->timestamp = timestamp; |
| 27 | iio_trigger_poll(trig); |
| 28 | |
| 29 | return IRQ_HANDLED; |
| 30 | } |
| 31 | |
| 32 | IIO_EVENT_SH(data_rdy_trig, &adis16400_data_rdy_trig_poll); |
| 33 | |
| 34 | static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); |
| 35 | |
| 36 | static struct attribute *adis16400_trigger_attrs[] = { |
| 37 | &dev_attr_name.attr, |
| 38 | NULL, |
| 39 | }; |
| 40 | |
| 41 | static const struct attribute_group adis16400_trigger_attr_group = { |
| 42 | .attrs = adis16400_trigger_attrs, |
| 43 | }; |
| 44 | |
| 45 | /** |
| 46 | * adis16400_data_rdy_trigger_set_state() set datardy interrupt state |
| 47 | **/ |
| 48 | static int adis16400_data_rdy_trigger_set_state(struct iio_trigger *trig, |
| 49 | bool state) |
| 50 | { |
| 51 | struct adis16400_state *st = trig->private_data; |
| 52 | struct iio_dev *indio_dev = st->indio_dev; |
| 53 | int ret = 0; |
| 54 | |
| 55 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); |
| 56 | ret = adis16400_set_irq(&st->indio_dev->dev, state); |
| 57 | if (state == false) { |
| 58 | iio_remove_event_from_list(&iio_event_data_rdy_trig, |
| 59 | &indio_dev->interrupts[0] |
| 60 | ->ev_list); |
| 61 | /* possible quirk with handler currently worked around |
| 62 | by ensuring the work queue is empty */ |
| 63 | flush_scheduled_work(); |
| 64 | } else { |
| 65 | iio_add_event_to_list(&iio_event_data_rdy_trig, |
| 66 | &indio_dev->interrupts[0]->ev_list); |
| 67 | } |
| 68 | return ret; |
| 69 | } |
| 70 | |
| 71 | /** |
| 72 | * adis16400_trig_try_reen() try renabling irq for data rdy trigger |
| 73 | * @trig: the datardy trigger |
| 74 | **/ |
| 75 | static int adis16400_trig_try_reen(struct iio_trigger *trig) |
| 76 | { |
| 77 | struct adis16400_state *st = trig->private_data; |
| 78 | enable_irq(st->us->irq); |
| 79 | /* irq reenabled so success! */ |
| 80 | return 0; |
| 81 | } |
| 82 | |
| 83 | int adis16400_probe_trigger(struct iio_dev *indio_dev) |
| 84 | { |
| 85 | int ret; |
| 86 | struct adis16400_state *st = indio_dev->dev_data; |
| 87 | |
| 88 | st->trig = iio_allocate_trigger(); |
| 89 | st->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL); |
| 90 | if (!st->trig->name) { |
| 91 | ret = -ENOMEM; |
| 92 | goto error_free_trig; |
| 93 | } |
| 94 | snprintf((char *)st->trig->name, |
| 95 | IIO_TRIGGER_NAME_LENGTH, |
| 96 | "adis16400-dev%d", indio_dev->id); |
| 97 | st->trig->dev.parent = &st->us->dev; |
| 98 | st->trig->owner = THIS_MODULE; |
| 99 | st->trig->private_data = st; |
| 100 | st->trig->set_trigger_state = &adis16400_data_rdy_trigger_set_state; |
| 101 | st->trig->try_reenable = &adis16400_trig_try_reen; |
| 102 | st->trig->control_attrs = &adis16400_trigger_attr_group; |
| 103 | ret = iio_trigger_register(st->trig); |
| 104 | |
| 105 | /* select default trigger */ |
| 106 | indio_dev->trig = st->trig; |
| 107 | if (ret) |
| 108 | goto error_free_trig_name; |
| 109 | |
| 110 | return 0; |
| 111 | |
| 112 | error_free_trig_name: |
| 113 | kfree(st->trig->name); |
| 114 | error_free_trig: |
| 115 | iio_free_trigger(st->trig); |
| 116 | |
| 117 | return ret; |
| 118 | } |
| 119 | |
| 120 | void adis16400_remove_trigger(struct iio_dev *indio_dev) |
| 121 | { |
| 122 | struct adis16400_state *state = indio_dev->dev_data; |
| 123 | |
| 124 | iio_trigger_unregister(state->trig); |
| 125 | kfree(state->trig->name); |
| 126 | iio_free_trigger(state->trig); |
| 127 | } |