[rtems commit] bsps/microblaze: Add support for multiple UARTs

Joel Sherrill joel at rtems.org
Wed Apr 19 14:36:56 UTC 2023


Module:    rtems
Branch:    master
Commit:    c627a13239d8568a63cb192ed4bc8bb75a746399
Changeset: http://git.rtems.org/rtems/commit/?id=c627a13239d8568a63cb192ed4bc8bb75a746399

Author:    Maldonado, Sergio E. (GSFC-580.0) <sergio.e.maldonado at nasa.gov>
Date:      Mon Feb 27 22:44:51 2023 -0600

bsps/microblaze: Add support for multiple UARTs

---

 bsps/microblaze/include/dev/serial/uartlite.h      |   2 +
 .../microblaze_fpga/console/console-io.c           | 205 ++++++++++++++++++---
 bsps/microblaze/shared/dev/serial/uartlite.c       |   8 +-
 spec/build/bsps/microblaze/microblaze_fpga/grp.yml |  10 +
 spec/build/bsps/microblaze/microblaze_fpga/obj.yml |   1 -
 .../microblaze/microblaze_fpga/optconsoleuart.yml  |  21 +++
 .../microblaze/microblaze_fpga/optmaxuarts.yml     |  21 +++
 .../bsps/microblaze/microblaze_fpga/optuartirq.yml |  20 ++
 .../bsps/microblaze/microblaze_fpga/optuseuart.yml |  17 ++
 9 files changed, 275 insertions(+), 30 deletions(-)

diff --git a/bsps/microblaze/include/dev/serial/uartlite.h b/bsps/microblaze/include/dev/serial/uartlite.h
index 2fda3796b3..009f416508 100644
--- a/bsps/microblaze/include/dev/serial/uartlite.h
+++ b/bsps/microblaze/include/dev/serial/uartlite.h
@@ -49,8 +49,10 @@ typedef struct {
   rtems_termios_device_context base;
   uintptr_t address;
   uint32_t initial_baud;
+  uint32_t enabled;
 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
   bool transmitting;
+  uint32_t irq;
 #endif
 } uart_lite_context;
 
diff --git a/bsps/microblaze/microblaze_fpga/console/console-io.c b/bsps/microblaze/microblaze_fpga/console/console-io.c
index 81c4e73690..a07c85642f 100644
--- a/bsps/microblaze/microblaze_fpga/console/console-io.c
+++ b/bsps/microblaze/microblaze_fpga/console/console-io.c
@@ -34,39 +34,200 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <bsp/console-termios.h>
-#include <bsp/microblaze-fdt-support.h>
-#include <dev/serial/uartlite.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
 
+#include <sys/param.h>
+#include <bsp/console-termios.h>
+#include <bsp/fatal.h>
 #include <bspopts.h>
+#include <dev/serial/uartlite.h>
 
-uart_lite_context microblaze_qemu_uart_context = {
-  .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "UARTLITE" ),
-  .initial_baud = 115200
-};
-
-static bool fill_uart_base(rtems_termios_device_context *context)
-{
-  uint32_t mblaze_uart_base;
-
-  mblaze_uart_base = try_get_prop_from_device_tree(
-    "xlnx,xps-uartlite-1.00.a",
-    "reg",
-    BSP_MICROBLAZE_FPGA_UART_BASE
-  );
+#ifdef BSP_MICROBLAZE_FPGA_USE_FDT
+#include <bsp/fdt.h>
+#include <libfdt.h>
+#endif
 
-  microblaze_qemu_uart_context.address = mblaze_uart_base;
+#include <rtems/console.h>
 
-  return true;
-}
+#ifndef BSP_MICROBLAZE_FPGA_USE_FDT
+static uart_lite_context uart_lite_instances[] = {
+  {
+    .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "UARTLITE" ),
+    .initial_baud = 115200,
+    .address = BSP_MICROBLAZE_FPGA_UART_BASE,
+#if BSP_MICROBLAZE_FPGA_USE_UART
+    .enabled = 1,
+#endif
+#ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
+    .irq = BSP_MICROBLAZE_FPGA_UART_IRQ
+#endif
+  }
+};
 
 const console_device console_device_table[] = {
   {
     .device_file = "/dev/ttyS0",
-    .probe = fill_uart_base,
     .handler = &microblaze_uart_fns,
-    .context = &microblaze_qemu_uart_context.base
+    .context = &uart_lite_instances[0].base
   }
 };
 
 const size_t console_device_count = RTEMS_ARRAY_SIZE( console_device_table );
