git: fc59fc3c1f63 - main - uart: Honour clock-frequency in FDT for UART_FDT_CLASS if present

From: Jessica Clarke <jrtc27_at_FreeBSD.org>
Date: Wed, 15 May 2024 15:53:53 UTC
The branch main has been updated by jrtc27:

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

commit fc59fc3c1f632e011347614ee9704fe00e51002e
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2024-05-15 15:53:33 +0000
Commit:     Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2024-05-15 15:53:33 +0000

    uart: Honour clock-frequency in FDT for UART_FDT_CLASS if present
    
    The StarFive VisionFive 2 has a Synopsys DesignWare ABP UART, whose
    driver uses UART_FDT_CLASS rather than UART_FDT_CLASS_AND_DEVICE as it
    has its own separate newbus driver. This UART is driven by a 24MHz clock
    as specified in the FDT, but we don't currently look at the property
    here, instead passing down 0 and letting the default value be used in
    the 8250 driver (~1.8MHz). As a result the divisor is misconfigured for
    the current baud rate for the entire kernel boot process. Once the
    newbus driver attaches the correct frequency is saved in the softc, but
    that does not take effect until the next time ns8250_param is called and
    the divisor is recalculated, namely when userspace runs and /dev/console
    is opened (note that ns8250_init does not get called when the newbus
    device corresponding to the current console attaches).
    
    Fix this issue by attemmpting to get the current clock frequency as for
    the UART_FDT_CLASS_AND_DEVICE_CASE, but falling back to 0 rather than
    failing on error.
    
    Reviewed by:    imp, mhorne
    Differential Revision:  https://reviews.freebsd.org/D45159
---
 sys/dev/uart/uart_bus_fdt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c
index 7725d09e212b..431f2962adb2 100644
--- a/sys/dev/uart/uart_bus_fdt.c
+++ b/sys/dev/uart/uart_bus_fdt.c
@@ -234,7 +234,8 @@ uart_cpu_fdt_probe(struct uart_class **classp, bus_space_tag_t *bst,
 		    (struct uart_class *)uart_fdt_find_by_node(node, 1);
 		if (class == NULL)
 			return (ENXIO);
-		clk = 0;
+		if (uart_fdt_get_clock(node, &clk) != 0)
+			clk = 0;
 	}
 
 	/*