grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 6/7] ns8250: Support more MMIO access sizes


From: Benjamin Herrenschmidt
Subject: [PATCH 6/7] ns8250: Support more MMIO access sizes
Date: Fri, 2 Dec 2022 10:05:25 +1100

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      | 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]