[dwuart] Read input clock frequency from the device tree

The 16550 design includes a programmable 16-bit clock divider for an
arbitrary input clock, requiring knowledge of the input clock
frequency in order to calculate the divider value for a given baud
rate.  The 16550 UARTs in an x86 PC will always have a 1.8432 MHz
input clock.  Non-x86 systems may have other input clock frequencies.

Define the input clock frequency as a property of a 16550 UART, and
read the value from the device tree "clock-frequency" property.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-06-23 22:40:04 +01:00
parent 0ed1dea7f4
commit 9ada09c919
4 changed files with 19 additions and 4 deletions

View File

@@ -46,6 +46,7 @@ static int dwuart_probe ( struct dt_device *dt, unsigned int offset ) {
struct ns16550_uart *ns16550;
struct uart *uart;
uint32_t shift;
uint32_t clock;
int rc;
/* Allocate and initialise UART */
@@ -71,6 +72,13 @@ static int dwuart_probe ( struct dt_device *dt, unsigned int offset ) {
shift = 0;
ns16550->shift = shift;
/* Get clock rate */
if ( ( rc = fdt_u32 ( &sysfdt, offset, "clock-frequency",
&clock ) ) != 0 ) {
clock = NS16550_CLK_DEFAULT;
}
ns16550->clock = clock;
/* Register UART */
if ( ( rc = uart_register ( uart ) ) != 0 )
goto err_register;

View File

@@ -138,7 +138,8 @@ static int ns16550_init ( struct uart *uart, unsigned int baud ) {
ns16550_write ( ns16550, NS16550_LCR,
( NS16550_LCR_8N1 | NS16550_LCR_DLAB ) );
if ( baud ) {
ns16550->divisor = ( NS16550_MAX_BAUD / baud );
ns16550->divisor = ( ( ns16550->clock / baud ) /
NS16550_CLK_BIT );
dlm = ( ( ns16550->divisor >> 8 ) & 0xff );
dll = ( ( ns16550->divisor >> 0 ) & 0xff );
ns16550_write ( ns16550, NS16550_DLM, dlm );