diff options
author | Wesley W. Terpstra <wesley@sifive.com> | 2017-03-27 12:13:53 -0700 |
---|---|---|
committer | Wesley W. Terpstra <wesley@sifive.com> | 2017-03-27 15:50:22 -0700 |
commit | 9fa7b30887301f149f2497469a442d0887b21149 (patch) | |
tree | 33b67126a0fb86de8603aa8cae2496f2342f45d0 | |
parent | 3473915b3a3fd925a68fc3260c64824cab2846d2 (diff) | |
download | pk-9fa7b30887301f149f2497469a442d0887b21149.zip pk-9fa7b30887301f149f2497469a442d0887b21149.tar.gz pk-9fa7b30887301f149f2497469a442d0887b21149.tar.bz2 |
uart: add physical device driver
-rw-r--r-- | machine/machine.mk.in | 2 | ||||
-rw-r--r-- | machine/minit.c | 5 | ||||
-rw-r--r-- | machine/mtrap.c | 13 | ||||
-rw-r--r-- | machine/uart.c | 38 | ||||
-rw-r--r-- | machine/uart.h | 21 |
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 |