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);
}