aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWesley W. Terpstra <wesley@sifive.com>2017-03-27 12:13:53 -0700
committerWesley W. Terpstra <wesley@sifive.com>2017-03-27 15:50:22 -0700
commit9fa7b30887301f149f2497469a442d0887b21149 (patch)
tree33b67126a0fb86de8603aa8cae2496f2342f45d0
parent3473915b3a3fd925a68fc3260c64824cab2846d2 (diff)
downloadriscv-pk-9fa7b30887301f149f2497469a442d0887b21149.zip
riscv-pk-9fa7b30887301f149f2497469a442d0887b21149.tar.gz
riscv-pk-9fa7b30887301f149f2497469a442d0887b21149.tar.bz2
uart: add physical device driver
-rw-r--r--machine/machine.mk.in2
-rw-r--r--machine/minit.c5
-rw-r--r--machine/mtrap.c13
-rw-r--r--machine/uart.c38
-rw-r--r--machine/uart.h21
5 files changed, 77 insertions, 2 deletions
diff --git a/machine/machine.mk.in b/machine/machine.mk.in
index 10d85b4..cdcb4a7 100644
--- a/machine/machine.mk.in
+++ b/machine/machine.mk.in
@@ -11,6 +11,7 @@ machine_hdrs = \
htif.h \
mcall.h \
mtrap.h \
+ uart.h \
unprivileged_memory.h \
vm.h \
@@ -23,6 +24,7 @@ machine_c_srcs = \
muldiv_emulation.c \
fp_emulation.c \
fp_ldst.c \
+ uart.c \
misaligned_ldst.c \
machine_asm_srcs = \
diff --git a/machine/minit.c b/machine/minit.c
index 48366d7..6fc51c6 100644
--- a/machine/minit.c
+++ b/machine/minit.c
@@ -3,6 +3,7 @@
#include "vm.h"
#include "fp_emulation.h"
#include "fdt.h"
+#include "uart.h"
#include <string.h>
#include <limits.h>
@@ -125,6 +126,10 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb)
hart_init();
hls_init(0); // this might get called again from parse_config_string
+ // Confirm console as early as possible
+ query_uart(dtb);
+ printm("SBI console now online\n");
+
query_mem(dtb);
query_harts(dtb);
query_clint(dtb);
diff --git a/machine/mtrap.c b/machine/mtrap.c
index 6e85d26..d7def4c 100644
--- a/machine/mtrap.c
+++ b/machine/mtrap.c
@@ -4,6 +4,7 @@
#include "atomic.h"
#include "bits.h"
#include "vm.h"
+#include "uart.h"
#include "unprivileged_memory.h"
#include <errno.h>
#include <stdarg.h>
@@ -16,7 +17,11 @@ void __attribute__((noreturn)) bad_trap(uintptr_t* regs, uintptr_t dummy, uintpt
static uintptr_t mcall_console_putchar(uint8_t ch)
{
- htif_console_putchar(ch);
+ if (uart) {
+ uart_putchar(ch);
+ } else {
+ htif_console_putchar(ch);
+ }
return 0;
}
@@ -52,7 +57,11 @@ static void send_ipi(uintptr_t recipient, int event)
static uintptr_t mcall_console_getchar()
{
- return htif_console_getchar();
+ if (uart) {
+ return uart_getchar();
+ } else {
+ return htif_console_getchar();
+ }
}
static uintptr_t mcall_clear_ipi()
diff --git a/machine/uart.c b/machine/uart.c
new file mode 100644
index 0000000..28cc21c
--- /dev/null
+++ b/machine/uart.c
@@ -0,0 +1,38 @@
+#include "uart.h"
+#include "fdt.h"
+
+volatile uint32_t* uart;
+
+void uart_putchar(uint8_t ch)
+{
+#ifdef __riscv_atomic
+ int32_t r;
+ do {
+ __asm__ __volatile__ (
+ "amoor.w %0, %2, %1\n"
+ : "=r" (r), "+A" (uart[UART_REG_TXFIFO])
+ : "r" (ch));
+ } while (r < 0);
+#else
+ volatile uint32_t *tx = uart + UART_REG_TXFIFO;
+ while ((int32_t)(*tx) < 0);
+ *tx = ch;
+#endif
+}
+
+int uart_getchar()
+{
+ int32_t ch = uart[UART_REG_RXFIFO];
+ if (ch < 0) return -1;
+ return ch;
+}
+
+void query_uart(uintptr_t dtb)
+{
+ uart = 0; // (void*)fdt_get_reg(dtb, "sifive,uart0");
+ if (!uart) return;
+
+ // Enable Rx/Tx channels
+ uart[UART_REG_TXCTRL] = UART_TXEN;
+ uart[UART_REG_RXCTRL] = UART_RXEN;
+}
diff --git a/machine/uart.h b/machine/uart.h
new file mode 100644
index 0000000..51e951f
--- /dev/null
+++ b/machine/uart.h
@@ -0,0 +1,21 @@
+#ifndef _RISCV_UART_H
+#define _RISCV_UART_H
+
+#include <stdint.h>
+
+extern volatile uint32_t* uart;
+
+#define UART_REG_TXFIFO 0
+#define UART_REG_RXFIFO 1
+#define UART_REG_TXCTRL 2
+#define UART_REG_RXCTRL 3
+#define UART_REG_DIV 4
+
+#define UART_TXEN 0x1
+#define UART_RXEN 0x1
+
+void uart_putchar(uint8_t ch);
+int uart_getchar();
+void query_uart(uintptr_t dtb);
+
+#endif