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