| /* |
| * SPDX-License-Identifier: BSD-2-Clause |
| * |
| * Copyright (c) 2021 Gabriel Somlo |
| * |
| * Authors: |
| * Gabriel Somlo <gsomlo@gmail.com> |
| */ |
| |
| #include <sbi/riscv_io.h> |
| #include <sbi/sbi_console.h> |
| #include <sbi_utils/serial/litex-uart.h> |
| |
| /* clang-format off */ |
| |
| #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 |
| |
| #define UART_EV_RX 0x2 |
| |
| /* clang-format on */ |
| |
| static volatile u32 *uart_base; |
| |
| static u8 get_reg(u8 reg) |
| { |
| return readb(uart_base + reg); |
| } |
| |
| static void set_reg(u8 reg, u8 val) |
| { |
| writeb(val, uart_base + reg); |
| } |
| |
| static void litex_uart_putc(char ch) |
| { |
| while (get_reg(UART_REG_TXFULL)); |
| set_reg(UART_REG_RXTX, ch); |
| } |
| |
| static int litex_uart_getc(void) |
| { |
| int ret; |
| |
| if (get_reg(UART_REG_RXEMPTY)) |
| return -1; |
| |
| ret = get_reg(UART_REG_RXTX); |
| set_reg(UART_REG_EV_PENDING, UART_EV_RX); /* ack. char read */ |
| return ret; |
| } |
| |
| static struct sbi_console_device litex_console = { |
| .name = "litex_uart", |
| .console_putc = litex_uart_putc, |
| .console_getc = litex_uart_getc |
| }; |
| |
| int litex_uart_init(unsigned long base) |
| { |
| uart_base = (volatile u32 *)base; |
| set_reg(UART_REG_EV_ENABLE, 0); /* UART in polling mode: disable IRQ */ |
| sbi_console_set_device(&litex_console); |
| return 0; |
| } |