Index: sys/dev/acpica/acpi.c =================================================================== --- sys/dev/acpica/acpi.c +++ sys/dev/acpica/acpi.c @@ -2221,6 +2221,15 @@ return (FALSE); status = acpi_GetInteger(h, "_STA", &s); + /* + * Onboard serial ports on certain AMD motherboards have an invalid _STA + * method that always returns 0. Force them to always be treated as present. + * + * This may solely be a quirk of a preproduction BIOS. + */ + if (acpi_MatchHid(h, "AMDI0020") || acpi_MatchHid(h, "AMDI0010")) + return (TRUE); + /* If no _STA method, must be present */ if (ACPI_FAILURE(status)) return (status == AE_NOT_FOUND ? TRUE : FALSE); Index: sys/dev/uart/uart_bus_acpi.c =================================================================== --- sys/dev/uart/uart_bus_acpi.c +++ sys/dev/uart/uart_bus_acpi.c @@ -27,6 +27,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_acpi.h" + #include #include #include @@ -37,17 +39,12 @@ #include #include -#include - #include #include #include - -#ifdef __aarch64__ #include #include #include -#endif static int uart_acpi_probe(device_t dev); @@ -66,59 +63,38 @@ sizeof(struct uart_softc), }; -#if defined(__i386__) || defined(__amd64__) -static struct isa_pnp_id acpi_ns8250_ids[] = { - {0x0005d041, "Standard PC COM port"}, /* PNP0500 */ - {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */ - {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */ - {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */ - {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */ - {0x04f0235c, "Wacom Tablet PC Screen"}, /* WACF004 */ - {0x0ef0235c, "Wacom Tablet PC Screen 00e"}, /* WACF00e */ - {0xe502aa1a, "Wacom Tablet at FuS Lifebook T"}, /* FUJ02E5 */ - {0} -}; -#endif - -#ifdef __aarch64__ -static struct uart_class * +static struct acpi_uart_compat_data * uart_acpi_find_device(device_t dev) { - struct acpi_uart_compat_data **cd; + struct acpi_uart_compat_data **cd, *cd_it; ACPI_HANDLE h; if ((h = acpi_get_handle(dev)) == NULL) return (NULL); SET_FOREACH(cd, uart_acpi_class_and_device_set) { - if (acpi_MatchHid(h, (*cd)->hid)) { - return ((*cd)->clas); + for (cd_it = *cd; cd_it->cd_hid != NULL; cd_it++) { + if (acpi_MatchHid(h, cd_it->cd_hid)) + return (cd_it); } } return (NULL); } -#endif static int uart_acpi_probe(device_t dev) { struct uart_softc *sc; + struct acpi_uart_compat_data *cd; sc = device_get_softc(dev); -#if defined(__i386__) || defined(__amd64__) - if (!ISA_PNP_PROBE(device_get_parent(dev), dev, acpi_ns8250_ids)) { - sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0, 0, 0)); + if ((cd = uart_acpi_find_device(dev)) != NULL) { + sc->sc_class = cd->cd_class; + return (uart_bus_probe(dev, cd->cd_regshft, cd->cd_regiowidth, + cd->cd_rclk, 0, 0)); } - - /* Add checks for non-ns8250 IDs here. */ -#elif defined(__aarch64__) - if ((sc->sc_class = uart_acpi_find_device(dev)) != NULL) - return (uart_bus_probe(dev, 2, 0, 0, 0, 0)); -#endif - return (ENXIO); } Index: sys/dev/uart/uart_cpu_acpi.h =================================================================== --- sys/dev/uart/uart_cpu_acpi.h +++ sys/dev/uart/uart_cpu_acpi.h @@ -38,9 +38,14 @@ struct uart_class; struct acpi_uart_compat_data { - const char *hid; - struct uart_class *clas; - uint16_t port_subtype; + const char *cd_hid; + struct uart_class *cd_class; + + uint16_t cd_port_subtype; + int cd_regshft; + int cd_regiowidth; + int cd_rclk; + const char *cd_desc; }; /* Index: sys/dev/uart/uart_cpu_arm64.c =================================================================== --- sys/dev/uart/uart_cpu_arm64.c +++ sys/dev/uart/uart_cpu_arm64.c @@ -147,7 +147,7 @@ if (err != 0) goto out; - *classp = cd->clas; + *classp = cd->class; *rclk = 0; *shiftp = 2; *iowidthp = spcr->SerialPort.BitWidth / 8; Index: sys/dev/uart/uart_dev_ns8250.c =================================================================== --- sys/dev/uart/uart_dev_ns8250.c +++ sys/dev/uart/uart_dev_ns8250.c @@ -26,6 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_acpi.h" #include "opt_platform.h" #include "opt_uart.h" @@ -54,6 +55,13 @@ #include #include #include +#ifdef DEV_ACPI +#include +#include +#include +#include +#include +#endif #include @@ -404,6 +412,58 @@ .uc_rshift = 0 }; +#ifdef DEV_ACPI +static int +snps_bus_attach(struct uart_softc *sc) +{ + + sc->sc_bas.busy_detect = 1; + return ns8250_bus_attach(sc); +} + +static kobj_method_t snps_methods[] = { + KOBJMETHOD(uart_attach, snps_bus_attach), + KOBJMETHOD(uart_detach, ns8250_bus_detach), + KOBJMETHOD(uart_flush, ns8250_bus_flush), + KOBJMETHOD(uart_getsig, ns8250_bus_getsig), + KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl), + KOBJMETHOD(uart_ipend, ns8250_bus_ipend), + KOBJMETHOD(uart_param, ns8250_bus_param), + KOBJMETHOD(uart_probe, ns8250_bus_probe), + KOBJMETHOD(uart_receive, ns8250_bus_receive), + KOBJMETHOD(uart_setsig, ns8250_bus_setsig), + KOBJMETHOD(uart_transmit, ns8250_bus_transmit), + KOBJMETHOD(uart_grab, ns8250_bus_grab), + KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab), + { 0, 0 } +}; + +static struct uart_class uart_snps_class = { + "snps", + snps_methods, + sizeof(struct ns8250_softc), + .uc_ops = &uart_ns8250_ops, + .uc_range = 8, + .uc_rclk = DEFAULT_RCLK, + .uc_rshift = 0 +}; + +static struct acpi_uart_compat_data acpi_compat_data[] = { + {"AMD0020", &uart_snps_class, 0, 2, 0, 48000000, "AMD / Synopsys Designware UART"}, + {"AMDI0020", &uart_snps_class, 0, 2, 0, 48000000, "AMD / Synopsys Designware UART"}, + {"PNP0500", &uart_ns8250_class, 0, 0, 0, 0, "Standard PC COM port"}, + {"PNP0501", &uart_ns8250_class, 0, 0, 0, 0, "16550A-compatible COM port"}, + {"PNP0502", &uart_ns8250_class, 0, 0, 0, 0, "Multiport serial device (non-intelligent 16550)"}, + {"PNP0510", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"}, + {"PNP0511", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"}, + {"WACF004", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen"}, + {"WACF00E", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen 00e"}, + {"FUJ02E5", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet at FuS Lifebook T"}, + {NULL, NULL, 0, 0 , 0, 0, NULL}, +}; +UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data); +#endif + #ifdef FDT static struct ofw_compat_data compat_data[] = { {"ns16550", (uintptr_t)&uart_ns8250_class}, Index: sys/dev/uart/uart_dev_pl011.c =================================================================== --- sys/dev/uart/uart_dev_pl011.c +++ sys/dev/uart/uart_dev_pl011.c @@ -342,9 +342,9 @@ #ifdef DEV_ACPI static struct acpi_uart_compat_data acpi_compat_data[] = { - {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_PL011}, - {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC}, - {NULL, NULL, 0}, + {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_PL011, 2, 0, 0, "pl011"}, + {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC, 2, 0, 0, "pl011"}, + {NULL, NULL, 0, 0, 0, 0, NULL}, }; UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data); #endif Index: sys/modules/uart/Makefile =================================================================== --- sys/modules/uart/Makefile +++ sys/modules/uart/Makefile @@ -37,6 +37,6 @@ SRCS+= acpi_if.h bus_if.h card_if.h device_if.h isa_if.h ${ofw_bus_if} \ pci_if.h \ power_if.h pccarddevs.h serdev_if.h -SRCS+= opt_platform.h opt_uart.h +SRCS+= opt_acpi.h opt_platform.h opt_uart.h .include