aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgsomlo <gsomlo@gmail.com>2020-12-15 16:11:40 -0500
committerGitHub <noreply@github.com>2020-12-15 13:11:40 -0800
commit62bb5daea5ef014616b00a63c106afdd07e68ffd (patch)
tree66d1d74fd95fa1a6b319ba857d6c3ca4ec434aa5
parent5c159feca11473822906ec9595f7593aba60222f (diff)
downloadriscv-pk-62bb5daea5ef014616b00a63c106afdd07e68ffd.zip
riscv-pk-62bb5daea5ef014616b00a63c106afdd07e68ffd.tar.gz
riscv-pk-62bb5daea5ef014616b00a63c106afdd07e68ffd.tar.bz2
Add support for the UART interface on the LiteX SoC (#230)
Tested using the RocketChip CPU option. (see https://github.com/enjoy-digital/litex) Signed-off-by: Gabriel Somlo <gsomlo@gmail.com>
-rw-r--r--machine/machine.mk.in4
-rw-r--r--machine/minit.c2
-rw-r--r--machine/mtrap.c5
-rw-r--r--machine/uart_litex.c77
-rw-r--r--machine/uart_litex.h14
5 files changed, 101 insertions, 1 deletions
diff --git a/machine/machine.mk.in b/machine/machine.mk.in
index ee0fc36..3543106 100644
--- a/machine/machine.mk.in
+++ b/machine/machine.mk.in
@@ -15,6 +15,7 @@ machine_hdrs = \
mtrap.h \
uart.h \
uart16550.h \
+ uart_litex.h \
finisher.h \
unprivileged_memory.h \
vm.h \
@@ -30,6 +31,7 @@ machine_c_srcs = \
fp_ldst.c \
uart.c \
uart16550.c \
+ uart_litex.c \
finisher.c \
misaligned_ldst.c \
flush_icache.c \
@@ -43,4 +45,4 @@ mentry.o: custom.dtb
custom.dtb: $(CUSTOM_DTS)
dtc -O dtb $^ -o $@
-endif \ No newline at end of file
+endif
diff --git a/machine/minit.c b/machine/minit.c
index f0587cc..2fb67a4 100644
--- a/machine/minit.c
+++ b/machine/minit.c
@@ -7,6 +7,7 @@
#include "fdt.h"
#include "uart.h"
#include "uart16550.h"
+#include "uart_litex.h"
#include "finisher.h"
#include "disabled_hart_mask.h"
#include "htif.h"
@@ -173,6 +174,7 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb)
// Confirm console as early as possible
query_uart(dtb);
query_uart16550(dtb);
+ query_uart_litex(dtb);
query_htif(dtb);
printm("bbl loader\r\n");
diff --git a/machine/mtrap.c b/machine/mtrap.c
index 42006b8..1acf802 100644
--- a/machine/mtrap.c
+++ b/machine/mtrap.c
@@ -8,6 +8,7 @@
#include "vm.h"
#include "uart.h"
#include "uart16550.h"
+#include "uart_litex.h"
#include "finisher.h"
#include "fdt.h"
#include "unprivileged_memory.h"
@@ -27,6 +28,8 @@ static uintptr_t mcall_console_putchar(uint8_t ch)
uart_putchar(ch);
} else if (uart16550) {
uart16550_putchar(ch);
+ } else if (uart_litex) {
+ uart_litex_putchar(ch);
} else if (htif) {
htif_console_putchar(ch);
}
@@ -69,6 +72,8 @@ static uintptr_t mcall_console_getchar()
return uart_getchar();
} else if (uart16550) {
return uart16550_getchar();
+ } else if (uart_litex) {
+ return uart_litex_getchar();
} else if (htif) {
return htif_console_getchar();
} else {
diff --git a/machine/uart_litex.c b/machine/uart_litex.c
new file mode 100644
index 0000000..1fe0359
--- /dev/null
+++ b/machine/uart_litex.c
@@ -0,0 +1,77 @@
+// See LICENSE for license details.
+
+#include <string.h>
+#include "uart_litex.h"
+#include "fdt.h"
+
+volatile unsigned int *uart_litex;
+
+#define UART_REG_RXTX 0
+#define UART_REG_TXFULL 1
+#define UART_REG_RXEMPTY 2
+#define UART_REG_EV_STATUS 3
+#define UART_REG_EV_PENDING 4
+#define UART_REG_EV_ENABLE 5
+
+void uart_litex_putchar(uint8_t c)
+{
+ while ((uart_litex[UART_REG_TXFULL] & 0x01)); // wait while tx-buffer full
+ uart_litex[UART_REG_RXTX] = c;
+}
+
+int uart_litex_getchar()
+{
+ int c = -1;
+ if (!(uart_litex[UART_REG_RXEMPTY] & 0x01)) { // if rx-buffer not empty
+ c = uart_litex[UART_REG_RXTX];
+ uart_litex[UART_REG_EV_PENDING] = 0x02; // ack (UART_EV_RX)
+ }
+ return c;
+}
+
+struct uart_litex_scan
+{
+ int compat;
+ uint64_t reg;
+};
+
+static void uart_litex_open(const struct fdt_scan_node *node, void *extra)
+{
+ struct uart_litex_scan *scan = (struct uart_litex_scan *)extra;
+ memset(scan, 0, sizeof(*scan));
+}
+
+static void uart_litex_prop(const struct fdt_scan_prop *prop, void *extra)
+{
+ struct uart_litex_scan *scan = (struct uart_litex_scan *)extra;
+ if (!strcmp(prop->name, "compatible") &&
+ !strcmp((const char *)prop->value, "litex,uart0")) {
+ scan->compat = 1;
+ } else if (!strcmp(prop->name, "reg")) {
+ fdt_get_address(prop->node->parent, prop->value, &scan->reg);
+ }
+}
+
+static void uart_litex_done(const struct fdt_scan_node *node, void *extra)
+{
+ struct uart_litex_scan *scan = (struct uart_litex_scan *)extra;
+ if (!scan->compat || !scan->reg || uart_litex)
+ return;
+
+ // Initialize LiteX UART
+ uart_litex = (void *)(uintptr_t)scan->reg;
+}
+
+void query_uart_litex(uintptr_t fdt)
+{
+ struct fdt_cb cb;
+ struct uart_litex_scan scan;
+
+ memset(&cb, 0, sizeof(cb));
+ cb.open = uart_litex_open;
+ cb.prop = uart_litex_prop;
+ cb.done = uart_litex_done;
+ cb.extra = &scan;
+
+ fdt_scan(fdt, &cb);
+}
diff --git a/machine/uart_litex.h b/machine/uart_litex.h
new file mode 100644
index 0000000..a10dc57
--- /dev/null
+++ b/machine/uart_litex.h
@@ -0,0 +1,14 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_UARTLR_H
+#define _RISCV_UARTLR_H
+
+#include <stdint.h>
+
+extern volatile unsigned int *uart_litex;
+
+void uart_litex_putchar(uint8_t ch);
+int uart_litex_getchar();
+void query_uart_litex(uintptr_t dtb);
+
+#endif