aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/uart
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/uart')
-rw-r--r--sys/dev/uart/uart_bus_acpi.c2
-rw-r--r--sys/dev/uart/uart_bus_fdt.c2
-rw-r--r--sys/dev/uart/uart_bus_isa.c2
-rw-r--r--sys/dev/uart/uart_bus_pci.c56
-rw-r--r--sys/dev/uart/uart_bus_puc.c2
-rw-r--r--sys/dev/uart/uart_bus_scc.c2
-rw-r--r--sys/dev/uart/uart_dev_imx.c2
-rw-r--r--sys/dev/uart/uart_dev_lowrisc.c2
-rw-r--r--sys/dev/uart/uart_dev_mu.c2
-rw-r--r--sys/dev/uart/uart_dev_mvebu.c2
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c51
-rw-r--r--sys/dev/uart/uart_dev_pl011.c2
-rw-r--r--sys/dev/uart/uart_dev_quicc.c2
-rw-r--r--sys/dev/uart/uart_dev_z8530.c2
-rw-r--r--sys/dev/uart/uart_tty.c3
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);