diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-07-06 11:20:31 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-07-06 14:27:39 +0200 |
commit | 1a192398bfff40e7e8f46f3ef872ee289e131fd3 (patch) | |
tree | 232a2fdb935a6f73d3cd7d6df3e93a85ceeba365 /bsps | |
parent | bsp/riscv: Simplify printk() support (diff) | |
download | rtems-1a192398bfff40e7e8f46f3ef872ee289e131fd3.tar.bz2 |
bsp/riscv: Add console support for NS16550 devices
Update #3433.
Diffstat (limited to 'bsps')
-rw-r--r-- | bsps/include/bsp/fatal.h | 4 | ||||
-rw-r--r-- | bsps/riscv/riscv/console/console-config.c | 100 |
2 files changed, 103 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; } |