1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Common library for ADIS16XXX devices |
4 | * |
5 | * Copyright 2012 Analog Devices Inc. |
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> |
7 | */ |
8 | |
9 | #include <linux/interrupt.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/spi/spi.h> |
12 | #include <linux/export.h> |
13 | |
14 | #include <linux/iio/iio.h> |
15 | #include <linux/iio/trigger.h> |
16 | #include <linux/iio/imu/adis.h> |
17 | |
18 | static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) |
19 | { |
20 | struct adis *adis = iio_trigger_get_drvdata(trig); |
21 | |
22 | return adis_enable_irq(adis, enable: state); |
23 | } |
24 | |
25 | static const struct iio_trigger_ops adis_trigger_ops = { |
26 | .set_trigger_state = &adis_data_rdy_trigger_set_state, |
27 | }; |
28 | |
29 | static int adis_validate_irq_flag(struct adis *adis) |
30 | { |
31 | unsigned long direction = adis->irq_flag & IRQF_TRIGGER_MASK; |
32 | |
33 | /* We cannot mask the interrupt so ensure it's not enabled at request */ |
34 | if (adis->data->unmasked_drdy) |
35 | adis->irq_flag |= IRQF_NO_AUTOEN; |
36 | /* |
37 | * Typically this devices have data ready either on the rising edge or |
38 | * on the falling edge of the data ready pin. This checks enforces that |
39 | * one of those is set in the drivers... It defaults to |
40 | * IRQF_TRIGGER_RISING for backward compatibility with devices that |
41 | * don't support changing the pin polarity. |
42 | */ |
43 | if (direction == IRQF_TRIGGER_NONE) { |
44 | adis->irq_flag |= IRQF_TRIGGER_RISING; |
45 | return 0; |
46 | } else if (direction != IRQF_TRIGGER_RISING && |
47 | direction != IRQF_TRIGGER_FALLING) { |
48 | dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n" , |
49 | adis->irq_flag); |
50 | return -EINVAL; |
51 | } |
52 | |
53 | return 0; |
54 | } |
55 | |
56 | /** |
57 | * devm_adis_probe_trigger() - Sets up trigger for a managed adis device |
58 | * @adis: The adis device |
59 | * @indio_dev: The IIO device |
60 | * |
61 | * Returns 0 on success or a negative error code |
62 | */ |
63 | int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) |
64 | { |
65 | int ret; |
66 | |
67 | adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d" , |
68 | indio_dev->name, |
69 | iio_device_id(indio_dev)); |
70 | if (!adis->trig) |
71 | return -ENOMEM; |
72 | |
73 | adis->trig->ops = &adis_trigger_ops; |
74 | iio_trigger_set_drvdata(trig: adis->trig, data: adis); |
75 | |
76 | ret = adis_validate_irq_flag(adis); |
77 | if (ret) |
78 | return ret; |
79 | |
80 | ret = devm_request_irq(dev: &adis->spi->dev, irq: adis->spi->irq, |
81 | handler: &iio_trigger_generic_data_rdy_poll, |
82 | irqflags: adis->irq_flag, |
83 | devname: indio_dev->name, |
84 | dev_id: adis->trig); |
85 | if (ret) |
86 | return ret; |
87 | |
88 | return devm_iio_trigger_register(dev: &adis->spi->dev, trig_info: adis->trig); |
89 | } |
90 | EXPORT_SYMBOL_NS_GPL(devm_adis_probe_trigger, IIO_ADISLIB); |
91 | |
92 | |