summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/mxs-auart.c46
1 files changed, 39 insertions, 7 deletions
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 7dc87a9e4bff..8d1cd158ca24 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -858,6 +858,30 @@ static void mxs_auart_reset_deassert(struct uart_port *u)
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
}
+static void mxs_auart_reset_assert(struct uart_port *u)
+{
+ int i;
+ u32 reg;
+
+ reg = readl(u->membase + AUART_CTRL0);
+ /* if already in reset state, keep it untouched */
+ if (reg & AUART_CTRL0_SFTRST)
+ return;
+
+ writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+ writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_SET);
+
+ for (i = 0; i < 1000; i++) {
+ reg = readl(u->membase + AUART_CTRL0);
+ /* reset is finished when the clock is gated */
+ if (reg & AUART_CTRL0_CLKGATE)
+ return;
+ udelay(10);
+ }
+
+ dev_err(u->dev, "Failed to reset the unit.");
+}
+
static int mxs_auart_startup(struct uart_port *u)
{
int ret;
@@ -867,7 +891,13 @@ static int mxs_auart_startup(struct uart_port *u)
if (ret)
return ret;
- writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+ if (uart_console(u)) {
+ writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+ } else {
+ /* reset the unit to a well known state */
+ mxs_auart_reset_assert(u);
+ mxs_auart_reset_deassert(u);
+ }
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
@@ -899,12 +929,14 @@ static void mxs_auart_shutdown(struct uart_port *u)
if (auart_dma_enabled(s))
mxs_auart_dma_exit(s);
- writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
-
- writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
- u->membase + AUART_INTR_CLR);
-
- writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+ if (uart_console(u)) {
+ writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
+ writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
+ u->membase + AUART_INTR_CLR);
+ writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+ } else {
+ mxs_auart_reset_assert(u);
+ }
clk_disable_unprepare(s->clk);
}