summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>2021-07-13 12:18:35 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-07-21 12:46:52 +0200
commit5bbe10a6942d668a63bfcb69c8ffdd0660db10f5 (patch)
treedb9ffd979f1191d80aa19fc0d331d28c35070cfa
parented623dffdeebcc0acac7be6af4a301ee7169cd21 (diff)
downloadlinux-stable-5bbe10a6942d668a63bfcb69c8ffdd0660db10f5.tar.gz
linux-stable-5bbe10a6942d668a63bfcb69c8ffdd0660db10f5.tar.bz2
linux-stable-5bbe10a6942d668a63bfcb69c8ffdd0660db10f5.zip
tty: serial: uartlite: Add runtime pm support
In the commit 07e5d4ff125a ("Revert serial-uartlite: Add runtime support") the runtime pm support was reverted to aid reverting of the other patches. This patch adds the runtime PM support back. The runtime pm calls are used to gate and enable the clocks. Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com> Link: https://lore.kernel.org/r/20210713064835.27978-3-shubhrajyoti.datta@xilinx.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/uartlite.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 0376c8607e89..047099b14cee 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -22,6 +22,7 @@
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#define ULITE_NAME "ttyUL"
#define ULITE_MAJOR 204
@@ -54,6 +55,7 @@
#define ULITE_CONTROL_RST_TX 0x01
#define ULITE_CONTROL_RST_RX 0x02
#define ULITE_CONTROL_IE 0x10
+#define UART_AUTOSUSPEND_TIMEOUT 3000 /* ms */
/* Static pointer to console port */
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
@@ -390,12 +392,16 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
static void ulite_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- struct uartlite_data *pdata = port->private_data;
+ int ret;
- if (!state)
- clk_enable(pdata->clk);
- else
- clk_disable(pdata->clk);
+ if (!state) {
+ ret = pm_runtime_get_sync(port->dev);
+ if (ret < 0)
+ dev_err(port->dev, "Failed to enable clocks\n");
+ } else {
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
+ }
}
#ifdef CONFIG_CONSOLE_POLL
@@ -719,11 +725,38 @@ static int __maybe_unused ulite_resume(struct device *dev)
return 0;
}
+static int __maybe_unused ulite_runtime_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
+
+ clk_disable(pdata->clk);
+ return 0;
+};
+
+static int __maybe_unused ulite_runtime_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
+ int ret;
+
+ ret = clk_enable(pdata->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock.\n");
+ return ret;
+ }
+ return 0;
+}
+
/* ---------------------------------------------------------------------
* Platform bus binding
*/
-static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume);
+static const struct dev_pm_ops ulite_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume)
+ SET_RUNTIME_PM_OPS(ulite_runtime_suspend,
+ ulite_runtime_resume, NULL)
+};
#if defined(CONFIG_OF)
/* Match table for of_platform binding */
@@ -779,6 +812,11 @@ static int ulite_probe(struct platform_device *pdev)
return ret;
}
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
if (!ulite_uart_driver.state) {
dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
ret = uart_register_driver(&ulite_uart_driver);
@@ -791,7 +829,8 @@ static int ulite_probe(struct platform_device *pdev)
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
- clk_disable(pdata->clk);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
return ret;
}
@@ -800,9 +839,14 @@ static int ulite_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
struct uartlite_data *pdata = port->private_data;
+ int rc;
clk_disable_unprepare(pdata->clk);
- return ulite_release(&pdev->dev);
+ rc = ulite_release(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ return rc;
}
/* work with hotplug and coldplug */