Browse Source

uart: add physical device driver

pull/53/head
Wesley W. Terpstra 9 years ago
parent
commit
9fa7b30887
  1. 2
      machine/machine.mk.in
  2. 5
      machine/minit.c
  3. 13
      machine/mtrap.c
  4. 38
      machine/uart.c
  5. 21
      machine/uart.h

2
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 = \

5
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);

13
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()

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

21
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
Loading…
Cancel
Save