From: Benjamin Herrenschmidt <b...@amazon.com> It is common for PCI based UARTs to use larger than one byte access sizes. This adds support for this and uses the information present in SPCR accordingly.
Signed-off-by: Benjamin Herrenschmidt <b...@kernel.crashing.org> --- grub-core/term/ns8250-spcr.c | 3 ++- grub-core/term/ns8250.c | 45 +++++++++++++++++++++++++++++++++--- include/grub/serial.h | 9 ++++++-- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/grub-core/term/ns8250-spcr.c b/grub-core/term/ns8250-spcr.c index 0786aee1b..dd589af60 100644 --- a/grub-core/term/ns8250-spcr.c +++ b/grub-core/term/ns8250-spcr.c @@ -73,7 +73,8 @@ grub_ns8250_spcr_init (void) switch (spcr->base_addr.space_id) { case GRUB_ACPI_GENADDR_MEM_SPACE: - return grub_serial_ns8250_add_mmio(spcr->base_addr.addr, &config); + return grub_serial_ns8250_add_mmio(spcr->base_addr.addr, + spcr->base_addr.access_size, &config); case GRUB_ACPI_GENADDR_IO_SPACE: return grub_serial_ns8250_add_port(spcr->base_addr.addr, &config); default: diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index 08dfb99da..76f68c037 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -48,7 +48,26 @@ 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)); + { + /* Note: we assume MMIO UARTs are little endian. This is not true of all + * embedded platforms but will do for now + */ + switch(port->access_size) + { + default: + case 1: + return *((volatile unsigned char *)(port->mmio_base + reg)); + case 2: + return grub_le_to_cpu16(*((volatile unsigned short *)(port->mmio_base + (reg << 1)))); + case 3: + return grub_le_to_cpu32(*((volatile unsigned long *)(port->mmio_base + (reg << 2)))); + case 4: + /* This will only work properly on 64-bit systems, thankfully it + * also probably doesn't exist + */ + return grub_le_to_cpu64(*((volatile unsigned long long *)(port->mmio_base + (reg << 3)))); + } + } return grub_inb (port->port + reg); } @@ -57,7 +76,24 @@ ns8250_reg_write (struct grub_serial_port *port, unsigned char value, grub_addr_ { asm volatile("" : : : "memory"); if (port->mmio) - *((volatile char *)(port->mmio_base + reg)) = value; + { + switch(port->access_size) + { + default: + case 1: + *((volatile unsigned char *)(port->mmio_base + reg)) = value; + break; + case 2: + *((volatile unsigned short *)(port->mmio_base + (reg << 1))) = grub_cpu_to_le16(value); + break; + case 3: + *((volatile unsigned long *)(port->mmio_base + (reg << 2))) = grub_cpu_to_le32(value); + break; + case 4: + *((volatile unsigned long long *)(port->mmio_base + (reg << 3))) = grub_cpu_to_le64(value); + break; + } + } else grub_outb (value, port->port + reg); } @@ -285,6 +321,7 @@ grub_ns8250_init (void) grub_print_error (); grub_serial_register (&com_ports[i]); + com_ports[i].access_size = 1; } } @@ -338,6 +375,7 @@ grub_serial_ns8250_add_port (grub_port_t port, struct grub_serial_config *config p->driver = &grub_ns8250_driver; p->mmio = 0; p->port = port; + p->access_size = 1; if (config) grub_serial_port_configure (p, config); else @@ -348,7 +386,7 @@ grub_serial_ns8250_add_port (grub_port_t port, struct grub_serial_config *config } char * -grub_serial_ns8250_add_mmio(grub_addr_t addr, struct grub_serial_config *config) +grub_serial_ns8250_add_mmio(grub_addr_t addr, unsigned int acc_size, struct grub_serial_config *config) { struct grub_serial_port *p; unsigned i; @@ -372,6 +410,7 @@ grub_serial_ns8250_add_mmio(grub_addr_t addr, struct grub_serial_config *config) p->driver = &grub_ns8250_driver; p->mmio = 1; p->mmio_base = addr; + p->access_size = acc_size; if (config) grub_serial_port_configure (p, config); else diff --git a/include/grub/serial.h b/include/grub/serial.h index 646bdf1bb..8875eaf82 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -94,7 +94,12 @@ struct grub_serial_port #if defined(__mips__) || defined (__i386__) || defined (__x86_64__) grub_port_t port; #endif - grub_addr_t mmio_base; + struct + { + grub_addr_t mmio_base; + /* Access size uses ACPI definition */ + unsigned int access_size; + }; }; }; struct @@ -187,7 +192,7 @@ grub_serial_config_defaults (struct grub_serial_port *port) void grub_ns8250_init (void); char * grub_ns8250_spcr_init (void); char *grub_serial_ns8250_add_port (grub_port_t port, struct grub_serial_config *config); -char *grub_serial_ns8250_add_mmio(grub_addr_t addr, struct grub_serial_config *config); +char *grub_serial_ns8250_add_mmio(grub_addr_t addr, unsigned int acc_size, struct grub_serial_config *config); #endif #ifdef GRUB_MACHINE_IEEE1275 void grub_ofserial_init (void); -- 2.34.1 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel