diff options
author | Johan Hovold <johan@kernel.org> | 2019-01-22 18:22:53 +0100 |
---|---|---|
committer | Johan Hovold <johan@kernel.org> | 2019-01-25 10:58:52 +0100 |
commit | 82f844c22588bf47132c82faeda50b6db473162c (patch) | |
tree | 5042e51ce950d2bee376ae0a658d0684454d3552 /drivers | |
parent | 49a57857aeea06ca831043acbb0fa5e0f50602fd (diff) | |
download | linux-82f844c22588bf47132c82faeda50b6db473162c.tar.gz linux-82f844c22588bf47132c82faeda50b6db473162c.tar.bz2 linux-82f844c22588bf47132c82faeda50b6db473162c.zip |
gnss: sirf: fix premature wakeup interrupt enable
Make sure the receiver is powered (and booted) before enabling the
wakeup interrupt to avoid spurious interrupts due to a floating input.
Similarly, disable the interrupt before powering off on probe errors and
on unbind.
Fixes: d2efbbd18b1e ("gnss: add driver for sirfstar-based receivers")
Cc: stable <stable@vger.kernel.org> # 4.19
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gnss/sirf.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/drivers/gnss/sirf.c b/drivers/gnss/sirf.c index 226f6e6fe01b..8e3f6a776e02 100644 --- a/drivers/gnss/sirf.c +++ b/drivers/gnss/sirf.c @@ -310,30 +310,26 @@ static int sirf_probe(struct serdev_device *serdev) ret = -ENODEV; goto err_put_device; } + + ret = regulator_enable(data->vcc); + if (ret) + goto err_put_device; + + /* Wait for chip to boot into hibernate mode. */ + msleep(SIRF_BOOT_DELAY); } if (data->wakeup) { ret = gpiod_to_irq(data->wakeup); if (ret < 0) - goto err_put_device; - + goto err_disable_vcc; data->irq = ret; - ret = devm_request_threaded_irq(dev, data->irq, NULL, - sirf_wakeup_handler, + ret = request_threaded_irq(data->irq, NULL, sirf_wakeup_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "wakeup", data); if (ret) - goto err_put_device; - } - - if (data->on_off) { - ret = regulator_enable(data->vcc); - if (ret) - goto err_put_device; - - /* Wait for chip to boot into hibernate mode */ - msleep(SIRF_BOOT_DELAY); + goto err_disable_vcc; } if (IS_ENABLED(CONFIG_PM)) { @@ -342,7 +338,7 @@ static int sirf_probe(struct serdev_device *serdev) } else { ret = sirf_runtime_resume(dev); if (ret < 0) - goto err_disable_vcc; + goto err_free_irq; } ret = gnss_register_device(gdev); @@ -356,6 +352,9 @@ err_disable_rpm: pm_runtime_disable(dev); else sirf_runtime_suspend(dev); +err_free_irq: + if (data->wakeup) + free_irq(data->irq, data); err_disable_vcc: if (data->on_off) regulator_disable(data->vcc); @@ -376,6 +375,9 @@ static void sirf_remove(struct serdev_device *serdev) else sirf_runtime_suspend(&serdev->dev); + if (data->wakeup) + free_irq(data->irq, data); + if (data->on_off) regulator_disable(data->vcc); |