| /* |
| * 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 && baudrate) |
| 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; |
| } |