Index: sys/dev/uart/uart_bus.h =================================================================== --- sys/dev/uart/uart_bus.h +++ sys/dev/uart/uart_bus.h @@ -58,6 +58,7 @@ /* UART quirk flags */ #define UART_F_BUSY_DETECT 0x1 +#define UART_F_IGNORE_SPCR_REGSHFT 0x2 /* * UART class & instance (=softc) Index: sys/dev/uart/uart_bus_pci.c =================================================================== --- sys/dev/uart/uart_bus_pci.c +++ sys/dev/uart/uart_bus_pci.c @@ -43,6 +43,7 @@ #include #include +#include #define DEFAULT_RCLK 1843200 @@ -190,10 +191,13 @@ return ((id->vendor == vendor && id->device == device) ? id : NULL); } +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; + static int uart_pci_probe(device_t dev) { struct uart_softc *sc; + struct uart_devinfo *sysdev; const struct pci_id *id; int result; @@ -208,6 +212,16 @@ return (ENXIO); match: + SLIST_FOREACH(sysdev, &uart_sysdevs, next) { + if (sysdev->pci_info.vendor == pci_get_vendor(dev) + && sysdev->pci_info.device == pci_get_device(dev) + && sysdev->pci_info.bus == pci_get_bus(dev) + && sysdev->pci_info.slot == pci_get_slot(dev)) { + sc->sc_sysdev = sysdev; + sysdev->bas.rclk = sc->sc_bas.rclk; + } + } + result = uart_bus_probe(dev, id->regshft, 0, id->rclk, id->rid, 0, 0); /* Bail out on error. */ if (result > 0) Index: sys/dev/uart/uart_cpu.h =================================================================== --- sys/dev/uart/uart_cpu.h +++ sys/dev/uart/uart_cpu.h @@ -52,6 +52,16 @@ extern bus_space_tag_t uart_bus_space_io; extern bus_space_tag_t uart_bus_space_mem; +/* + * PCI bus address from the ACPI SPCR table. + */ +struct uart_pci_info { + uint16_t vendor; + uint16_t device; + uint8_t bus; + uint8_t slot; +}; + /* * Console and debug port device info. */ @@ -72,6 +82,7 @@ void *cookie; /* Type dependent use. */ struct mtx *hwmtx; struct uart_softc *sc; /* valid only from start of attach */ + struct uart_pci_info pci_info; }; int uart_cpu_eqres(struct uart_bas *, struct uart_bas *); Index: sys/dev/uart/uart_cpu_arm64.c =================================================================== --- sys/dev/uart/uart_cpu_arm64.c +++ sys/dev/uart/uart_cpu_arm64.c @@ -109,7 +109,7 @@ static int uart_cpu_acpi_probe(struct uart_class **classp, bus_space_tag_t *bst, bus_space_handle_t *bsh, int *baud, u_int *rclk, u_int *shiftp, - u_int *iowidthp) + u_int *iowidthp, struct uart_pci_info *pcip) { struct acpi_uart_compat_data *cd; ACPI_TABLE_SPCR *spcr; @@ -153,6 +153,19 @@ *shiftp = spcr->SerialPort.AccessWidth - 1; *iowidthp = spcr->SerialPort.BitWidth / 8; + if (spcr->InterfaceType == ACPI_DBG2_ARM_SBSA_32BIT) { + *shiftp = 2; + } + + if (cd->cd_quirks & UART_F_IGNORE_SPCR_REGSHFT) { + *shiftp = cd->cd_regshft; + } + + pcip->vendor = spcr->PciVendorId; + pcip->device = spcr->PciDeviceId; + pcip->bus = spcr->PciBus; + pcip->slot = spcr->PciDevice; + out: acpi_unmap_table(spcr); return (err); @@ -180,7 +193,7 @@ err = ENXIO; #ifdef DEV_ACPI err = uart_cpu_acpi_probe(&class, &bst, &bsh, &br, &rclk, &shift, - &iowidth); + &iowidth, &di->pci_info); #endif #ifdef FDT if (err != 0) { Index: sys/dev/uart/uart_dev_pl011.c =================================================================== --- sys/dev/uart/uart_dev_pl011.c +++ sys/dev/uart/uart_dev_pl011.c @@ -342,8 +342,8 @@ #ifdef DEV_ACPI static struct acpi_uart_compat_data acpi_compat_data[] = { - {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_PL011, 2, 0, 0, 0, "uart plo11"}, - {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC, 2, 0, 0, 0, "uart plo11"}, + {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_PL011, 2, 0, 0, UART_F_IGNORE_SPCR_REGSHFT, "uart plo11"}, + {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC, 2, 0, 0, UART_F_IGNORE_SPCR_REGSHFT, "uart plo11"}, {NULL, NULL, 0, 0, 0, 0, 0, NULL}, }; UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data);