diff options
author | roshni.shah <roshni.shah@timesys.com> | 2013-06-30 10:10:19 -0400 |
---|---|---|
committer | Andy Voltz <andy.voltz@timesys.com> | 2013-07-26 01:30:24 -0400 |
commit | 6619f8df2dfe43d84587823a68b9e1c53233af71 (patch) | |
tree | 9e315d776037647a8428c27d5289b2a0e3fb98fd /drivers | |
parent | 3a915708a763387c608cf5041ceb0d7732c2820b (diff) |
MVF Serial Driver Improvements to fix the sysvinit console hang issue.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/serial/mvf.c | 118 |
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 |