Lines Matching +full:use +full:- +full:broken +full:- +full:interrupts
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
7 * Redistribution and use in source and binary forms, with or without
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
83 "Number of UART RX interrupts where TX is not ready, before data is discarded");
86 * To use early printf on x86, add the following to your kernel config:
102 while ((inb(stat) & LSR_THRE) == 0 && --limit > 0) in uart_ns8250_early_putc()
110 * Clear pending interrupts. THRE is cleared by reading IIR. Data
160 return (16000000 * divisor / bas->rclk); in ns8250_delay()
161 return (16000 * divisor / (bas->rclk / 1000)); in ns8250_delay()
179 error = ((actual_baud - baudrate) * 2000 / baudrate + 1) / 2; in ns8250_divisor()
182 if (error < -UART_DEV_TOLERANCE_PCT || error > UART_DEV_TOLERANCE_PCT) in ns8250_divisor()
198 * an infinite loop when the hardware is broken. Make the in ns8250_drain()
202 while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit) in ns8250_drain()
213 * an infinite loop when the hardware is broken. Make the in ns8250_drain()
224 while (limit && (uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) { in ns8250_drain()
228 } while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit); in ns8250_drain()
233 /* printf("uart: ns8250: receiver appears broken... "); */ in ns8250_drain()
264 * Firecracker VMM, aka. the rust-vmm/vm-superio emulation code: in ns8250_flush()
265 * https://github.com/rust-vmm/vm-superio/issues/83 in ns8250_flush()
273 printf("uart: ns8250: UART FCR is broken\n"); in ns8250_flush()
285 /* Don't change settings when running on Hyper-V */ in ns8250_param()
303 if (baudrate > 0 && bas->rclk > 0) { in ns8250_param()
304 divisor = ns8250_divisor(bas->rclk, baudrate); in ns8250_param()
321 * Low-level UART interface.
369 * We use 0xe0 instead of 0xf0 as the mask because the XScale PXA in ns8250_init()
370 * UARTs split the receive time-out interrupt bit out separately as in ns8250_init()
384 if (bas->rclk_guess && bas->rclk == 0 && baudrate != 0) { in ns8250_init()
388 bas->rclk = baudrate * div * 16; in ns8250_init()
393 * refinement, but that's hard outside of consoles to know what to use. in ns8250_init()
396 if (bas->rclk == 0 && baudrate != 0) in ns8250_init()
397 bas->rclk = DEFAULT_RCLK; in ns8250_init()
428 while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0 && --limit) in ns8250_putc()
492 * XXX -- refactor out ACPI and FDT ifdefs
505 {"PNP0501", &uart_ns8250_class, 0, 0, 0, 0, 0, "16550A-compatible COM port"},
506 {"PNP0502", &uart_ns8250_class, 0, 0, 0, 0, 0, "Multiport serial device (non-intelligent 16550)"},
507 {"PNP0510", &uart_ns8250_class, 0, 0, 0, 0, 0, "Generic IRDA-compatible device"},
508 {"PNP0511", &uart_ns8250_class, 0, 0, 0, 0, 0, "Generic IRDA-compatible device"},
526 /* Use token-pasting to form SER_ and MSR_ named constants. */
574 /* Check whether uart has a broken txfifo. */ in ns8250_bus_attach()
575 node = ofw_bus_get_node(sc->sc_dev); in ns8250_bus_attach()
576 if ((OF_getencprop(node, "broken-txfifo", &cell, sizeof(cell))) > 0) in ns8250_bus_attach()
580 bas = &sc->sc_bas; in ns8250_bus_attach()
582 ns8250->busy_detect = bas->busy_detect; in ns8250_bus_attach()
583 ns8250->mcr = uart_getreg(bas, REG_MCR); in ns8250_bus_attach()
584 ns8250->fcr = FCR_ENABLE; in ns8250_bus_attach()
585 if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags", in ns8250_bus_attach()
588 ns8250->fcr |= FCR_RX_LOW; in ns8250_bus_attach()
590 ns8250->fcr |= FCR_RX_MEDL; in ns8250_bus_attach()
592 ns8250->fcr |= FCR_RX_HIGH; in ns8250_bus_attach()
594 ns8250->fcr |= FCR_RX_MEDH; in ns8250_bus_attach()
596 ns8250->fcr |= FCR_RX_MEDH; in ns8250_bus_attach()
600 resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_mask", in ns8250_bus_attach()
602 ns8250->ier_mask = (uint8_t)(ivar & 0xff); in ns8250_bus_attach()
606 resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_rxbits", in ns8250_bus_attach()
608 ns8250->ier_rxbits = (uint8_t)(ivar & 0xff); in ns8250_bus_attach()
610 uart_setreg(bas, REG_FCR, ns8250->fcr); in ns8250_bus_attach()
614 if (ns8250->mcr & MCR_DTR) in ns8250_bus_attach()
615 sc->sc_hwsig |= SER_DTR; in ns8250_bus_attach()
616 if (ns8250->mcr & MCR_RTS) in ns8250_bus_attach()
617 sc->sc_hwsig |= SER_RTS; in ns8250_bus_attach()
621 ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; in ns8250_bus_attach()
622 ns8250->ier |= ns8250->ier_rxbits; in ns8250_bus_attach()
623 uart_setreg(bas, REG_IER, ns8250->ier); in ns8250_bus_attach()
631 * ns8250_bus_ipend() -- which it accidentally had before r253161. in ns8250_bus_attach()
649 bas = &sc->sc_bas; in ns8250_bus_detach()
650 ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; in ns8250_bus_detach()
664 bas = &sc->sc_bas; in ns8250_bus_flush()
665 uart_lock(sc->sc_hwmtx); in ns8250_bus_flush()
666 if (sc->sc_rxfifosz > 1) { in ns8250_bus_flush()
668 uart_setreg(bas, REG_FCR, ns8250->fcr); in ns8250_bus_flush()
673 uart_unlock(sc->sc_hwmtx); in ns8250_bus_flush()
684 * The delta bits are reputed to be broken on some hardware, so use in ns8250_bus_getsig()
685 * software delta detection by default. Use the hardware delta bits in ns8250_bus_getsig()
688 * others, so always use software for it. Other threads may be changing in ns8250_bus_getsig()
689 * other (non-MSR) bits in sc_hwsig, so loop until it can successfully in ns8250_bus_getsig()
695 old = sc->sc_hwsig; in ns8250_bus_getsig()
697 uart_lock(sc->sc_hwmtx); in ns8250_bus_getsig()
698 msr = uart_getreg(&sc->sc_bas, REG_MSR); in ns8250_bus_getsig()
699 uart_unlock(sc->sc_hwmtx); in ns8250_bus_getsig()
700 if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) { in ns8250_bus_getsig()
710 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, sig & ~SER_MASK_DELTA)); in ns8250_bus_getsig()
721 bas = &sc->sc_bas; in ns8250_bus_ioctl()
723 uart_lock(sc->sc_hwmtx); in ns8250_bus_ioctl()
766 baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0; in ns8250_bus_ioctl()
776 uart_unlock(sc->sc_hwmtx); in ns8250_bus_ioctl()
789 bas = &sc->sc_bas; in ns8250_bus_ipend()
790 uart_lock(sc->sc_hwmtx); in ns8250_bus_ipend()
793 if (ns8250->busy_detect && (iir & IIR_BUSY) == IIR_BUSY) { in ns8250_bus_ipend()
795 uart_unlock(sc->sc_hwmtx); in ns8250_bus_ipend()
799 uart_unlock(sc->sc_hwmtx); in ns8250_bus_ipend()
814 ns8250->ier &= ~IER_ETXRDY; in ns8250_bus_ipend()
815 uart_setreg(bas, REG_IER, ns8250->ier); in ns8250_bus_ipend()
822 uart_unlock(sc->sc_hwmtx); in ns8250_bus_ipend()
835 bas = &sc->sc_bas; in ns8250_bus_param()
836 uart_lock(sc->sc_hwmtx); in ns8250_bus_param()
842 if (ns8250->busy_detect != 0) { in ns8250_bus_param()
845 * an infinite loop in case when the hardware is broken. in ns8250_bus_param()
849 --limit) in ns8250_bus_param()
854 uart_unlock(sc->sc_hwmtx); in ns8250_bus_param()
860 uart_unlock(sc->sc_hwmtx); in ns8250_bus_param()
871 bas = &sc->sc_bas; in ns8250_bus_probe()
878 if (sc->sc_sysdev == NULL) { in ns8250_bus_probe()
891 * avoid the possibility that automatic flow-control prevents in ns8250_bus_probe()
911 sc->sc_rxfifosz = sc->sc_txfifosz = 1; in ns8250_bus_probe()
912 device_set_desc(sc->sc_dev, "8250 or 16450 or compatible"); in ns8250_bus_probe()
950 --limit) in ns8250_bus_probe()
963 count--; in ns8250_bus_probe()
972 sc->sc_rxfifosz = 16; in ns8250_bus_probe()
973 device_set_desc(sc->sc_dev, "16550 or compatible"); in ns8250_bus_probe()
975 sc->sc_rxfifosz = 32; in ns8250_bus_probe()
976 device_set_desc(sc->sc_dev, "16650 or compatible"); in ns8250_bus_probe()
978 sc->sc_rxfifosz = 64; in ns8250_bus_probe()
979 device_set_desc(sc->sc_dev, "16750 or compatible"); in ns8250_bus_probe()
981 sc->sc_rxfifosz = 128; in ns8250_bus_probe()
982 device_set_desc(sc->sc_dev, "16950 or compatible"); in ns8250_bus_probe()
984 sc->sc_rxfifosz = 256; in ns8250_bus_probe()
985 device_set_desc(sc->sc_dev, "16x50 with 256 byte FIFO"); in ns8250_bus_probe()
987 sc->sc_rxfifosz = 16; in ns8250_bus_probe()
988 device_set_desc(sc->sc_dev, in ns8250_bus_probe()
989 "Non-standard ns8250 class UART with FIFOs"); in ns8250_bus_probe()
997 sc->sc_txfifosz = 16; in ns8250_bus_probe()
1007 if (sc->sc_rxfifosz > 16) { in ns8250_bus_probe()
1008 sc->sc_hwiflow = 1; in ns8250_bus_probe()
1009 sc->sc_hwoflow = 1; in ns8250_bus_probe()
1024 bas = &sc->sc_bas; in ns8250_bus_receive()
1025 uart_lock(sc->sc_hwmtx); in ns8250_bus_receive()
1029 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; in ns8250_bus_receive()
1039 if (++ns8250->noise_count >= uart_noise_threshold) in ns8250_bus_receive()
1042 ns8250->noise_count = 0; in ns8250_bus_receive()
1057 uart_unlock(sc->sc_hwmtx); in ns8250_bus_receive()
1068 bas = &sc->sc_bas; in ns8250_bus_setsig()
1070 old = sc->sc_hwsig; in ns8250_bus_setsig()
1078 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); in ns8250_bus_setsig()
1079 uart_lock(sc->sc_hwmtx); in ns8250_bus_setsig()
1080 ns8250->mcr &= ~(MCR_DTR|MCR_RTS); in ns8250_bus_setsig()
1082 ns8250->mcr |= MCR_DTR; in ns8250_bus_setsig()
1084 ns8250->mcr |= MCR_RTS; in ns8250_bus_setsig()
1085 uart_setreg(bas, REG_MCR, ns8250->mcr); in ns8250_bus_setsig()
1087 uart_unlock(sc->sc_hwmtx); in ns8250_bus_setsig()
1098 bas = &sc->sc_bas; in ns8250_bus_transmit()
1099 uart_lock(sc->sc_hwmtx); in ns8250_bus_transmit()
1102 for (i = 0; i < sc->sc_txdatasz; i++) { in ns8250_bus_transmit()
1103 uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]); in ns8250_bus_transmit()
1107 ns8250->ier |= IER_ETXRDY; in ns8250_bus_transmit()
1108 uart_setreg(bas, REG_IER, ns8250->ier); in ns8250_bus_transmit()
1113 sc->sc_txbusy = 1; in ns8250_bus_transmit()
1114 uart_unlock(sc->sc_hwmtx); in ns8250_bus_transmit()
1123 struct uart_bas *bas = &sc->sc_bas; in ns8250_bus_txbusy()
1134 struct uart_bas *bas = &sc->sc_bas; in ns8250_bus_grab()
1139 * turn off all interrupts to enter polling mode. Leave the in ns8250_bus_grab()
1143 uart_lock(sc->sc_hwmtx); in ns8250_bus_grab()
1145 uart_setreg(bas, REG_IER, ier & ns8250->ier_mask); in ns8250_bus_grab()
1147 uart_unlock(sc->sc_hwmtx); in ns8250_bus_grab()
1154 struct uart_bas *bas = &sc->sc_bas; in ns8250_bus_ungrab()
1159 uart_lock(sc->sc_hwmtx); in ns8250_bus_ungrab()
1160 uart_setreg(bas, REG_IER, ns8250->ier); in ns8250_bus_ungrab()
1162 uart_unlock(sc->sc_hwmtx); in ns8250_bus_ungrab()