Index: com.c =================================================================== RCS file: /cvs/src/sys/dev/ic/com.c,v retrieving revision 1.158 diff -u -p -r1.158 com.c --- com.c 14 Sep 2014 14:17:24 -0000 1.158 +++ com.c 6 Jan 2016 02:46:41 -0000 @@ -106,6 +106,7 @@ cdev_decl(com); static u_char tiocm_xxx2mcr(int); +static void write_lcr(bus_space_tag_t, bus_space_handle_t, u_int8_t); void compwroff(struct com_softc *); void cominit(bus_space_tag_t, bus_space_handle_t, int, int); @@ -146,6 +147,21 @@ void com_kgdb_putc(void *, int); #define DEVUNIT(x) (minor(x) & 0x7f) #define DEVCUA(x) (minor(x) & 0x80) +static void +write_lcr(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t lcr) +{ + int i; + + /* there is a buggy UART which sometimes fails to + * write LCR register, so retry it */ + for (i = 0; i < 1000; i++) { + bus_space_write_1(iot, ioh, com_lcr, lcr); + if (bus_space_read_1(iot, ioh, com_lcr) == lcr) break; + } + + if (i) printf("write_lcr: failed to set lcr %d\n", i); +} + int comspeed(long freq, long speed) { @@ -342,11 +358,11 @@ comopen(dev_t dev, int flag, int mode, s switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + write_lcr(iot, ioh, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, EFR_ECB); bus_space_write_1(iot, ioh, com_ier, 0); bus_space_write_1(iot, ioh, com_efr, 0); - bus_space_write_1(iot, ioh, com_lcr, 0); + write_lcr(iot, ioh, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, 0); @@ -370,8 +386,7 @@ comopen(dev_t dev, int flag, int mode, s if (sc->sc_uarttype == COM_UART_TI16750) { fifo |= FIFO_ENABLE_64BYTE; lcr = bus_space_read_1(iot, ioh, com_lcr); - bus_space_write_1(iot, ioh, com_lcr, - lcr | LCR_DLAB); + write_lcr(iot, ioh, lcr | LCR_DLAB); } /* @@ -397,7 +412,7 @@ comopen(dev_t dev, int flag, int mode, s break; } if (sc->sc_uarttype == COM_UART_TI16750) - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr(iot, ioh, lcr); } /* Flush any pending I/O. */ @@ -531,7 +546,7 @@ compwroff(struct com_softc *sc) struct tty *tp = sc->sc_tty; CLR(sc->sc_lcr, LCR_SBREAK); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + write_lcr(iot, ioh, sc->sc_lcr); bus_space_write_1(iot, ioh, com_ier, 0); if (ISSET(tp->t_cflag, HUPCL) && !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { @@ -555,10 +570,10 @@ compwroff(struct com_softc *sc) switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + write_lcr(iot, ioh, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, EFR_ECB); bus_space_write_1(iot, ioh, com_ier, IER_SLEEP); - bus_space_write_1(iot, ioh, com_lcr, 0); + write_lcr(iot, ioh, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, IER_SLEEP); @@ -599,11 +614,11 @@ com_resume(struct com_softc *sc) switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + write_lcr(iot, ioh, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, EFR_ECB); bus_space_write_1(iot, ioh, com_ier, 0); bus_space_write_1(iot, ioh, com_efr, 0); - bus_space_write_1(iot, ioh, com_lcr, 0); + write_lcr(iot, ioh, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, 0); @@ -617,12 +632,12 @@ com_resume(struct com_softc *sc) ospeed = comspeed(sc->sc_frequency, tp->t_ospeed); if (ospeed != 0) { - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr | LCR_DLAB); + write_lcr(iot, ioh, sc->sc_lcr | LCR_DLAB); bus_space_write_1(iot, ioh, com_dlbl, ospeed); bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + write_lcr(iot, ioh, sc->sc_lcr); } else { - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + write_lcr(iot, ioh, sc->sc_lcr); } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { @@ -638,8 +653,7 @@ com_resume(struct com_softc *sc) if (sc->sc_uarttype == COM_UART_TI16750) { fifo |= FIFO_ENABLE_64BYTE; lcr = bus_space_read_1(iot, ioh, com_lcr); - bus_space_write_1(iot, ioh, com_lcr, - lcr | LCR_DLAB); + write_lcr(iot, ioh, lcr | LCR_DLAB); } /* @@ -665,7 +679,7 @@ com_resume(struct com_softc *sc) break; } if (sc->sc_uarttype == COM_UART_TI16750) - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr(iot, ioh, lcr); } /* You turn me on, baby! */ @@ -751,11 +765,11 @@ comioctl(dev_t dev, u_long cmd, caddr_t switch (cmd) { case TIOCSBRK: SET(sc->sc_lcr, LCR_SBREAK); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + write_lcr(iot, ioh, sc->sc_lcr); break; case TIOCCBRK: CLR(sc->sc_lcr, LCR_SBREAK); - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + write_lcr(iot, ioh, sc->sc_lcr); break; case TIOCSDTR: SET(sc->sc_mcr, sc->sc_dtr); @@ -921,30 +935,29 @@ comparam(struct tty *tp, struct termios } } - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + write_lcr(iot, ioh, lcr | LCR_DLAB); bus_space_write_1(iot, ioh, com_dlbl, ospeed); bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8); - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr(iot, ioh, lcr); SET(sc->sc_mcr, MCR_DTR); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } else - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr(iot, ioh, lcr); if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { if (sc->sc_uarttype == COM_UART_TI16750) { - bus_space_write_1(iot, ioh, com_lcr, - lcr | LCR_DLAB); + write_lcr(iot, ioh, lcr | LCR_DLAB); bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | FIFO_ENABLE_64BYTE | (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr(iot, ioh, lcr); } else bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); } } else - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr(iot, ioh, lcr); /* When not using CRTSCTS, RTS follows DTR. */ if (!ISSET(t->c_cflag, CRTSCTS)) { @@ -1387,11 +1400,11 @@ cominit(bus_space_tag_t iot, bus_space_h int s = splhigh(); u_char stat; - bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB); + write_lcr(iot, ioh, LCR_DLAB); rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */ bus_space_write_1(iot, ioh, com_dlbl, rate); bus_space_write_1(iot, ioh, com_dlbh, rate >> 8); - bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS); + write_lcr(iot, ioh, LCR_8BITS); bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS); #ifdef COM_PXA2X0 /* XXX */ @@ -1606,9 +1619,9 @@ com_attach_subr(struct com_softc *sc) * Probe for all known forms of UART. */ lcr = bus_space_read_1(iot, ioh, com_lcr); - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + write_lcr(iot, ioh, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, 0); - bus_space_write_1(iot, ioh, com_lcr, 0); + write_lcr(iot, ioh, 0); bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE); delay(100); @@ -1633,14 +1646,14 @@ com_attach_subr(struct com_softc *sc) } if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */ - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + write_lcr(iot, ioh, lcr | LCR_DLAB); if (bus_space_read_1(iot, ioh, com_efr) == 0) { bus_space_write_1(iot, ioh, com_efr, EFR_CTS); if (bus_space_read_1(iot, ioh, com_efr) != 0) sc->sc_uarttype = COM_UART_ST16650; bus_space_write_1(iot, ioh, com_efr, 0); } else { - bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + write_lcr(iot, ioh, LCR_EFR); if (bus_space_read_1(iot, ioh, com_efr) == 0) sc->sc_uarttype = COM_UART_ST16650V2; } @@ -1651,7 +1664,7 @@ com_attach_subr(struct com_softc *sc) u_int8_t dlbl, dlbh; /* Enable latch access and get the current values. */ - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + write_lcr(iot, ioh, lcr | LCR_DLAB); dlbl = bus_space_read_1(iot, ioh, com_dlbl); dlbh = bus_space_read_1(iot, ioh, com_dlbh); @@ -1671,12 +1684,12 @@ com_attach_subr(struct com_softc *sc) #endif if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for TI16750s */ - bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + write_lcr(iot, ioh, lcr | LCR_DLAB); bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | FIFO_ENABLE_64BYTE); if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 7) { #if 0 - bus_space_write_1(iot, ioh, com_lcr, 0); + write_lcr(iot, ioh, 0); if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 6) #endif sc->sc_uarttype = COM_UART_TI16750; @@ -1685,7 +1698,7 @@ com_attach_subr(struct com_softc *sc) } /* Reset the LCR (latch access is probably enabled). */ - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr(iot, ioh, lcr); if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */ u_int8_t scr0, scr1, scr2; @@ -1856,10 +1869,10 @@ com_fifo_probe(struct com_softc *sc) ier |= IER_EUART; #endif bus_space_write_1(iot, ioh, com_ier, ier); - bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB); + write_lcr(iot, ioh, LCR_DLAB); bus_space_write_1(iot, ioh, com_dlbl, 3); bus_space_write_1(iot, ioh, com_dlbh, 0); - bus_space_write_1(iot, ioh, com_lcr, LCR_PNONE | LCR_8BITS); + write_lcr(iot, ioh, LCR_PNONE | LCR_8BITS); bus_space_write_1(iot, ioh, com_mcr, MCR_LOOPBACK); fifo = FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST;