1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
// See LICENSE for license details.
#include "femto.h"
enum {
UART_RBR = 0x00, /* Receive Buffer Register */
UART_THR = 0x00, /* Transmit Hold Register */
UART_IER = 0x01, /* Interrupt Enable Register */
UART_DLL = 0x00, /* Divisor LSB (LCR_DLAB) */
UART_DLM = 0x01, /* Divisor MSB (LCR_DLAB) */
UART_FCR = 0x02, /* FIFO Control Register */
UART_LCR = 0x03, /* Line Control Register */
UART_MCR = 0x04, /* Modem Control Register */
UART_LSR = 0x05, /* Line Status Register */
UART_MSR = 0x06, /* Modem Status Register */
UART_SCR = 0x07, /* Scratch Register */
UART_LCR_DLAB = 0x80, /* Divisor Latch Bit */
UART_LCR_8BIT = 0x03, /* 8-bit */
UART_LCR_PODD = 0x08, /* Parity Odd */
UART_LSR_DA = 0x01, /* Data Available */
UART_LSR_OE = 0x02, /* Overrun Error */
UART_LSR_PE = 0x04, /* Parity Error */
UART_LSR_FE = 0x08, /* Framing Error */
UART_LSR_BI = 0x10, /* Break indicator */
UART_LSR_RE = 0x20, /* THR is empty */
UART_LSR_RI = 0x40, /* THR is empty and line is idle */
UART_LSR_EF = 0x80, /* Erroneous data in FIFO */
};
static volatile uint8_t *uart;
static void ns16550a_init()
{
uart = (uint8_t *)(void *)getauxval(NS16550A_UART0_CTRL_ADDR);
uint32_t uart_freq = getauxval(UART0_CLOCK_FREQ);
uint32_t baud_rate = getauxval(UART0_BAUD_RATE);
uint32_t divisor = uart_freq / (16 * baud_rate);
uart[UART_LCR] = UART_LCR_DLAB;
uart[UART_DLL] = divisor & 0xff;
uart[UART_DLM] = (divisor >> 8) & 0xff;
uart[UART_LCR] = UART_LCR_PODD | UART_LCR_8BIT;
}
static int ns16550a_getchar()
{
if (uart[UART_LSR] & UART_LSR_DA) {
return uart[UART_RBR];
} else {
return -1;
}
}
static int ns16550a_putchar(int ch)
{
while ((uart[UART_LSR] & UART_LSR_RI) == 0);
return uart[UART_THR] = ch & 0xff;
}
console_device_t console_ns16550a = {
ns16550a_init,
ns16550a_getchar,
ns16550a_putchar
};
|