summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Aaberg <jonas.aberg@stericsson.com>2011-11-09 11:00:51 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:01:11 +0200
commitec0eb4b5a300afef03b256b78a5c2833db346dac (patch)
tree8740fdf8fe6b8737b44ba5994895411570aa19f7
parentfecc63f228ed0d11d6f4e3f2bec3d789fe5c4900 (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.c31
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++)