aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-03-05 12:39:12 +0530
committerHenrik hman <henrik.ohman@stericsson.com>2011-03-15 14:23:06 +0100
commit0754bb60108af169297c0b31444d473cdb162402 (patch)
tree8b8861389cda94579050e8a519f0df10028a73ef
parent95564202d60e489e1a494acfb47de2730e153def (diff)
downloadlinux-2.6.35-ux500-0754bb60108af169297c0b31444d473cdb162402.tar.gz
ux500/amba-pl011: fix UART backup for UART0
ST-Ericsson Linux next: - ST-Ericsson ID: 327057 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie527522083674cd94368e51f648a0b43c74c5bd6 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17675 Tested-by: Rabin VINCENT <rabin.vincent@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Tested-by: Lukasz RYMANOWSKI <lukasz.rymanowski@stericsson.com> Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/uart-db8500.c16
-rw-r--r--drivers/serial/amba-pl011.c69
2 files changed, 43 insertions, 42 deletions
diff --git a/arch/arm/mach-ux500/uart-db8500.c b/arch/arm/mach-ux500/uart-db8500.c
index 0fb6679c953..b3da7ad5287 100644
--- a/arch/arm/mach-ux500/uart-db8500.c
+++ b/arch/arm/mach-ux500/uart-db8500.c
@@ -78,14 +78,7 @@ static void save_uart(void)
int i;
for (i = 0; i < UX500_NR_UARTS; i++) {
- /*
- * No need to store the UART register values
- * for the port which is already disabled the clock
- * other than the console port.
- */
- context_uart[i].cr =
- readl(context_uart[i].base + UART011_CR);
- if ((!context_uart[i].cr) && (i != CONFIG_UX500_DEBUG_UART))
+ if (i != CONFIG_UX500_DEBUG_UART)
continue;
clk_enable(context_uart[i].uart_clk);
@@ -147,12 +140,7 @@ static void restore_uart(void)
int i, cnt;
for (i = 0; i < UX500_NR_UARTS; i++) {
- /*
- * No need to restore the UART register values
- * for the port which is already disabled the clock
- * other than the console port.
- */
- if ((!context_uart[i].cr) && (i != CONFIG_UX500_DEBUG_UART))
+ if (i != CONFIG_UX500_DEBUG_UART)
continue;
clk_enable(context_uart[i].uart_clk);
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index c4fee2e77e5..26e6766ea22 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -89,9 +89,10 @@ enum pl011_clk_states {
* Backup registers to be used during regulator startup/shutdown
*/
static const u32 backup_regs[] = {
+ UART011_IBRD,
+ UART011_FBRD,
ST_UART011_LCRH_RX,
ST_UART011_LCRH_TX,
- UART011_ICR,
UART011_CR,
UART011_IMSC,
};
@@ -143,15 +144,49 @@ static struct vendor_data vendor_st = {
.oversampling = true,
};
+static void __pl011_startup(struct uart_amba_port *uap)
+{
+ unsigned int cr;
+
+ writew(uap->ifls, uap->port.membase + UART011_IFLS);
+
+ /*
+ * Provoke TX FIFO interrupt into asserting.
+ */
+ cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
+ writew(cr, uap->port.membase + UART011_CR);
+ writew(0, uap->port.membase + UART011_FBRD);
+ writew(1, uap->port.membase + UART011_IBRD);
+ writew(0, uap->port.membase + uap->lcrh_rx);
+ if (uap->lcrh_tx != uap->lcrh_rx) {
+ int i;
+ /*
+ * Wait 10 PCLKs before writing LCRH_TX register,
+ * to get this delay write read only register 10 times
+ */
+ for (i = 0; i < 10; ++i)
+ writew(0xff, uap->port.membase + UART011_MIS);
+ writew(0, uap->port.membase + uap->lcrh_tx);
+ }
+ writew(0, uap->port.membase + UART01x_DR);
+ while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
+ barrier();
+}
+
/* Backup the registers during regulator startup/shutdown */
#ifdef CONFIG_SERIAL_AMBA_PL011_CLOCK_CONTROL
static int pl011_backup(struct uart_amba_port *uap, bool suspend)
{
int i, cnt;
+ if (!suspend) {
+ __pl011_startup(uap);
+ writew(0, uap->port.membase + UART011_CR);
+ }
+
for (i = 0; i < ARRAY_SIZE(backup_regs); i++) {
if (suspend)
- uap->backup[i] = readl(uap->port.membase +
+ uap->backup[i] = readw(uap->port.membase +
backup_regs[i]);
else {
if (backup_regs[i] == ST_UART011_LCRH_TX) {
@@ -165,7 +200,7 @@ static int pl011_backup(struct uart_amba_port *uap, bool suspend)
UART011_MIS);
}
- writel(uap->backup[i],
+ writew(uap->backup[i],
uap->port.membase + backup_regs[i]);
}
}
@@ -192,12 +227,12 @@ static void pl011_clock_off(struct work_struct *work)
if (uap->clk_state == PL011_CLK_REQUEST_OFF) {
if (uart_circ_empty(xmit) && !interrupt_status && !busy) {
- clk_disable(uap->clk);
if (!uart_console(&uap->port) && uap->regulator) {
pl011_backup(uap, true);
disable_regulator = true;
}
uap->clk_state = PL011_CLK_OFF;
+ clk_disable(uap->clk);
} else
schedule_delayed_work(&uap->clk_off_work,
uap->clk_off_delay);
@@ -237,13 +272,13 @@ static void pl011_clock_on(struct uart_port *port)
switch (uap->clk_state) {
case PL011_CLK_OFF:
+ clk_enable(uap->clk);
if (!uart_console(&uap->port) && uap->regulator) {
spin_unlock_irqrestore(&port->lock, flags);
regulator_enable(uap->regulator);
spin_lock_irqsave(&port->lock, flags);
pl011_backup(uap, false);
}
- clk_enable(uap->clk);
/* fallthrough */
case PL011_CLK_REQUEST_OFF:
cancel_delayed_work(&uap->clk_off_work);
@@ -645,29 +680,7 @@ static int pl011_startup(struct uart_port *port)
if (retval)
goto clk_dis;
- writew(uap->ifls, uap->port.membase + UART011_IFLS);
-
- /*
- * Provoke TX FIFO interrupt into asserting.
- */
- cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
- writew(cr, uap->port.membase + UART011_CR);
- writew(0, uap->port.membase + UART011_FBRD);
- writew(1, uap->port.membase + UART011_IBRD);
- writew(0, uap->port.membase + uap->lcrh_rx);
- if (uap->lcrh_tx != uap->lcrh_rx) {
- int i;
- /*
- * Wait 10 PCLKs before writing LCRH_TX register,
- * to get this delay write read only register 10 times
- */
- for (i = 0; i < 10; ++i)
- writew(0xff, uap->port.membase + UART011_MIS);
- writew(0, uap->port.membase + uap->lcrh_tx);
- }
- writew(0, uap->port.membase + UART01x_DR);
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
- barrier();
+ __pl011_startup(uap);
cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);