+#else
+static uart_lite_context uart_lite_instances[BSP_MICROBLAZE_FPGA_MAX_UARTS];
+console_device *dynamic_console_device_table;
+size_t dynamic_console_device_count;
+
+/* Override the console_device_table and console_device_count */
+#define console_device_table dynamic_console_device_table
+#define console_device_count dynamic_console_device_count
+#endif /* BSP_MICROBLAZE_FPGA_USE_FDT */
+
+#ifdef BSP_MICROBLAZE_FPGA_USE_FDT
+static int microblaze_fpga_get_stdout_node(const void *fdt)
+{
+  int node;
+  int len;
+  int offset;
+  const char *console;
+  const char *q;
+
+  node = fdt_path_offset( fdt, "/chosen" );
+  if ( node < 0 ) {
+    return 0;
+  }
+
+  console = fdt_getprop( fdt, node, "stdout-path", NULL );
+  if ( console == NULL ) {
+    return 0;
+  }
+
+  q = strchr(console, ':');
+  if ( !q ) {
+    return 0;
+  }
+
+  len = q - console;
+
+  /* Get the node specified by stdout-path */
+  offset = fdt_path_offset_namelen( fdt, console, len );
+  if (offset < 0) {
+    return 0;
+  }
+
+  return offset;
+}
+
+static void initialize_uart_arrays(uint32_t max_uarts) {
+  dynamic_console_device_table = calloc(max_uarts, sizeof(console_device));
+  dynamic_console_device_count = max_uarts;
+
+  for (uint32_t i = 0; i < max_uarts; i++) {
+    rtems_termios_device_context_initialize(&uart_lite_instances[i].base, "UARTLITE");
+    uart_lite_instances[i].initial_baud = 115200;
+
+    dynamic_console_device_table[i].device_file = malloc(11);
+    snprintf((char *)console_device_table[i].device_file, 11, "/dev/ttyS%u", i);
+    dynamic_console_device_table[i].handler = &microblaze_uart_fns;
+    dynamic_console_device_table[i].context = &uart_lite_instances[i].base;
+  }
+}
+#endif
+
+rtems_device_driver console_initialize(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  uint32_t port;
+  uint32_t stdout_port = BSP_MICROBLAZE_FPGA_CONSOLE_UART;
+
+#ifdef BSP_MICROBLAZE_FPGA_USE_FDT
+  initialize_uart_arrays(BSP_MICROBLAZE_FPGA_MAX_UARTS);
+
+  const char compatible[] = "xlnx,xps-uartlite-1.00.a";
+  const void *fdt = bsp_fdt_get();
+  int len;
+  int stdout_node = microblaze_fpga_get_stdout_node(fdt);
+  int node = fdt_node_offset_by_compatible( fdt, -1, compatible);
+
+  while ( node != -FDT_ERR_NOTFOUND ) {
+    const uint32_t *prop;
+    const void *status;
+    uint32_t disabled = 0;
+    port = console_device_count;
+
+    /* check if node device status has been set to disabled */
+    status = fdt_getprop( fdt, node, "status", &len );
+    if ( status != NULL ) {
+      if ( strncmp( status, "disabled", MIN( 9, len) ) == 0 ) {
+        disabled = 1;
+      }
+    }
+
+    if ( !disabled ) {
+      /* use port number property as the device table index */
+      prop = fdt_getprop( fdt, node, "port-number", NULL );
+      if ( prop != NULL ) {
+        port = fdt32_to_cpu( prop[0] );
+      }
+
+      if ( port < console_device_count ) {
+        prop = fdt_getprop( fdt, node, "reg", NULL );
+        if ( prop != NULL ) {
+          uint32_t address = fdt32_to_cpu( prop[0] );
+          uart_lite_instances[ port ].address = address;
+          uart_lite_instances[ port ].enabled = 1;
+          if ( node == stdout_node ) {
+            stdout_port = port;
+          }
+        }
+
+#ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
+        prop = fdt_getprop( fdt, node, "interrupts", NULL );
+        if ( prop != NULL ) {
+          uint32_t irq = fdt32_to_cpu( prop[0] );
+          uart_lite_instances[ port ].irq = irq;
+        }
+#endif
+      }
+    }
+
+    node = fdt_node_offset_by_compatible( fdt, node, compatible );
+
+    if ( disabled || ( port >= console_device_count ) )
+      continue;
+  }
+#endif /* BSP_MICROBLAZE_FPGA_USE_FDT */
+
+  rtems_termios_initialize();
+
+  for ( port = 0; port < console_device_count; port++ ) {
+    const console_device *ctx = &console_device_table[ port ];
+    rtems_status_code     sc;
+
+    if ( !uart_lite_instances[ port ].enabled )
+      continue;
+
+    sc = rtems_termios_device_install(
+      ctx->device_file,
+      ctx->handler,
+      ctx->flow,
+      ctx->context
+    );
+    if ( sc != RTEMS_SUCCESSFUL ) {
+      bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_0 );
+    }
+
+    if ( port == stdout_port ) {
+      if ( link( ctx->device_file, CONSOLE_DEVICE_NAME ) != 0 ) {
+        bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_1 );
+      }
+    }
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/microblaze/shared/dev/serial/uartlite.c b/bsps/microblaze/shared/dev/serial/uartlite.c
index 953c630759..e2007ee24a 100644
--- a/bsps/microblaze/shared/dev/serial/uartlite.c
+++ b/bsps/microblaze/shared/dev/serial/uartlite.c
@@ -71,14 +71,8 @@ static bool uart_first_open(
 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
   XUartLite_EnableIntr( ctx->address );
 
-  uint32_t uart_irq_num = try_get_prop_from_device_tree(
-    "xlnx,xps-uartlite-1.00.a",
-    "interrupts",
-    1
-  );
-
   sc = rtems_interrupt_handler_install(
-    uart_irq_num,
+    ctx->irq,
     "UART",
     RTEMS_INTERRUPT_SHARED,
     microblaze_uart_interrupt,
diff --git a/spec/build/bsps/microblaze/microblaze_fpga/grp.yml b/spec/build/bsps/microblaze/microblaze_fpga/grp.yml
index aa88821458..4f854de2cd 100644
--- a/spec/build/bsps/microblaze/microblaze_fpga/grp.yml
+++ b/spec/build/bsps/microblaze/microblaze_fpga/grp.yml
@@ -54,6 +54,8 @@ links:
   uid: opticachesize
 - role: build-dependency
   uid: optintcbaseaddress
+- role: build-dependency
+  uid: optmaxuarts
 - role: build-dependency
   uid: optramlen
 - role: build-dependency
@@ -66,6 +68,14 @@ links:
   uid: opttimerfrequency
 - role: build-dependency
   uid: optuartlitebaseaddress
+- role: build-dependency
+  uid: optuseuart
+- role: build-dependency
+  uid: optuartirq
+- role: build-dependency
+  uid: optuartirq
+- role: build-dependency
+  uid: optconsoleuart
 - role: build-dependency
   uid: optusefdt
 - role: build-dependency
diff --git a/spec/build/bsps/microblaze/microblaze_fpga/obj.yml b/spec/build/bsps/microblaze/microblaze_fpga/obj.yml
index 67afbb7c7e..52ba596768 100644
--- a/spec/build/bsps/microblaze/microblaze_fpga/obj.yml
+++ b/spec/build/bsps/microblaze/microblaze_fpga/obj.yml
@@ -47,7 +47,6 @@ source:
 - bsps/shared/dev/cpucounter/cpucounterfrequency.c
 - bsps/shared/dev/cpucounter/cpucounterread.c
 - bsps/shared/dev/getentropy/getentropy-cpucounter.c
-- bsps/shared/dev/serial/console-termios-init.c
 - bsps/shared/dev/serial/console-termios.c
 - bsps/shared/irq/irq-default-handler.c
 - bsps/shared/start/bspfatal-default.c
diff --git a/spec/build/bsps/microblaze/microblaze_fpga/optconsoleuart.yml b/spec/build/bsps/microblaze/microblaze_fpga/optconsoleuart.yml
new file mode 100644
index 0000000000..8cc8e18062
--- /dev/null
+++ b/spec/build/bsps/microblaze/microblaze_fpga/optconsoleuart.yml
@@ -0,0 +1,21 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+actions:
+- get-integer: null
+- assert-uint32: null
+- env-assign: null
+- format-and-define: null
+build-type: option
+copyrights:
+- Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
+default:
+- enabled-by: true
+  value: 0
+default-by-variant: []
+description: |
+  default uart console device port number
+enabled-by: true
+format: '{}'
+links: []
+name: BSP_MICROBLAZE_FPGA_CONSOLE_UART
+type: build
diff --git a/spec/build/bsps/microblaze/microblaze_fpga/optmaxuarts.yml b/spec/build/bsps/microblaze/microblaze_fpga/optmaxuarts.yml
new file mode 100644
index 0000000000..3b639a5922
--- /dev/null
+++ b/spec/build/bsps/microblaze/microblaze_fpga/optmaxuarts.yml
@@ -0,0 +1,21 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+actions:
+- get-integer: null
+- assert-uint32: null
+- env-assign: null
+- format-and-define: null
+build-type: option
+copyrights:
+- Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
+default:
+- enabled-by: true
+  value: 1
+default-by-variant: []
+description: |
+  maximum number of UART devices
+enabled-by: true
+format: '{}'
+links: []
+name: BSP_MICROBLAZE_FPGA_MAX_UARTS
+type: build
diff --git a/spec/build/bsps/microblaze/microblaze_fpga/optuartirq.yml b/spec/build/bsps/microblaze/microblaze_fpga/optuartirq.yml
new file mode 100644
index 0000000000..054388bf8a
--- /dev/null
+++ b/spec/build/bsps/microblaze/microblaze_fpga/optuartirq.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-integer: null
+- assert-uint32: null
+- env-assign: null
+- format-and-define: null
+build-type: option
+copyrights:
+- Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
+default:
+- enabled-by: true
+  value: 3
+default-by-variant: []
+description: |
+  irq number of the AXI UART Lite
+enabled-by: true
+format: '{:#010x}'
+links: []
+name: BSP_MICROBLAZE_FPGA_UART_IRQ
+type: build
diff --git a/spec/build/bsps/microblaze/microblaze_fpga/optuseuart.yml b/spec/build/bsps/microblaze/microblaze_fpga/optuseuart.yml
new file mode 100644
index 0000000000..c3ddd11b78
--- /dev/null
+++ b/spec/build/bsps/microblaze/microblaze_fpga/optuseuart.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-boolean: null
+- define-condition: null
+build-type: option
+copyrights:
+- Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
+default:
+- enabled-by: true
+  value: true
+default-by-variant: []
+description: |
+  define if UART is used
+enabled-by: true
+links: []
+name: BSP_MICROBLAZE_FPGA_USE_UART
+type: build



More information about the vc mailing list