diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2011-11-09 11:00:51 +0100 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@linaro.org> | 2012-03-19 08:51:06 +0100 |
commit | 992bfbe8fbb2cf3a3386f5b917c6137d30d00b62 (patch) | |
tree | 4490da44d7f5284839c6576397f446fcb19b5963 /drivers | |
parent | f98865e606ba4effa0dac3be61970b9b7b694012 (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>
Diffstat (limited to 'drivers')
-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 4f7d5cfda52..54e2383174d 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/io.h> +#include <linux/pm_runtime.h> #include <asm/sizes.h> @@ -1222,6 +1223,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); @@ -1235,6 +1237,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 @@ -1246,6 +1249,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 */ @@ -1276,6 +1281,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); @@ -1310,13 +1316,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; @@ -1325,6 +1334,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); @@ -1332,6 +1342,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; } @@ -1340,6 +1351,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 @@ -1369,12 +1382,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 @@ -2275,6 +2290,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; @@ -2288,12 +2307,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; } @@ -2305,6 +2318,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++) |