mirror of
https://github.com/ipxe/ipxe
synced 2025-12-12 23:15:10 +03:00
[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:
@@ -37,6 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define ISA_UART( NAME, BASE ) \
|
||||
static struct ns16550_uart ns16550_ ## NAME = { \
|
||||
.base = ( ( void * ) (BASE) ), \
|
||||
.clock = NS16550_CLK_DEFAULT, \
|
||||
}; \
|
||||
struct uart NAME = { \
|
||||
.refcnt = REF_INIT ( ref_no_free ), \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -73,19 +73,24 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
/** Divisor latch (most significant byte) */
|
||||
#define NS16550_DLM 0x01
|
||||
|
||||
/** Maximum baud rate */
|
||||
#define NS16550_MAX_BAUD 115200
|
||||
|
||||
/** A 16550-compatible UART */
|
||||
struct ns16550_uart {
|
||||
/** Register base address */
|
||||
void *base;
|
||||
/** Register shift */
|
||||
unsigned int shift;
|
||||
/** Input clock frequency */
|
||||
unsigned int clock;
|
||||
/** Baud rate divisor */
|
||||
uint16_t divisor;
|
||||
};
|
||||
|
||||
/** Post-division clock cycles per data bit */
|
||||
#define NS16550_CLK_BIT 16
|
||||
|
||||
/** Default input clock rate (1.8432 MHz) */
|
||||
#define NS16550_CLK_DEFAULT 1843200
|
||||
|
||||
#include <bits/ns16550.h>
|
||||
|
||||
/** Dummy COM1 UART for non-x86 platforms
|
||||
|
||||
Reference in New Issue
Block a user