summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-07-06 11:20:31 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-07-06 14:27:39 +0200
commit1a192398bfff40e7e8f46f3ef872ee289e131fd3 (patch)
tree232a2fdb935a6f73d3cd7d6df3e93a85ceeba365
parent31f90a2ff4cb40b830c2cbcc184315e424fc8e12 (diff)
downloadrtems-1a192398bfff40e7e8f46f3ef872ee289e131fd3.tar.bz2
bsp/riscv: Add console support for NS16550 devices
Update #3433.
-rw-r--r--bsps/include/bsp/fatal.h4
-rw-r--r--bsps/riscv/riscv/console/console-config.c100
-rw-r--r--c/src/lib/libbsp/riscv/riscv/configure.ac6
3 files changed, 109 insertions, 1 deletions
diff --git a/bsps/include/bsp/fatal.h b/bsps/include/bsp/fatal.h
index 12d33a20e4..77c056601c 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 2cbb2091cd..6847deeb66 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 68a7b50871..17f4eb8d88 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