[rtems commit] bsp/riscv: Add console support for NS16550 devices

Sebastian Huber sebh at rtems.org
Fri Jul 6 12:28:58 UTC 2018


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Jul  6 11:20:31 2018 +0200

bsp/riscv: Add console support for NS16550 devices

Update #3433.

---

 bsps/include/bsp/fatal.h                  |   4 +-
 bsps/riscv/riscv/console/console-config.c | 100 ++++++++++++++++++++++++++++++
 c/src/lib/libbsp/riscv/riscv/configure.ac |   6 ++
 3 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/bsps/include/bsp/fatal.h b/bsps/include/bsp/fatal.h
index 12d33a2..77c0566 100644
--- a/bsps/include/bsp/fatal.h
+++ b/bsps/include/bsp/fatal.h
@@ -140,7 +140,9 @@ typedef enum {
   IMX_FATAL_GENERIC_TIMER_FREQUENCY = BSP_FATAL_CODE_BLOCK(12),
 
   /* RISC-V fatal codes */
-  RISCV_FATAL_NO_TIMEBASE_FREQUENCY_IN_DEVICE_TREE = BSP_FATAL_CODE_BLOCK(13)
+  RISCV_FATAL_NO_TIMEBASE_FREQUENCY_IN_DEVICE_TREE = BSP_FATAL_CODE_BLOCK(13),
+  RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE,
+  RISCV_FATAL_NO_NS16550_CLOCK_FREQUENCY_IN_DEVICE_TREE
 } bsp_fatal_code;
 
 RTEMS_NO_RETURN static inline void
diff --git a/bsps/riscv/riscv/console/console-config.c b/bsps/riscv/riscv/console/console-config.c
index 2cbb209..6847dee 100644
--- a/bsps/riscv/riscv/console/console-config.c
+++ b/bsps/riscv/riscv/console/console-config.c
@@ -18,10 +18,12 @@
 #include <rtems/termiostypes.h>
 
 #include <bsp.h>
+#include <bsp/fatal.h>
 #include <bsp/fdt.h>
 #include <bsp/irq.h>
 
 #include <dev/serial/htif.h>
+#include <libchip/ns16550.h>
 
 #include <libfdt.h>
 
@@ -29,6 +31,10 @@
 static htif_console_context htif_console_instance;
 #endif
 
+#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
+static ns16550_context ns16550_instances[RISCV_CONSOLE_MAX_NS16550_DEVICES];
+#endif
+
 static struct {
   rtems_termios_device_context *context;
   void (*putchar)(rtems_termios_device_context *base, char c);
@@ -55,14 +61,38 @@ static int riscv_get_console_node(const void *fdt)
   return fdt_path_offset(fdt, stdout_path);
 }
 
+#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
+static uint8_t get_register(uintptr_t addr, uint8_t i)
+{
+  volatile uint8_t *reg;
+
+  reg = (uint8_t *) addr;
+  return reg[i];
+}
+
+static void set_register(uintptr_t addr, uint8_t i, uint8_t val)
+{
+  volatile uint8_t *reg;
+
+  reg = (uint8_t *)addr;
+  reg[i] = val;
+}
+#endif
+
 static void riscv_console_probe(void)
 {
   const void *fdt;
   int node;
   int console_node;
+#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
+  size_t ns16550_devices;
+#endif
 
   fdt = bsp_fdt_get();
   console_node = riscv_get_console_node(fdt);
+#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
+  ns16550_devices = 0;
+#endif
 
   node = fdt_next_node(fdt, -1, NULL);
 
@@ -77,6 +107,52 @@ static void riscv_console_probe(void)
     };
 #endif
 
