This adds the ability for the driver to access UARTs via MMIO instead
of PIO selectively at runtime, and exposes a new function to add an
MMIO port.
I had a couple of sleepless nights trying to find out why this didn't work for my MMIO UART (Intel Cannon Lake PCH Intel C246), so I thought I would share my findings with others in a similar situation. (See below.)
diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c
index 39809d042..183e14b3b 100644
--- a/grub-core/term/ns8250.c
+++ b/grub-core/term/ns8250.c
@@ -44,6 +44,24 @@ static int dead_ports = 0;
#define DEFAULT_BASE_CLOCK 115200
#endif
+static inline unsigned char
+ns8250_reg_read (struct grub_serial_port *port, grub_addr_t reg)
+{
+ asm volatile("" : : : "memory");
+ if (port->mmio)
+ return *((volatile unsigned char *)(port->mmio_base + reg));
+ return grub_inb (port->port + reg);
+}
+
+static inline void
+ns8250_reg_write (struct grub_serial_port *port, unsigned char value, grub_addr_t reg)
+{
+ asm volatile("" : : : "memory");
+ if (port->mmio)
+ *((volatile char *)(port->mmio_base + reg)) = value;
+ else
+ grub_outb (value, port->port + reg);
+}
This code assumes that the registers are only 8 bit wide. Apparently for my chipset they are 32 bits wide, so it only (finally) worked when I rewrote this code to address and write full grub_uint32_t values, like this:
------
volatile grub_uint32_t* p = (void*)(port->mmio_base);
*(p + reg) = (grub_uint32_t)(value);
------
Cheers
Sven