summaryrefslogtreecommitdiff
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorStefan Wahren <wahrenst@gmx.net>2024-08-18 20:49:36 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-09-03 11:47:42 +0300
commit2f102a5efe84808768a57ac2a5f1884bd56d62d8 (patch)
treefbfcde75e07900bf0609a3f194018a93ba27db27 /drivers/tty/serial
parentd2e8590fd1048c5c0dba160edc6a48ee8305a1f0 (diff)
downloadlinux-2f102a5efe84808768a57ac2a5f1884bd56d62d8.tar.xz
serial: 8250_bcm2835aux: Fix clock imbalance in PM resume
During review Ulf Hansson discovered a clock imbalance in the recently introduced PM resume code. The driver should enable the clock only in case it has been disabled in suspend before. In order to make the conditions easier to read, refactor this into a separate function. Reported-by: Ulf Hansson <ulf.hansson@linaro.org> Closes: https://lore.kernel.org/linux-arm-kernel/CAPDyKFoJh3j8xSeXZ9o031YZLTCDYVA+dgvURuwozjDpU_aauA@mail.gmail.com/ Fixes: 0e1d8780526f ("serial: 8250_bcm2835aux: add PM suspend/resume support") Signed-off-by: Stefan Wahren <wahrenst@gmx.net> Link: https://lore.kernel.org/r/20240818174936.88372-1-wahrenst@gmx.net Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/8250/8250_bcm2835aux.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
index 829abef2564d..d7a0f271263a 100644
--- a/drivers/tty/serial/8250/8250_bcm2835aux.c
+++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
@@ -214,17 +214,27 @@ static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);
-static int bcm2835aux_suspend(struct device *dev)
+static bool bcm2835aux_can_disable_clock(struct device *dev)
{
struct bcm2835aux_data *data = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(data->line);
- serial8250_suspend_port(data->line);
-
if (device_may_wakeup(dev))
- return 0;
+ return false;
if (uart_console(&up->port) && !console_suspend_enabled)
+ return false;
+
+ return true;
+}
+
+static int bcm2835aux_suspend(struct device *dev)
+{
+ struct bcm2835aux_data *data = dev_get_drvdata(dev);
+
+ serial8250_suspend_port(data->line);
+
+ if (!bcm2835aux_can_disable_clock(dev))
return 0;
clk_disable_unprepare(data->clk);
@@ -236,9 +246,11 @@ static int bcm2835aux_resume(struct device *dev)
struct bcm2835aux_data *data = dev_get_drvdata(dev);
int ret;
- ret = clk_prepare_enable(data->clk);
- if (ret)
- return ret;
+ if (bcm2835aux_can_disable_clock(dev)) {
+ ret = clk_prepare_enable(data->clk);
+ if (ret)
+ return ret;
+ }
serial8250_resume_port(data->line);