tty: serial: uartlite: Add runtime pm support

In the commit 07e5d4ff12 ("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>
This commit is contained in:
Shubhrajyoti Datta 2021-07-13 12:18:35 +05:30 коммит произвёл Greg Kroah-Hartman
Родитель ed623dffde
Коммит 5bbe10a694
1 изменённых файлов: 52 добавлений и 8 удалений

Просмотреть файл

@ -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 */