1 From 82f844c22588bf47132c82faeda50b6db473162c Mon Sep 17 00:00:00 2001
2 From: Johan Hovold <johan@kernel.org>
3 Date: Tue, 22 Jan 2019 18:22:53 +0100
4 Subject: gnss: sirf: fix premature wakeup interrupt enable
6 From: Johan Hovold <johan@kernel.org>
8 commit 82f844c22588bf47132c82faeda50b6db473162c upstream.
10 Make sure the receiver is powered (and booted) before enabling the
11 wakeup interrupt to avoid spurious interrupts due to a floating input.
13 Similarly, disable the interrupt before powering off on probe errors and
16 Fixes: d2efbbd18b1e ("gnss: add driver for sirfstar-based receivers")
17 Cc: stable <stable@vger.kernel.org> # 4.19
18 Signed-off-by: Johan Hovold <johan@kernel.org>
19 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22 drivers/gnss/sirf.c | 32 +++++++++++++++++---------------
23 1 file changed, 17 insertions(+), 15 deletions(-)
25 --- a/drivers/gnss/sirf.c
26 +++ b/drivers/gnss/sirf.c
27 @@ -310,30 +310,26 @@ static int sirf_probe(struct serdev_devi
32 + ret = regulator_enable(data->vcc);
34 + goto err_put_device;
36 + /* Wait for chip to boot into hibernate mode. */
37 + msleep(SIRF_BOOT_DELAY);
41 ret = gpiod_to_irq(data->wakeup);
43 - goto err_put_device;
45 + goto err_disable_vcc;
48 - ret = devm_request_threaded_irq(dev, data->irq, NULL,
49 - sirf_wakeup_handler,
50 + ret = request_threaded_irq(data->irq, NULL, sirf_wakeup_handler,
51 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
54 - goto err_put_device;
58 - ret = regulator_enable(data->vcc);
60 - goto err_put_device;
62 - /* Wait for chip to boot into hibernate mode */
63 - msleep(SIRF_BOOT_DELAY);
64 + goto err_disable_vcc;
67 if (IS_ENABLED(CONFIG_PM)) {
68 @@ -342,7 +338,7 @@ static int sirf_probe(struct serdev_devi
70 ret = sirf_runtime_resume(dev);
72 - goto err_disable_vcc;
76 ret = gnss_register_device(gdev);
77 @@ -356,6 +352,9 @@ err_disable_rpm:
78 pm_runtime_disable(dev);
80 sirf_runtime_suspend(dev);
83 + free_irq(data->irq, data);
86 regulator_disable(data->vcc);
87 @@ -376,6 +375,9 @@ static void sirf_remove(struct serdev_de
89 sirf_runtime_suspend(&serdev->dev);
92 + free_irq(data->irq, data);
95 regulator_disable(data->vcc);