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 24 Jan 2016 20:37:26 -0000 @@ -106,6 +106,7 @@ cdev_decl(com); static u_char tiocm_xxx2mcr(int); +static void write_lcr(char *, 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(char *id, 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: [%s] failed to set lcr %d\n", id, 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("comopen0", 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("comopen1", 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("comopen2", 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("comopen3", 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("compwroff0", 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("compwroff1", 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("compwroff2", 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("com_resume0", 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("com_resume1", 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("com_resume2", 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("com_resume3", iot, ioh, sc->sc_lcr); } else { - bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); + write_lcr("com_resume4", 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("com_resume5", 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("com_resume6", 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("comioctl0", 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("comioctl1", iot, ioh, sc->sc_lcr); break; case TIOCSDTR: SET(sc->sc_mcr, sc->sc_dtr); @@ -920,31 +934,50 @@ comparam(struct tty *tp, struct termios return (error); } } +{ + u_int8_t lsr = bus_space_read_1(iot, ioh, com_lsr); + int i, h, l; + + write_lcr("comparam0", iot, ioh, lcr | LCR_DLAB); + +for (i = 0; i < 100; i++) { + bus_space_write_1(iot, ioh, com_dlbh, 0xff); + bus_space_write_1(iot, ioh, com_dlbl, 0xff); - bus_space_write_1(iot, ioh, com_lcr, 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); + + h = bus_space_read_1(iot, ioh, com_dlbh); + l = bus_space_read_1(iot, ioh, com_dlbl); + + if (h == (ospeed >> 8) && l == (ospeed & 0xff)) break; + + printf("comparam: dlbl: %02x -> %02x dlbh: %02x -> %02x\n", + ospeed & 0xff, l, ospeed >> 8, h); +} + + write_lcr("comparam1", iot, ioh, lcr); SET(sc->sc_mcr, MCR_DTR); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); + printf("comparam: lsr was %x\n", lsr); +} } else - bus_space_write_1(iot, ioh, com_lcr, lcr); + write_lcr("comparam2", 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("comparam3", 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("comparam4", 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("comparam5", iot, ioh, lcr); /* When not using CRTSCTS, RTS follows DTR. */ if (!ISSET(t->c_cflag, CRTSCTS)) { @@ -1387,11 +1420,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("cominit0", 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("cominit1", iot, ioh, LCR_8BITS); bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS); #ifdef COM_PXA2X0 /* XXX */ @@ -1606,9 +1639,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("com_attach_subr0", iot, ioh, LCR_EFR); bus_space_write_1(iot, ioh, com_efr, 0); - bus_space_write_1(iot, ioh, com_lcr, 0); + write_lcr("com_attach_subr1", iot, ioh, 0); bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE); delay(100); @@ -1633,14 +1666,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("com_attach_subr2", 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("com_attach_subr3", iot, ioh, LCR_EFR); if (bus_space_read_1(iot, ioh, com_efr) == 0) sc->sc_uarttype = COM_UART_ST16650V2; } @@ -1651,7 +1684,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("com_attach_subr4", 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 +1704,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("com_attach_subr5", 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("com_attach_subr6", iot, ioh, 0); if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 6) #endif sc->sc_uarttype = COM_UART_TI16750; @@ -1685,7 +1718,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("com_attach_subr7", iot, ioh, lcr); if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */ u_int8_t scr0, scr1, scr2; @@ -1856,10 +1889,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("com_fifo_probe0", 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("com_fifo_probe1", 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;