git: 987dc68e66b7 - main - uart: Implement SPCR rev 3 and 4 for PreciseBaudrate and UartClkFreq

From: Warner Losh <imp_at_FreeBSD.org>
Date: Tue, 15 Oct 2024 11:01:18 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=987dc68e66b747815c7a78e3c3e2b5f64e885791

commit 987dc68e66b747815c7a78e3c3e2b5f64e885791
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2024-10-15 11:00:11 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-10-15 11:00:11 +0000

    uart: Implement SPCR rev 3 and 4 for PreciseBaudrate and UartClkFreq
    
    If we have a new enough SPCR, then use it when it provides a
    PreciseBaudrate and/or a UartClkFreq.
    
    Sponsored by:           Netflix
    Reviewed by:            andrew,adrian
    Differential Revision:  https://reviews.freebsd.org/D47097
---
 sys/dev/uart/uart_cpu_acpi.c | 60 ++++++++++++++++++++++++++++----------------
 1 file changed, 39 insertions(+), 21 deletions(-)

diff --git a/sys/dev/uart/uart_cpu_acpi.c b/sys/dev/uart/uart_cpu_acpi.c
index 816738ec31d5..ce00a09fee33 100644
--- a/sys/dev/uart/uart_cpu_acpi.c
+++ b/sys/dev/uart/uart_cpu_acpi.c
@@ -167,28 +167,46 @@ uart_cpu_acpi_spcr(int devtype, struct uart_devinfo *di)
 	if (error != 0)
 		goto out;
 
-	switch (spcr->BaudRate) {
-	case 0:
-		/* Special value; means "keep current value unchanged". */
-		di->baudrate = 0;
-		break;
-	case 3:
-		di->baudrate = 9600;
-		break;
-	case 4:
-		di->baudrate = 19200;
-		break;
-	case 6:
-		di->baudrate = 57600;
-		break;
-	case 7:
-		di->baudrate = 115200;
-		break;
-	default:
-		printf("SPCR has reserved BaudRate value: %d!\n",
-		    (int)spcr->BaudRate);
-		goto out;
+	/*
+	 * SPCR Rev 4 and newer allow a precise baudrate to be passed in for
+	 * things like 1.5M or 2.0M. If we have that, then use that value,
+	 * otherwise try to decode the older enumeration.
+	 */
+	if (spcr->Header.Revision >= 4 && spcr->PreciseBaudrate != 0) {
+		di->baudrate = spcr->PreciseBaudrate;
+	} else {
+		switch (spcr->BaudRate) {
+		case 0:
+			/* Special value; means "keep current value unchanged". */
+			di->baudrate = 0;
+			break;
+		case 3:
+			di->baudrate = 9600;
+			break;
+		case 4:
+			di->baudrate = 19200;
+			break;
+		case 6:
+			di->baudrate = 57600;
+			break;
+		case 7:
+			di->baudrate = 115200;
+			break;
+		default:
+			printf("SPCR has reserved BaudRate value: %d!\n",
+			    (int)spcr->BaudRate);
+			goto out;
+		}
 	}
+
+	/*
+	 * Rev 3 and newer can specify a rclk, use it if it's there. It's
+	 * defined to be 0 when it's not known, and we've initialized rclk to 0
+	 * in uart_cpu_acpi_init_devinfo, so we don't have to test for it.
+	 */
+	if (spcr->Header.Revision >= 3)
+		di->bas.rclk = spcr->UartClkFreq;
+
 	/*
 	 * If no rclk is set, then we will assume the BIOS has configured the
 	 * hardware at the stated baudrate, so we can use it to guess the rclk