Commit | Line | Data |
---|---|---|
930bae86 | 1 | /* |
d4fd73bf | 2 | * Industrial I/O - generic interrupt based trigger support |
930bae86 | 3 | * |
d4fd73bf | 4 | * Copyright (c) 2008-2013 Jonathan Cameron |
930bae86 JC |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License version 2 as published by | |
8 | * the Free Software Foundation. | |
930bae86 JC |
9 | */ |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/platform_device.h> | |
14 | #include <linux/interrupt.h> | |
5a0e3ad6 | 15 | #include <linux/slab.h> |
930bae86 | 16 | |
06458e27 JC |
17 | #include <linux/iio/iio.h> |
18 | #include <linux/iio/trigger.h> | |
930bae86 | 19 | |
930bae86 | 20 | |
d4fd73bf | 21 | struct iio_interrupt_trigger_info { |
a05d7ce3 | 22 | unsigned int irq; |
930bae86 | 23 | }; |
930bae86 | 24 | |
d4fd73bf | 25 | static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private) |
930bae86 | 26 | { |
398fd22b | 27 | iio_trigger_poll(private); |
930bae86 JC |
28 | return IRQ_HANDLED; |
29 | } | |
30 | ||
d4fd73bf | 31 | static const struct iio_trigger_ops iio_interrupt_trigger_ops = { |
d29f73db JC |
32 | .owner = THIS_MODULE, |
33 | }; | |
34 | ||
d4fd73bf | 35 | static int iio_interrupt_trigger_probe(struct platform_device *pdev) |
930bae86 | 36 | { |
d4fd73bf | 37 | struct iio_interrupt_trigger_info *trig_info; |
3c1e02db | 38 | struct iio_trigger *trig; |
a05d7ce3 MH |
39 | unsigned long irqflags; |
40 | struct resource *irq_res; | |
3c1e02db | 41 | int irq, ret = 0; |
930bae86 | 42 | |
3c1e02db JC |
43 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
44 | ||
45 | if (irq_res == NULL) | |
46 | return -ENODEV; | |
47 | ||
48 | irqflags = (irq_res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED; | |
49 | ||
50 | irq = irq_res->start; | |
51 | ||
78f304d0 | 52 | trig = iio_trigger_alloc("irqtrig%d", irq); |
3c1e02db JC |
53 | if (!trig) { |
54 | ret = -ENOMEM; | |
55 | goto error_ret; | |
56 | } | |
57 | ||
58 | trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); | |
59 | if (!trig_info) { | |
60 | ret = -ENOMEM; | |
61 | goto error_put_trigger; | |
62 | } | |
63 | iio_trigger_set_drvdata(trig, trig_info); | |
64 | trig_info->irq = irq; | |
65 | trig->ops = &iio_interrupt_trigger_ops; | |
66 | ret = request_irq(irq, iio_interrupt_trigger_poll, | |
67 | irqflags, trig->name, trig); | |
68 | if (ret) { | |
69 | dev_err(&pdev->dev, | |
70 | "request IRQ-%d failed", irq); | |
71 | goto error_free_trig_info; | |
72 | } | |
73 | ||
74 | ret = iio_trigger_register(trig); | |
75 | if (ret) | |
76 | goto error_release_irq; | |
77 | platform_set_drvdata(pdev, trig); | |
930bae86 | 78 | |
930bae86 JC |
79 | return 0; |
80 | ||
81 | /* First clean up the partly allocated trigger */ | |
82 | error_release_irq: | |
83 | free_irq(irq, trig); | |
930bae86 JC |
84 | error_free_trig_info: |
85 | kfree(trig_info); | |
86 | error_put_trigger: | |
7cbb7537 | 87 | iio_trigger_put(trig); |
3c1e02db | 88 | error_ret: |
930bae86 JC |
89 | return ret; |
90 | } | |
91 | ||
d4fd73bf | 92 | static int iio_interrupt_trigger_remove(struct platform_device *pdev) |
930bae86 | 93 | { |
3c1e02db | 94 | struct iio_trigger *trig; |
d4fd73bf | 95 | struct iio_interrupt_trigger_info *trig_info; |
930bae86 | 96 | |
3c1e02db JC |
97 | trig = platform_get_drvdata(pdev); |
98 | trig_info = iio_trigger_get_drvdata(trig); | |
99 | iio_trigger_unregister(trig); | |
100 | free_irq(trig_info->irq, trig); | |
101 | kfree(trig_info); | |
102 | iio_trigger_put(trig); | |
930bae86 JC |
103 | |
104 | return 0; | |
105 | } | |
106 | ||
d4fd73bf JC |
107 | static struct platform_driver iio_interrupt_trigger_driver = { |
108 | .probe = iio_interrupt_trigger_probe, | |
109 | .remove = iio_interrupt_trigger_remove, | |
930bae86 | 110 | .driver = { |
d4fd73bf | 111 | .name = "iio_interrupt_trigger", |
930bae86 JC |
112 | }, |
113 | }; | |
114 | ||
d4fd73bf | 115 | module_platform_driver(iio_interrupt_trigger_driver); |
930bae86 | 116 | |
0f8c9620 | 117 | MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); |
d4fd73bf | 118 | MODULE_DESCRIPTION("Interrupt trigger for the iio subsystem"); |
930bae86 | 119 | MODULE_LICENSE("GPL v2"); |