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