diff options
Diffstat (limited to 'sys/dev/uart')
| -rw-r--r-- | sys/dev/uart/uart_bus_acpi.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_bus_fdt.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_bus_isa.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_bus_pci.c | 56 | ||||
| -rw-r--r-- | sys/dev/uart/uart_bus_puc.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_bus_scc.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_imx.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_lowrisc.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_mu.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_mvebu.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_ns8250.c | 51 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_pl011.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_quicc.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_dev_z8530.c | 2 | ||||
| -rw-r--r-- | sys/dev/uart/uart_tty.c | 3 |
15 files changed, 89 insertions, 45 deletions
diff --git a/sys/dev/uart/uart_bus_acpi.c b/sys/dev/uart/uart_bus_acpi.c index bd53bfb204ed..b75c8a9ad517 100644 --- a/sys/dev/uart/uart_bus_acpi.c +++ b/sys/dev/uart/uart_bus_acpi.c @@ -49,7 +49,7 @@ static device_method_t uart_acpi_methods[] = { DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD(device_resume, uart_bus_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_acpi_driver = { diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c index e9a7e04e4e0c..957638548880 100644 --- a/sys/dev/uart/uart_bus_fdt.c +++ b/sys/dev/uart/uart_bus_fdt.c @@ -54,7 +54,7 @@ static device_method_t uart_fdt_methods[] = { DEVMETHOD(device_probe, uart_fdt_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_fdt_driver = { diff --git a/sys/dev/uart/uart_bus_isa.c b/sys/dev/uart/uart_bus_isa.c index 27211a1334c0..166f25599d4c 100644 --- a/sys/dev/uart/uart_bus_isa.c +++ b/sys/dev/uart/uart_bus_isa.c @@ -49,7 +49,7 @@ static device_method_t uart_isa_methods[] = { DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD(device_resume, uart_bus_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_isa_driver = { diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c index 22af8ee8663c..97c5ff84d251 100644 --- a/sys/dev/uart/uart_bus_pci.c +++ b/sys/dev/uart/uart_bus_pci.c @@ -280,33 +280,43 @@ uart_pci_probe(device_t dev) { struct uart_softc *sc; const struct pci_id *id; - struct pci_id cid = { - .regshft = 0, - .rclk = 0, - .rid = 0x10 | PCI_NO_MSI, - .desc = "Generic SimpleComm PCI device", - }; - int result; sc = device_get_softc(dev); id = uart_pci_match(dev, pci_ns8250_ids); if (id != NULL) { sc->sc_class = &uart_ns8250_class; - goto match; + return (BUS_PROBE_SPECIFIC); } if (pci_get_class(dev) == PCIC_SIMPLECOMM && pci_get_subclass(dev) == PCIS_SIMPLECOMM_UART && - pci_get_progif(dev) < PCIP_SIMPLECOMM_UART_16550A) { - /* XXX rclk what to do */ - id = &cid; + pci_get_progif(dev) <= PCIP_SIMPLECOMM_UART_16550A) { sc->sc_class = &uart_ns8250_class; - goto match; + return (BUS_PROBE_GENERIC); } /* Add checks for non-ns8250 IDs here. */ return (ENXIO); +} + +static int +uart_pci_attach(device_t dev) +{ + static const struct pci_id cid = { + .regshft = 0, + .rclk = 0, + .rid = 0x10 | PCI_NO_MSI, + .desc = "Generic SimpleComm PCI device", + }; + struct uart_softc *sc; + const struct pci_id *id = uart_pci_match(dev, pci_ns8250_ids); + int count, result; + + if (id == NULL) + /* No specific PCI ID match, must be a generic device. */ + id = &cid; + + sc = device_get_softc(dev); - match: result = uart_bus_probe(dev, id->regshft, 0, id->rclk, id->rid & PCI_RID_MASK, 0, 0); /* Bail out on error. */ @@ -322,25 +332,13 @@ uart_pci_probe(device_t dev) /* Set/override the device description. */ if (id->desc) device_set_desc(dev, id->desc); - return (result); -} - -static int -uart_pci_attach(device_t dev) -{ - struct uart_softc *sc; - const struct pci_id *id; - int count; - - sc = device_get_softc(dev); /* - * Use MSI in preference to legacy IRQ if available. However, experience - * suggests this is only reliable when one MSI vector is advertised. + * Use MSI in preference to legacy IRQ if available. However, + * experience suggests this is only reliable when one MSI vector is + * advertised. */ - id = uart_pci_match(dev, pci_ns8250_ids); - if ((id == NULL || (id->rid & PCI_NO_MSI) == 0) && - pci_msi_count(dev) == 1) { + if ((id->rid & PCI_NO_MSI) == 0 && pci_msi_count(dev) == 1) { count = 1; if (pci_alloc_msi(dev, &count) == 0) { sc->sc_irid = 1; diff --git a/sys/dev/uart/uart_bus_puc.c b/sys/dev/uart/uart_bus_puc.c index 5f6c5cdbbdad..661db8595262 100644 --- a/sys/dev/uart/uart_bus_puc.c +++ b/sys/dev/uart/uart_bus_puc.c @@ -52,7 +52,7 @@ static device_method_t uart_puc_methods[] = { /* Serdev interface */ DEVMETHOD(serdev_ihand, uart_bus_ihand), DEVMETHOD(serdev_ipend, uart_bus_ipend), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_puc_driver = { diff --git a/sys/dev/uart/uart_bus_scc.c b/sys/dev/uart/uart_bus_scc.c index 731c1532851a..ad826dfe80d4 100644 --- a/sys/dev/uart/uart_bus_scc.c +++ b/sys/dev/uart/uart_bus_scc.c @@ -53,7 +53,7 @@ static device_method_t uart_scc_methods[] = { /* Serdev interface */ DEVMETHOD(serdev_ihand, uart_bus_ihand), DEVMETHOD(serdev_sysdev, uart_bus_sysdev), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_scc_driver = { diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c index b40012a313ca..021475ecc676 100644 --- a/sys/dev/uart/uart_dev_imx.c +++ b/sys/dev/uart/uart_dev_imx.c @@ -296,7 +296,7 @@ static kobj_method_t imx_uart_methods[] = { KOBJMETHOD(uart_transmit, imx_uart_bus_transmit), KOBJMETHOD(uart_grab, imx_uart_bus_grab), KOBJMETHOD(uart_ungrab, imx_uart_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_imx_class = { diff --git a/sys/dev/uart/uart_dev_lowrisc.c b/sys/dev/uart/uart_dev_lowrisc.c index 19630deb4b78..ef70118a817a 100644 --- a/sys/dev/uart/uart_dev_lowrisc.c +++ b/sys/dev/uart/uart_dev_lowrisc.c @@ -168,7 +168,7 @@ static kobj_method_t lowrisc_uart_methods[] = { KOBJMETHOD(uart_transmit, lowrisc_uart_bus_transmit), KOBJMETHOD(uart_grab, lowrisc_uart_bus_grab), KOBJMETHOD(uart_ungrab, lowrisc_uart_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_lowrisc_class = { diff --git a/sys/dev/uart/uart_dev_mu.c b/sys/dev/uart/uart_dev_mu.c index ddaca2edce2c..abfb105f6c9c 100644 --- a/sys/dev/uart/uart_dev_mu.c +++ b/sys/dev/uart/uart_dev_mu.c @@ -280,7 +280,7 @@ static kobj_method_t uart_mu_methods[] = { KOBJMETHOD(uart_transmit, uart_mu_bus_transmit), KOBJMETHOD(uart_grab, uart_mu_bus_grab), KOBJMETHOD(uart_ungrab, uart_mu_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_mu_class = { diff --git a/sys/dev/uart/uart_dev_mvebu.c b/sys/dev/uart/uart_dev_mvebu.c index 8f989aa0ca14..a4d331bea6c0 100644 --- a/sys/dev/uart/uart_dev_mvebu.c +++ b/sys/dev/uart/uart_dev_mvebu.c @@ -299,7 +299,7 @@ static kobj_method_t uart_mvebu_methods[] = { KOBJMETHOD(uart_transmit, uart_mvebu_bus_transmit), KOBJMETHOD(uart_grab, uart_mvebu_bus_grab), KOBJMETHOD(uart_ungrab, uart_mvebu_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; struct uart_class uart_mvebu_class = { diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index c38d50e54ad8..c13eabe9055e 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -89,9 +89,7 @@ SYSCTL_INT(_hw, OID_AUTO, uart_noise_threshold, CTLFLAG_RWTUN, * options EARLY_PRINTF=ns8250 */ #if CHECK_EARLY_PRINTF(ns8250) -#if !(defined(__amd64__) || defined(__i386__)) -#error ns8250 early putc is x86 specific as it uses inb/outb -#endif +#if (defined(__amd64__) || defined(__i386__)) static void uart_ns8250_early_putc(int c) { @@ -103,7 +101,45 @@ uart_ns8250_early_putc(int c) continue; outb(tx, c); } +#elif (defined(__arm__) || defined(__aarch64__)) +#ifndef UART_NS8250_EARLY_REG_IO_WIDTH +#error Option 'UART_NS8250_EARLY_REG_IO_WIDTH' is missing. +#endif +#ifndef UART_NS8250_EARLY_REG_SHIFT +#error Option 'UART_NS8250_EARLY_REG_SHIFT' is missing. +#endif + +#if UART_NS8250_EARLY_REG_IO_WIDTH == 1 +#define T uint8_t +#elif UART_NS8250_EARLY_REG_IO_WIDTH == 2 +#define T uint16_t +#elif UART_NS8250_EARLY_REG_IO_WIDTH == 4 +#define T uint32_t + +#else +#error Invalid/unsupported UART_NS8250_EARLY_REG_IO_WIDTH value +#endif + +#include <machine/machdep.h> + +static void +uart_ns8250_early_putc(int c) +{ + volatile T *stat; + volatile T *tx; + + stat = (T *)(socdev_va + (REG_LSR << UART_NS8250_EARLY_REG_SHIFT)); + tx = (T *)(socdev_va + (REG_DATA << UART_NS8250_EARLY_REG_SHIFT)); + + while ((*stat & LSR_THRE) == 0) + continue; + *tx = c & 0xff; +} +#else +#error ns8250 early putc is not implemented for current architecture +#endif early_putc_t *early_putc = uart_ns8250_early_putc; +#undef DTYPE #endif /* EARLY_PRINTF */ /* @@ -963,6 +999,15 @@ ns8250_bus_probe(struct uart_softc *sc) uart_setreg(bas, REG_IER, ier); uart_setreg(bas, REG_MCR, mcr); uart_setreg(bas, REG_FCR, 0); + /* + * The Alder Lake AMT SOL Redirection device will never + * set LSR_OE (when in loopback mode at least) and + * instead block further input by not setting LSR_TEMT. + * Recovering the device afterwards into a working + * state requires re-writing the LCR register. This + * should be harmless on all other devices. + */ + uart_setreg(bas, REG_LCR, uart_getreg(bas, REG_LCR)); uart_barrier(bas); count = 0; goto describe; diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index 6afc693cd347..ae3c4d3218cf 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -367,7 +367,7 @@ static kobj_method_t uart_pl011_methods[] = { KOBJMETHOD(uart_transmit, uart_pl011_bus_transmit), KOBJMETHOD(uart_grab, uart_pl011_bus_grab), KOBJMETHOD(uart_ungrab, uart_pl011_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_pl011_class = { diff --git a/sys/dev/uart/uart_dev_quicc.c b/sys/dev/uart/uart_dev_quicc.c index d6a8846b874e..84d040f64942 100644 --- a/sys/dev/uart/uart_dev_quicc.c +++ b/sys/dev/uart/uart_dev_quicc.c @@ -261,7 +261,7 @@ static kobj_method_t quicc_methods[] = { KOBJMETHOD(uart_transmit, quicc_bus_transmit), KOBJMETHOD(uart_grab, quicc_bus_grab), KOBJMETHOD(uart_ungrab, quicc_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; struct uart_class uart_quicc_class = { diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c index 45bf63f20bb2..56d9c96cd31a 100644 --- a/sys/dev/uart/uart_dev_z8530.c +++ b/sys/dev/uart/uart_dev_z8530.c @@ -297,7 +297,7 @@ static kobj_method_t z8530_methods[] = { KOBJMETHOD(uart_transmit, z8530_bus_transmit), KOBJMETHOD(uart_grab, z8530_bus_grab), KOBJMETHOD(uart_ungrab, z8530_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; struct uart_class uart_z8530_class = { diff --git a/sys/dev/uart/uart_tty.c b/sys/dev/uart/uart_tty.c index d15d1d0c6ac2..7f0f730b3b6e 100644 --- a/sys/dev/uart/uart_tty.c +++ b/sys/dev/uart/uart_tty.c @@ -447,8 +447,9 @@ uart_tty_detach(struct uart_softc *sc) tp = sc->sc_u.u_tty.tp; - tty_lock(tp); swi_remove(sc->sc_softih); + + tty_lock(tp); tty_rel_gone(tp); return (0); |
