[uart] Add support for MMIO-accessible 16550 UARTs

16550 UARTs exist on non-x86 platforms but will be accessible via MMIO
rather than port I/O.  It is possible to encounter MMIO-mapped 16550
UARTs on x86 platforms, but there is no real requirement to support
them in iPXE since the standard COM1, COM2, etc ports have been
present on every PC-compatible machine since 1981.

Assume for now that accessing 16550 UART registers requires
inb()/outb() on x86 and readb()/writeb() on other architectures.

Allow for the existence of a register shift on MMIO-mapped 16550
UARTs, since modern SoCs tend to treat register addresses as being
aligned to either 32-bit or 64-bit boundaries.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-06-19 12:57:28 +01:00
parent 6c8fb4b89d
commit 71b4bfb6b2
2 changed files with 33 additions and 4 deletions

View File

@@ -3,13 +3,40 @@
/** @file
*
* Dummy architecture-specific 16550-compatible UART
*
* This file is included only if the architecture does not provide its
* own version of this file.
* 16550-compatible UART
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/io.h>
/**
* Write to UART register
*
* @v ns16550 16550 UART
* @v address Register address
* @v data Data
*/
static inline __attribute__ (( always_inline )) void
ns16550_write ( struct ns16550_uart *ns16550, unsigned int address,
uint8_t data ) {
writeb ( data, ( ns16550->base + ( address << ns16550->shift ) ) );
}
/**
* Read from UART register
*
* @v ns16550 16550 UART
* @v address Register address
* @ret data Data
*/
static inline __attribute__ (( always_inline )) uint8_t
ns16550_read ( struct ns16550_uart *ns16550, unsigned int address ) {
return readb ( ns16550->base + ( address << ns16550->shift ) );
}
#endif /* _BITS_NS16550_H */

View File

@@ -82,6 +82,8 @@ struct ns16550_uart {
struct uart uart;
/** Register base address */
void *base;
/** Register shift */
unsigned int shift;
/** Baud rate divisor */
uint16_t divisor;
};