diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2011-11-09 11:00:51 +0100 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:01:11 +0200 |
commit | ec0eb4b5a300afef03b256b78a5c2833db346dac (patch) | |
tree | 8740fdf8fe6b8737b44ba5994895411570aa19f7 | |
parent | fecc63f228ed0d11d6f4e3f2bec3d789fe5c4900 (diff) |
drivers: serial: amba-pl011: Introduce runtime pm
ST-Ericsson Linux next: -
ST-Ericsson ID: 373766
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: Ie2a7719ca602abf3fbb3e4cef05adc4f7ab07035
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37021
Reviewed-by: QABUILD
Reviewed-by: Ulf HANSSON <ulf.hansson@stericsson.com>
-rw-r--r-- | drivers/tty/serial/amba-pl011.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 98da861fc8a..07d7081344e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -53,6 +53,7 @@ #include <linux/scatterlist.h> #include <linux/delay.h> #include <linux/types.h> +#include <linux/pm_runtime.h> #include <asm/io.h> #include <asm/sizes.h> @@ -1231,6 +1232,7 @@ static void pl011_clock_off(struct work_struct *work) struct circ_buf *xmit = &port->state->xmit; unsigned long flags; bool disable_regulator = false; + bool runtime_put = false; unsigned int busy, interrupt_status; spin_lock_irqsave(&port->lock, flags); @@ -1244,6 +1246,7 @@ static void pl011_clock_off(struct work_struct *work) pl011_backup(uap, true); disable_regulator = true; } + runtime_put = true; uap->clk_state = PL011_CLK_OFF; clk_disable(uap->clk); } else @@ -1255,6 +1258,8 @@ static void pl011_clock_off(struct work_struct *work) if (disable_regulator) regulator_disable(uap->regulator); + if (runtime_put) + pm_runtime_put_sync(uap->port.dev); } /* Request to turn off uart clock once pending TX is flushed */ @@ -1285,6 +1290,7 @@ static void pl011_clock_on(struct uart_port *port) switch (uap->clk_state) { case PL011_CLK_OFF: + pm_runtime_get_sync(uap->port.dev); clk_enable(uap->clk); if (!uart_console(&uap->port) && uap->regulator) { spin_unlock_irqrestore(&port->lock, flags); @@ -1319,13 +1325,16 @@ static int pl011_power_startup(struct uart_amba_port *uap) int retval = 0; if (uap->clk_state == PL011_PORT_OFF) { + pm_runtime_get_sync(uap->port.dev); if (!uart_console(&uap->port) && uap->regulator) regulator_enable(uap->regulator); retval = clk_enable(uap->clk); - if (!retval) + if (!retval) { uap->clk_state = PL011_CLK_ON; - else + } else { uap->clk_state = PL011_PORT_OFF; + pm_runtime_put_sync(uap->port.dev); + } } return retval; @@ -1334,6 +1343,7 @@ static int pl011_power_startup(struct uart_amba_port *uap) static void pl011_power_shutdown(struct uart_amba_port *uap) { bool disable_regulator = false; + bool runtime_put = false; cancel_delayed_work_sync(&uap->clk_off_work); @@ -1341,6 +1351,7 @@ static void pl011_power_shutdown(struct uart_amba_port *uap) if (uap->clk_state == PL011_CLK_ON || uap->clk_state == PL011_CLK_REQUEST_OFF) { clk_disable(uap->clk); + runtime_put = true; if (!uart_console(&uap->port) && uap->regulator) disable_regulator = true; } @@ -1349,6 +1360,8 @@ static void pl011_power_shutdown(struct uart_amba_port *uap) if (disable_regulator) regulator_disable(uap->regulator); + if (runtime_put) + pm_runtime_put_sync(uap->port.dev); } static void @@ -1378,12 +1391,14 @@ static inline void pl011_clock_check(struct uart_amba_port *uap) static inline int pl011_power_startup(struct uart_amba_port *uap) { + pm_runtime_get_sync(uap->port.dev); return clk_enable(uap->clk); } static inline void pl011_power_shutdown(struct uart_amba_port *uap) { clk_disable(uap->clk); + pm_runtime_put_sync(uap->port.dev); } static inline void @@ -2288,6 +2303,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) pl011_clock_control_init(uap); ret = uart_add_one_port(&amba_reg, &uap->port); + + if (!ret) + pm_runtime_put(&dev->dev); + if (ret) { amba_set_drvdata(dev, NULL); amba_ports[i] = NULL; @@ -2301,12 +2320,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) kfree(uap); } out: - /* - * Disable the silicon block pclk and any voltage domain and just - * power it up and clock it when it's needed - */ - amba_pclk_disable(dev); - amba_vcore_disable(dev); return ret; } @@ -2318,6 +2331,8 @@ static int pl011_remove(struct amba_device *dev) amba_set_drvdata(dev, NULL); + pm_runtime_get_sync(uap->port.dev); + uart_remove_one_port(&amba_reg, &uap->port); for (i = 0; i < ARRAY_SIZE(amba_ports); i++) |