#include #include #include "console.h" /* * Core UART functions to implement for a port */ static uint64_t potato_uart_base; #define PROC_FREQ 100000000 #define UART_FREQ 115200 #define UART_BASE 0xc0002000 #define POTATO_CONSOLE_TX 0x00 #define POTATO_CONSOLE_RX 0x08 #define POTATO_CONSOLE_STATUS 0x10 #define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01 #define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02 #define POTATO_CONSOLE_STATUS_RX_FULL 0x04 #define POTATO_CONSOLE_STATUS_TX_FULL 0x08 #define POTATO_CONSOLE_CLOCK_DIV 0x18 #define POTATO_CONSOLE_IRQ_EN 0x20 static uint64_t potato_uart_reg_read(int offset) { uint64_t val; __asm__ volatile("ldcix %0,%1,%2" : "=r" (val) : "b" (potato_uart_base), "r" (offset)); return val; } static void potato_uart_reg_write(int offset, uint64_t val) { __asm__ volatile("stdcix %0,%1,%2" : : "r" (val), "b" (potato_uart_base), "r" (offset)); } static int potato_uart_rx_empty(void) { uint64_t val; val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); if (val & POTATO_CONSOLE_STATUS_RX_EMPTY) return 1; return 0; } static int potato_uart_tx_full(void) { uint64_t val; val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); if (val & POTATO_CONSOLE_STATUS_TX_FULL) return 1; return 0; } static char potato_uart_read(void) { uint64_t val; val = potato_uart_reg_read(POTATO_CONSOLE_RX); return (char)(val & 0x000000ff); } static void potato_uart_write(char c) { uint64_t val; val = c; potato_uart_reg_write(POTATO_CONSOLE_TX, val); } static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq) { return proc_freq / (uart_freq * 16) - 1; } void potato_uart_init(void) { potato_uart_base = UART_BASE; potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ)); } void potato_uart_irq_en(void) { potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, 0xff); } void potato_uart_irq_dis(void) { potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, 0x00); } int getchar(void) { while (potato_uart_rx_empty()) /* Do nothing */ ; return potato_uart_read(); } void putchar(unsigned char c) { while (potato_uart_tx_full()) /* Do Nothing */; potato_uart_write(c); } void putstr(const char *str, unsigned long len) { for (unsigned long i = 0; i < len; i++) { putchar(str[i]); } } size_t strlen(const char *s) { size_t len = 0; while (*s++) len++; return len; }