git: 097bd33dd7a6 - main - uart: DBG2 support to find the debug uart
Date: Fri, 17 May 2024 16:12:49 UTC
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=097bd33dd7a687cd3ad7fd4bc7ededa3b9e00e28 commit 097bd33dd7a687cd3ad7fd4bc7ededa3b9e00e28 Author: Andrew Turner <andrew@FreeBSD.org> AuthorDate: 2024-03-12 18:15:29 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> CommitDate: 2024-05-17 16:07:15 +0000 uart: DBG2 support to find the debug uart The Debug Port Table 2 (DBG2) contains information on which devices can be used for debugging purposes. Add support to the uart driver to use the DBG2 table when enabled from loader. Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D44359 --- sys/dev/uart/uart_cpu_acpi.c | 83 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/sys/dev/uart/uart_cpu_acpi.c b/sys/dev/uart/uart_cpu_acpi.c index 9c9ffc1e3194..53fe459e64a1 100644 --- a/sys/dev/uart/uart_cpu_acpi.c +++ b/sys/dev/uart/uart_cpu_acpi.c @@ -210,12 +210,95 @@ out: return (error); } +static int +uart_cpu_acpi_dbg2(struct uart_devinfo *di) +{ + vm_paddr_t dbg2_physaddr; + ACPI_TABLE_DBG2 *dbg2; + ACPI_DBG2_DEVICE *dbg2_dev; + ACPI_GENERIC_ADDRESS *base_address; + struct acpi_uart_compat_data *cd; + struct uart_class *class; + int error; + bool found; + + /* Look for the SPCR table. */ + dbg2_physaddr = acpi_find_table(ACPI_SIG_DBG2); + if (dbg2_physaddr == 0) + return (ENXIO); + + dbg2 = acpi_map_table(dbg2_physaddr, ACPI_SIG_DBG2); + if (dbg2 == NULL) { + printf("Unable to map the DBG2 table!\n"); + return (ENXIO); + } + + error = ENXIO; + + dbg2_dev = (ACPI_DBG2_DEVICE *)((vm_offset_t)dbg2 + dbg2->InfoOffset); + found = false; + while ((vm_offset_t)dbg2_dev + dbg2_dev->Length <= + (vm_offset_t)dbg2 + dbg2->Header.Length) { + if (dbg2_dev->PortType != ACPI_DBG2_SERIAL_PORT) + goto next; + + /* XXX: Too restrictive? */ + if (dbg2_dev->RegisterCount != 1) + goto next; + + cd = uart_cpu_acpi_scan(dbg2_dev->PortSubtype); + if (cd == NULL) + goto next; + + class = cd->cd_class; + base_address = (ACPI_GENERIC_ADDRESS *) + ((vm_offset_t)dbg2_dev + dbg2_dev->BaseAddressOffset); + + error = uart_cpu_acpi_init_devinfo(di, class, base_address); + if (error == 0) { + found = true; + break; + } + +next: + dbg2_dev = (ACPI_DBG2_DEVICE *) + ((vm_offset_t)dbg2_dev + dbg2_dev->Length); + } + if (!found) + goto out; + + /* XXX: Find the correct value */ + di->baudrate = 115200; + + /* Apply device tweaks. */ + if ((cd->cd_quirks & UART_F_IGNORE_SPCR_REGSHFT) == + UART_F_IGNORE_SPCR_REGSHFT) { + di->bas.regshft = cd->cd_regshft; + } + + /* Create a bus space handle. */ + error = bus_space_map(di->bas.bst, base_address->Address, + uart_getrange(class), 0, &di->bas.bsh); + +out: + acpi_unmap_table(dbg2); + return (error); +} + int uart_cpu_acpi_setup(int devtype, struct uart_devinfo *di) { + char *cp; + switch(devtype) { case UART_DEV_CONSOLE: return (uart_cpu_acpi_spcr(devtype, di)); + case UART_DEV_DBGPORT: + /* Use the Debug Port Table 2 (DBG2) to find a debug uart */ + cp = kern_getenv("hw.acpi.enable_dbg2"); + if (cp != NULL && strcasecmp(cp, "yes") == 0) + return (uart_cpu_acpi_dbg2(di)); + break; } return (ENXIO); }