bsp/riscv: Add console support for NS16550 devices

Update #3433.
This commit is contained in:
Sebastian Huber
2018-07-06 11:20:31 +02:00
parent 31f90a2ff4
commit 1a192398bf
3 changed files with 109 additions and 1 deletions

View File

@@ -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

View File

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

View File

@@ -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