87 lines
1.7 KiB
C
87 lines
1.7 KiB
C
/*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2021 Cobham Gaisler AB.
|
|
*
|
|
* Authors:
|
|
* Daniel Cederman <cederman@gaisler.com>
|
|
*/
|
|
|
|
#include <sbi/riscv_io.h>
|
|
#include <sbi/sbi_console.h>
|
|
#include <sbi_utils/serial/gaisler-uart.h>
|
|
|
|
/* clang-format off */
|
|
|
|
#define UART_REG_DATA 0
|
|
#define UART_REG_STATUS 1
|
|
#define UART_REG_CTRL 2
|
|
#define UART_REG_SCALER 3
|
|
|
|
#define UART_DATA_DATA 0x000000ff
|
|
#define UART_STATUS_FIFOFULL 0x00000200
|
|
#define UART_STATUS_DATAREADY 0x00000001
|
|
|
|
#define UART_CTRL_DB (1<<11)
|
|
#define UART_CTRL_FL (1<<6)
|
|
#define UART_CTRL_TE (1<<1)
|
|
#define UART_CTRL_RE (1<<0)
|
|
|
|
/* clang-format on */
|
|
|
|
static volatile char *uart_base;
|
|
|
|
static u32 get_reg(u32 num)
|
|
{
|
|
return readl(uart_base + (num * 0x4));
|
|
}
|
|
|
|
static void set_reg(u32 num, u32 val)
|
|
{
|
|
writel(val, uart_base + (num * 0x4));
|
|
}
|
|
|
|
static void gaisler_uart_putc(char ch)
|
|
{
|
|
while (get_reg(UART_REG_STATUS) & UART_STATUS_FIFOFULL)
|
|
;
|
|
|
|
set_reg(UART_REG_DATA, ch);
|
|
}
|
|
|
|
static int gaisler_uart_getc(void)
|
|
{
|
|
u32 ret = get_reg(UART_REG_STATUS);
|
|
if (!(ret & UART_STATUS_DATAREADY))
|
|
return -1;
|
|
return get_reg(UART_REG_DATA) & UART_DATA_DATA;
|
|
}
|
|
|
|
static struct sbi_console_device gaisler_console = {
|
|
.name = "gaisler_uart",
|
|
.console_putc = gaisler_uart_putc,
|
|
.console_getc = gaisler_uart_getc
|
|
};
|
|
|
|
int gaisler_uart_init(unsigned long base, u32 in_freq, u32 baudrate)
|
|
{
|
|
u32 ctrl;
|
|
|
|
uart_base = (volatile char *)base;
|
|
|
|
/* Configure baudrate */
|
|
if (in_freq)
|
|
set_reg(UART_REG_SCALER, in_freq / (baudrate * 8 + 7));
|
|
|
|
ctrl = get_reg(UART_REG_CTRL);
|
|
/* Preserve debug mode and flow control */
|
|
ctrl &= (UART_CTRL_DB | UART_CTRL_FL);
|
|
/* Enable TX and RX */
|
|
ctrl |= UART_CTRL_TE | UART_CTRL_RE;
|
|
set_reg(UART_REG_CTRL, ctrl);
|
|
|
|
sbi_console_set_device(&gaisler_console);
|
|
|
|
return 0;
|
|
}
|