/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Cobham Gaisler AB. * * Authors: * Daniel Cederman */ #include #include #include /* 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; }