summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroshni.shah <roshni.shah@timesys.com>2013-06-30 10:10:19 -0400
committerAndy Voltz <andy.voltz@timesys.com>2013-07-26 01:30:24 -0400
commit6619f8df2dfe43d84587823a68b9e1c53233af71 (patch)
tree9e315d776037647a8428c27d5289b2a0e3fb98fd
parent3a915708a763387c608cf5041ceb0d7732c2820b (diff)
MVF Serial Driver Improvements to fix the sysvinit console hang issue.
-rw-r--r--drivers/tty/serial/mvf.c118
1 files changed, 52 insertions, 66 deletions
diff --git a/drivers/tty/serial/mvf.c b/drivers/tty/serial/mvf.c
index d57390172338..037d09e386dc 100644
--- a/drivers/tty/serial/mvf.c
+++ b/drivers/tty/serial/mvf.c
@@ -496,6 +496,7 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_RTS)
temp |= MXC_UARTMODEM_RXRTSE;
+
writeb(temp, sport->port.membase + MXC_UARTMODEM);
}
@@ -553,7 +554,6 @@ static int imx_setup_watermark(struct imx_port *sport, unsigned int mode)
/* restore CR2 */
writeb(old_cr2, sport->port.membase + MXC_UARTCR2);
-
return 0;
}
@@ -574,13 +574,6 @@ static int imx_startup(struct uart_port *port)
imx_setup_watermark(sport, 0);
#endif
- /* disable the DREN bit (Data Ready interrupt enable) before
- * requesting IRQs
- */
- temp = readb(sport->port.membase + MXC_UARTCR2);
-
- writeb(temp & ~MXC_UARTCR2_RIE, sport->port.membase + MXC_UARTCR2);
-
/*
* Allocate the IRQ(s)
* Vybrid chips only have one interrupt.
@@ -588,8 +581,7 @@ static int imx_startup(struct uart_port *port)
retval = request_irq(sport->port.irq, imx_int, 0,
DRIVER_NAME, sport);
if (retval) {
- free_irq(sport->port.irq, sport);
- goto error_out1;
+ return retval;
}
/* Enable the DMA ops for uart. */
@@ -614,11 +606,10 @@ static int imx_startup(struct uart_port *port)
spin_lock_irqsave(&sport->port.lock, flags);
/*
- * Finally, clear and enable interrupts
+ * Finally enable interrupts and RX/TX
*/
-
temp = readb(sport->port.membase + MXC_UARTCR2);
- temp |= MXC_UARTCR2_RIE | MXC_UARTCR2_TIE;
+ temp |= (MXC_UARTCR2_RIE | MXC_UARTCR2_TIE | MXC_UARTCR2_TE | MXC_UARTCR2_RE);
writeb(temp, sport->port.membase + MXC_UARTCR2);
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -627,9 +618,6 @@ static int imx_startup(struct uart_port *port)
tty = sport->port.state->port.tty;
return 0;
-
-error_out1:
- return retval;
}
static void imx_shutdown(struct uart_port *port)
@@ -647,9 +635,14 @@ static void imx_shutdown(struct uart_port *port)
}
}
+ while (!(readb(sport->port.membase + MXC_UARTSR1) & MXC_UARTSR1_TC))
+ barrier();
spin_lock_irqsave(&sport->port.lock, flags);
+
+ /* Disable Rx/Tx and interrupts */
temp = readb(sport->port.membase + MXC_UARTCR2);
- temp &= ~(MXC_UARTCR2_TE | MXC_UARTCR2_RE);
+ temp &= ~(MXC_UARTCR2_TE | MXC_UARTCR2_RE |
+ MXC_UARTCR2_TIE | MXC_UARTCR2_TCIE | MXC_UARTCR2_RIE);
writeb(temp, sport->port.membase + MXC_UARTCR2);
spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -660,16 +653,6 @@ static void imx_shutdown(struct uart_port *port)
free_irq(sport->port.irq, sport);
- /*
- * Disable all interrupts, port and break condition.
- */
-
- spin_lock_irqsave(&sport->port.lock, flags);
- temp = readb(sport->port.membase + MXC_UARTCR2);
- temp &= ~(MXC_UARTCR2_TIE | MXC_UARTCR2_TCIE | MXC_UARTCR2_RIE);
- writeb(temp, sport->port.membase + MXC_UARTCR2);
-
- spin_unlock_irqrestore(&sport->port.lock, flags);
}
static void
@@ -1034,6 +1017,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
unsigned long flags;
spin_lock_irqsave(&sport->port.lock, flags);
+
/*
* First, save UCR1/2 and then disable interrupts
*/
@@ -1053,9 +1037,10 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
* and restore CR2
*/
while (!(readb(sport->port.membase + MXC_UARTSR1) & MXC_UARTSR1_TC))
- ;
+ barrier();
writeb(old_cr2, sport->port.membase + MXC_UARTCR2);
+
spin_unlock_irqrestore(&sport->port.lock, flags);
}
@@ -1067,49 +1052,50 @@ static void __init
imx_console_get_options(struct imx_port *sport, int *baud,
int *parity, int *bits)
{
+ unsigned char cr1, cr2, bdh, bdl, brfa;
+ unsigned int sbr, uartclk;
+ unsigned int baud_raw;
- if (readb(sport->port.membase + MXC_UARTCR2) &
- (MXC_UARTCR2_TE | MXC_UARTCR2)) {
- /* ok, the port was enabled */
- unsigned char cr1, bdh, bdl, brfa;
- unsigned int sbr, uartclk;
- unsigned int baud_raw;
-
- cr1 = readb(sport->port.membase + MXC_UARTCR1);
+ cr2 = readb(sport->port.membase + MXC_UARTCR2);
+ cr2 &= (MXC_UARTCR2_TE | MXC_UARTCR2_RE);
+ if (!cr2)
+ return;
+ /* ok, the port was enabled */
- *parity = 'n';
- if (cr1 & MXC_UARTCR1_PE) {
- if (cr1 & MXC_UARTCR1_PT)
- *parity = 'o';
- else
- *parity = 'e';
- }
+ cr1 = readb(sport->port.membase + MXC_UARTCR1);
- if (cr1 & MXC_UARTCR1_M)
- *bits = 9;
+ *parity = 'n';
+ if (cr1 & MXC_UARTCR1_PE) {
+ if (cr1 & MXC_UARTCR1_PT)
+ *parity = 'o';
else
- *bits = 8;
-
- bdh = readb(sport->port.membase + MXC_UARTBDH) &
- MXC_UARTBDH_SBR_MASK;
- bdl = readb(sport->port.membase + MXC_UARTBDL);
- sbr = bdh;
- sbr <<= 8;
- sbr |= bdl;
- brfa = readb(sport->port.membase + MXC_UARTCR4) &
- MXC_UARTCR4_BRFA_MASK;
-
- uartclk = clk_get_rate(sport->clk);
- /*
- * Baud = mod_clk/(16*(sbr[13]+(brfa)/32)
- */
- baud_raw = uartclk/(16 * (sbr + brfa/32));
-
- if (*baud != baud_raw)
- printk(KERN_INFO "Serial: Console IMX "
- "rounded baud rate from %d to %d\n",
- baud_raw, *baud);
+ *parity = 'e';
}
+
+ if (cr1 & MXC_UARTCR1_M)
+ *bits = 9;
+ else
+ *bits = 8;
+
+ bdh = readb(sport->port.membase + MXC_UARTBDH) &
+ MXC_UARTBDH_SBR_MASK;
+ bdl = readb(sport->port.membase + MXC_UARTBDL);
+ sbr = bdh;
+ sbr <<= 8;
+ sbr |= bdl;
+ brfa = readb(sport->port.membase + MXC_UARTCR4) &
+ MXC_UARTCR4_BRFA_MASK;
+
+ uartclk = clk_get_rate(sport->clk);
+ /*
+ * Baud = mod_clk/(16*(sbr[13]+(brfa)/32)
+ */
+ baud_raw = uartclk/(16 * (sbr + brfa/32));
+
+ if (*baud != baud_raw)
+ printk(KERN_INFO "Serial: Console IMX "
+ "rounded baud rate from %d to %d\n",
+ baud_raw, *baud);
}
static int __init