[haiku-commits] haiku: hrev53569 - src/add-ons/kernel/bus_managers/fdt

  • From: Alex von Gluck IV <kallisti5@xxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 29 Oct 2019 13:40:38 -0400 (EDT)

hrev53569 adds 1 changeset to branch 'master'
old head: bc3b6065c6701704712d99f3eec5c2aa41fadb65
new head: 9d010ea47db677131e385b5e7855d38fd0c8103f
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=9d010ea47db6+%5Ebc3b6065c670

----------------------------------------------------------------------------

9d010ea47db6: fdt/serial: Make uart search more agressive. Examine /chosen for 
serial devices
  
  Change-Id: Icc1673b331d9afb3a7b34c91e7b1f20c3dee964a
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/1871
  Reviewed-by: Adrien Destugues <pulkomandy@xxxxxxxxx>
  Reviewed-by: Alex von Gluck IV <kallisti5@xxxxxxxxxxx>

                          [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev53569
Commit:      9d010ea47db677131e385b5e7855d38fd0c8103f
URL:         https://git.haiku-os.org/haiku/commit/?id=9d010ea47db6
Author:      Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Date:        Fri Sep 20 14:32:59 2019 UTC
Committer:   Alex von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Tue Oct 29 13:35:36 2019 UTC

----------------------------------------------------------------------------

1 file changed, 95 insertions(+), 34 deletions(-)
.../kernel/bus_managers/fdt/fdt_serial.cpp       | 129 ++++++++++++++-----

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/bus_managers/fdt/fdt_serial.cpp 
b/src/add-ons/kernel/bus_managers/fdt/fdt_serial.cpp
index 25d06fdf31..a2ba64832d 100644
--- a/src/add-ons/kernel/bus_managers/fdt/fdt_serial.cpp
+++ b/src/add-ons/kernel/bus_managers/fdt/fdt_serial.cpp
@@ -40,43 +40,18 @@ extern "C" {
 
 // If we dprintf before the UART is initalized there will be no output
 
-
-DebugUART*
-debug_uart_from_fdt(const void *fdt)
+static DebugUART*
+debug_uart_from_node(const void *fdt, int node)
 {
-       const char *name;
-       int node;
        int len;
+       const void *prop;
        phys_addr_t regs;
        int32 clock = 0;
        int32 speed = 0;
-       const void *prop;
        DebugUART *uart = NULL;
 
-       if (fdt == NULL) {
-               TRACE("%s: No FDT found!\n", __func__);
-               return NULL;
-       }
-
-       name = fdt_get_alias(fdt, "serial");
-       if (name == NULL)
-               name = fdt_get_alias(fdt, "serial0");
-       if (name == NULL)
-               name = fdt_get_alias(fdt, "serial1");
-       if (name == NULL)
-               name = fdt_get_alias(fdt, "uart0");
-       // TODO: else use /chosen linux,stdout-path
-       if (name == NULL) {
-               TRACE("%s: No known FDT UART alias found!\n", __func__);
-               return NULL;
-       }
-
-       node = fdt_path_offset(fdt, name);
-
-       if (node < 0) {
-               TRACE("%s: FDT node not found!\n", __func__);
+       if (node < 0 || fdt == NULL)
                return NULL;
-       }
 
        // determine the MMIO address
        regs = fdt_get_device_reg(fdt, node, false);
@@ -86,7 +61,7 @@ debug_uart_from_fdt(const void *fdt)
                return NULL;
        }
 
-       TRACE("serial: using '%s', node %d @ %" B_PRIxPHYSADDR "\n",
+       TRACE("serial: checking '%s', node %d @ %" B_PRIxPHYSADDR "\n",
                name, node, regs);
 
        // get the UART clock rate
@@ -104,9 +79,9 @@ debug_uart_from_fdt(const void *fdt)
        }
 
        // fdt_node_check_compatible returns 0 on match.
-
        if (fdt_node_check_compatible(fdt, node, "ns16550a") == 0
-               || fdt_node_check_compatible(fdt, node, "ns16550") == 0) {
+               || fdt_node_check_compatible(fdt, node, "ns16550") == 0
+               || fdt_node_check_compatible(fdt, node, "snps,dw-apb-uart") == 
0) {
                TRACE("serial: Found 8250 serial UART!\n");
                uart = arch_get_uart_8250(regs, clock);
        #if defined(__arm__)
@@ -124,10 +99,96 @@ debug_uart_from_fdt(const void *fdt)
                TRACE("serial: Found pl011 serial UART!\n");
                uart = arch_get_uart_pl011(regs, clock);
        #endif
-       } else {
-               // TODO: handle more UART types
+       }
+       return uart;
+}
+
+
+DebugUART*
+debug_uart_from_fdt(const void *fdt)
+{
+       int chosen_node;
+       int node;
+       int len;
+       const char *name;
+       const void *prop;
+       DebugUART *uart = NULL;
+
+       if (fdt == NULL) {
+               TRACE("%s: No FDT found!\n", __func__);
                return NULL;
        }
 
+       chosen_node = fdt_path_offset(fdt, "/chosen");
+       if (chosen_node >= 0) {
+               prop = fdt_getprop(fdt, chosen_node, "stdout-path", &len);
+               if (prop && len > 0) {
+                       node = fdt_path_offset(fdt, (const char*)prop);
+                       uart = debug_uart_from_node(fdt, node);
+               }
+               if (uart == NULL) {
+                       prop = fdt_getprop(fdt, chosen_node, 
"linux,stdout-path", &len);
+                       if (prop && len > 0) {
+                               node = fdt_path_offset(fdt, (const char*)prop);
+                               uart = debug_uart_from_node(fdt, node);
+                       }
+               }
+
+               if (uart == NULL) {
+                       // From what i've seen, stdout is generally an alias.
+                       // we could check for "/..." in the prop, but not sure
+                       // it's needed. If we *did* check for a prop starting
+                       // with / we could make all three of these "the same"
+                       prop = fdt_getprop(fdt, chosen_node, "stdout", &len);
+                       if (prop && len > 0) {
+                               name = fdt_get_alias(fdt, (const char*)prop);
+                               if (name != NULL) {
+                                       node = fdt_path_offset(fdt, name);
+                                       uart = debug_uart_from_node(fdt, node);
+                               }
+                       }
+               }
+
+               // Whoo-hoo! Bail.
+               if (uart != NULL)
+                       return uart;
+       }
+
+       // If we didn't find a /chosen serial device, lets search for some 
common aliases
+       char aliases[][8] = {
+               "serial",
+               "serial0",
+               "uart",
+               "uart0",
+               "serial1",
+               "serial2",
+               "serial3",
+               "uart1",
+               "uart2",
+               "uart3"
+       };
+
+       // For each known common serial alias, check it out and see if we have 
the
+       // needed driver for it. uart0 seems most common.
+       for (int index = 0; index < sizeof(aliases[0]) / sizeof(aliases); 
index++) {
+               name = fdt_get_alias(fdt, aliases[index]);
+               if (name == NULL)
+                       continue;
+
+               node = fdt_path_offset(fdt, name);
+               if (node < 0) {
+                       TRACE("%s: FDT node not found!\n", __func__);
+                       continue;
+               }
+               uart = debug_uart_from_node(fdt, node);
+
+               // We found a valid serial device. bail.
+               if (uart != NULL)
+                       break;
+       }
+
+       // It would be nice if we had *some* communication mechanism here if 
uart is still
+       // NULL to warn the user that we couldn't find a serial port.
+
        return uart;
 }


Other related posts:

  • » [haiku-commits] haiku: hrev53569 - src/add-ons/kernel/bus_managers/fdt - Alex von Gluck IV