Browse Source

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>
pull/235/head
gsomlo 5 years ago
committed by GitHub
parent
commit
62bb5daea5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      machine/machine.mk.in
  2. 2
      machine/minit.c
  3. 5
      machine/mtrap.c
  4. 77
      machine/uart_litex.c
  5. 14
      machine/uart_litex.h

4
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
endif

2
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");

5
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 {

77
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);
}

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