[prev in list] [next in list] [prev in thread] [next in thread]
List: grub-devel
Subject: [PATCH v3 7/8] ns8250: Support more MMIO access sizes
From: Benjamin Herrenschmidt <benh () kernel ! crashing ! org>
Date: 2022-12-23 1:47:58
Message-ID: 20221223014759.2112747-8-benh () kernel ! crashing ! org
[Download RAW message or body]
From: Benjamin Herrenschmidt <benh@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 <benh@kernel.crashing.org>
---
grub-core/term/ns8250-spcr.c | 3 +-
grub-core/term/ns8250.c | 67 ++++++++++++++++++++++++++++++------
include/grub/serial.h | 10 ++++--
3 files changed, 67 insertions(+), 13 deletions(-)
diff --git a/grub-core/term/ns8250-spcr.c b/grub-core/term/ns8250-spcr.c
index 0b4417a30..f4b718833 100644
--- a/grub-core/term/ns8250-spcr.c
+++ b/grub-core/term/ns8250-spcr.c
@@ -74,7 +74,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 d9d93fcf8..98f0b3bc3 100644
--- a/grub-core/term/ns8250.c
+++ b/grub-core/term/ns8250.c
@@ -42,16 +42,59 @@ ns8250_reg_read (struct grub_serial_port *port, grub_addr_t reg)
{
asm volatile("" : : : "memory");
if (port->mmio)
- return *((volatile grub_uint8_t *) (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:
+ /* ACPI tables occasionally uses "0" (legacy) as equivalent to "1" (byte) */
+ case 1:
+ return *((volatile grub_uint8_t *) (port->mmio_base + reg));
+ case 2:
+ return grub_le_to_cpu16 (*((volatile grub_uint16_t *) (port->mmio_base + (reg << 1))));
+ case 3:
+ return grub_le_to_cpu32 (*((volatile grub_uint32_t *) (port->mmio_base + (reg << 2))));
+ case 4:
+ /*
+ * This will only work properly on 64-bit systems since 64-bit
+ * accessors aren't atomic on 32-bit hardware. Thankfully the
+ * case of a UART with a 64-bit register spacing on 32-bit
+ * also probably doesn't exist.
+ */
+ return grub_le_to_cpu64 (*((volatile grub_uint64_t *) (port->mmio_base + (reg << 3))));
+ }
+ }
return grub_inb (port->port + reg);
}
static void
-ns8250_reg_write (struct grub_serial_port *port, grub_uint8_t, grub_addr_t reg)
+ns8250_reg_write (struct grub_serial_port *port, grub_uint8_t value, grub_addr_t reg)
{
asm volatile("" : : : "memory");
if (port->mmio)
- *((volatile grub_uint8_t *) (port->mmio_base + reg)) = value;
+ {
+ switch(port->access_size)
+ {
+ default:
+ /* ACPI tables occasionally uses "0" (legacy) as equivalent to "1" (byte) */
+ case 1:
+ *((volatile grub_uint8_t *) (port->mmio_base + reg)) = value;
+ break;
+ case 2:
+ *((volatile grub_uint16_t *) (port->mmio_base + (reg << 1))) = grub_cpu_to_le16 (value);
+ break;
+ case 3:
+ *((volatile grub_uint32_t *) (port->mmio_base + (reg << 2))) = grub_cpu_to_le32 (value);
+ break;
+ case 4:
+ /* See commment in ns8250_reg_read() */
+ *((volatile grub_uint64_t *) (port->mmio_base + (reg << 3))) = grub_cpu_to_le64 (value);
+ break;
+ }
+ }
else
grub_outb (value, port->port + reg);
}
@@ -286,6 +329,7 @@ grub_ns8250_init (void)
grub_print_error ();
grub_serial_register (&com_ports[i]);
+ com_ports[i].access_size = 1;
}
}
@@ -312,12 +356,12 @@ grub_serial_ns8250_add_port (grub_port_t port, struct grub_serial_config *config
for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
if (com_ports[i].port == port)
{
- if (dead_ports & (1 << i))
- return NULL;
- /* give the opportunity for SPCR to configure a default com port */
- if (config != NULL)
- grub_serial_port_configure (&com_ports[i], config);
- return com_names[i];
+ if (dead_ports & (1 << i))
+ return NULL;
+ /* give the opportunity for SPCR to configure a default com port */
+ if (config != NULL)
+ grub_serial_port_configure (&com_ports[i], config);
+ return com_names[i];
}
grub_outb (0x5a, port + UART_SR);
@@ -340,6 +384,7 @@ grub_serial_ns8250_add_port (grub_port_t port, struct grub_serial_config *config
p->driver = &grub_ns8250_driver;
p->mmio = false;
p->port = port;
+ p->access_size = 1;
if (config != NULL)
grub_serial_port_configure (p, config);
else
@@ -350,7 +395,8 @@ 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;
@@ -375,6 +421,7 @@ grub_serial_ns8250_add_mmio (grub_addr_t addr, struct grub_serial_config *config
p->driver = &grub_ns8250_driver;
p->mmio = true;
p->mmio_base = addr;
+ p->access_size = acc_size;
if (config != NULL)
grub_serial_port_configure (p, config);
else
diff --git a/include/grub/serial.h b/include/grub/serial.h
index 8d6ed56a3..65ccab4ff 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 */
+ grub_uint8_t access_size;
+ };
};
};
struct
@@ -187,7 +192,8 @@ 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
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic