Breakout the console code so it can be reused.
No functional change. Signed-off-by: Michael Neuling <mikey@neuling.org>pull/155/head
parent
8bee4ae3cc
commit
96fbd61de8
@ -0,0 +1,132 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Core UART functions to implement for a port
|
||||
*/
|
||||
|
||||
static uint64_t potato_uart_base;
|
||||
|
||||
#define PROC_FREQ 50000000
|
||||
#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 addr;
|
||||
uint64_t val;
|
||||
|
||||
addr = potato_uart_base + offset;
|
||||
|
||||
val = *(volatile uint64_t *)addr;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void potato_uart_reg_write(int offset, uint64_t val)
|
||||
{
|
||||
uint64_t addr;
|
||||
|
||||
addr = potato_uart_base + offset;
|
||||
|
||||
*(volatile uint64_t *)addr = val;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
void potato_uart_init(void);
|
||||
int getchar(void);
|
||||
void putchar(unsigned char c);
|
||||
void putstr(const char *str, unsigned long len);
|
||||
size_t strlen(const char *s);
|
Loading…
Reference in New Issue