+#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
+    if (fdt_node_check_compatible(fdt, node, "ns16550a") == 0) {
+      if (ns16550_devices < RISCV_CONSOLE_MAX_NS16550_DEVICES) {
+        ns16550_context *ctx;
+        fdt32_t *val;
+        int len;
+
+        ctx = &ns16550_instances[ns16550_devices];
+        ctx->get_reg = get_register;
+        ctx->set_reg = set_register;
+        ctx->initial_baud = BSP_CONSOLE_BAUD;
+
+        val = (fdt32_t *) fdt_getprop(fdt, node, "reg", &len);
+
+        if (val == NULL || (len != 8 && len != 16)) {
+          bsp_fatal(RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE);
+        }
+
+        if (len == 16) {
+          ctx->port = fdt32_to_cpu(val[1]);
+        } else {
+          ctx->port = fdt32_to_cpu(val[0]);
+        }
+
+        val = (fdt32_t *) fdt_getprop(fdt, node, "clock-frequency", &len);
+
+        if (val == NULL || len != 4) {
+          bsp_fatal(RISCV_FATAL_NO_NS16550_CLOCK_FREQUENCY_IN_DEVICE_TREE);
+        }
+
+        ctx->clock = fdt32_to_cpu(val[0]);
+
+        if (node == console_node) {
+          riscv_console.context = &ctx->base;
+          riscv_console.putchar = ns16550_polled_putchar;
+          riscv_console.getchar = ns16550_polled_getchar;
+        }
+
+        rtems_termios_device_context_initialize(&ctx->base, "NS16550");
+        ns16550_probe(&ctx->base);
+
+        ++ns16550_devices;
+      }
+    }
+#endif
+
     node = fdt_next_node(fdt, node, NULL);
   }
 
@@ -101,6 +177,10 @@ rtems_status_code console_initialize(
 {
   rtems_termios_device_context *base;
   char htif_path[] = "/dev/ttyShtif";
+#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
+  char path[] = "/dev/ttyS?";
+  size_t i;
+#endif
 
   rtems_termios_initialize();
 
@@ -113,6 +193,26 @@ rtems_status_code console_initialize(
   }
 #endif
 
+#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
+  for (i = 0; i < RISCV_CONSOLE_MAX_NS16550_DEVICES; ++i) {
+    ns16550_context *ctx;
+
+    ctx = &ns16550_instances[i];
+    path[sizeof(path) - 2] = (char) ('0' + i);
+
+    rtems_termios_device_install(
+      path,
+      &ns16550_handler_polled,
+      NULL,
+      &ctx->base
+    );
+
+    if (&ctx->base == riscv_console.context) {
+      link(path, CONSOLE_DEVICE_NAME);
+    }
+  }
+#endif
+
   return RTEMS_SUCCESSFUL;
 }
 
diff --git a/c/src/lib/libbsp/riscv/riscv/configure.ac b/c/src/lib/libbsp/riscv/riscv/configure.ac
index 68a7b50..17f4eb8 100644
--- a/c/src/lib/libbsp/riscv/riscv/configure.ac
+++ b/c/src/lib/libbsp/riscv/riscv/configure.ac
@@ -27,9 +27,15 @@ RTEMS_BSPOPTS_HELP([BSP_FDT_BLOB_READ_ONLY],[place the FDT blob into the read-on
 RTEMS_BSPOPTS_SET([BSP_FDT_BLOB_COPY_TO_READ_ONLY_LOAD_AREA],[*],[1])
 RTEMS_BSPOPTS_HELP([BSP_FDT_BLOB_COPY_TO_READ_ONLY_LOAD_AREA],[copy the FDT blob into the read-only load area via bsp_fdt_copy()])
 
+RTEMS_BSPOPTS_SET([BSP_CONSOLE_BAUD],[*],[115200])
+RTEMS_BSPOPTS_HELP([BSP_CONSOLE_BAUD],[default baud for console driver devices (default 115200)])
+
 RTEMS_BSPOPTS_SET([RISCV_ENABLE_HTIF_SUPPORT],[*],[1])
 RTEMS_BSPOPTS_HELP([RISCV_ENABLE_HTIF_SUPPORT],[enables the HTIF support if defined to a non-zero value, otherwise it is disabled (enabled by default)])
 
+RTEMS_BSPOPTS_SET([RISCV_CONSOLE_MAX_NS16550_DEVICES],[*],[2])
+RTEMS_BSPOPTS_HELP([RISCV_CONSOLE_MAX_NS16550_DEVICES],[maximum number of NS16550 devices supported by the console driver (2 by default)])
+
 RTEMS_BSP_CLEANUP_OPTIONS
 
 case "${RTEMS_BSP}" in




More information about the vc mailing list