]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[uart] Add support for MMIO-accessible 16550 UARTs
authorMichael Brown <mcb30@ipxe.org>
Thu, 19 Jun 2025 11:57:28 +0000 (12:57 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 20 Jun 2025 11:52:04 +0000 (12:52 +0100)
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>
src/include/bits/ns16550.h
src/include/ipxe/ns16550.h

index 4b3e30c76b7e143cda505954f2ac603afa4ca2e9..e40b2a21b4fa9fc8f0eaf95523b70008e2de6aea 100644 (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 */
index f7bb55a84812cc83dc320336099e4625ec309214..3aaab6891c63cc4955384384f144787e700b27cd 100644 (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;
 };