uart.c

Commit: e6209518 Author: jokerz Raw Copy
1
/* uart.c — PL011 UART driver for QEMU virt / Pi 5 */
2
#include "uart.h"
3
4
/* PL011 register offsets */
5
#define UART_DR   0x00
6
#define UART_FR   0x18
7
#define UART_IBRD 0x24
8
#define UART_FBRD 0x28
9
#define UART_LCRH 0x2C
10
#define UART_CR   0x30
11
#define UART_IMSC 0x38
12
#define UART_ICR  0x44
13
14
static inline void mmio_write(unsigned long off, unsigned int val) {
15
    *(volatile unsigned int *)(UART0_BASE + off) = val;
16
}
17
static inline unsigned int mmio_read(unsigned long off) {
18
    return *(volatile unsigned int *)(UART0_BASE + off);
19
}
20
21
void uart_init(void) {
22
    /* Disable UART */
23
    mmio_write(UART_CR, 0);
24
    /* Wait for TX to finish */
25
    while (mmio_read(UART_FR) & (1 << 3)) {}
26
    /* Clear interrupts */
27
    mmio_write(UART_ICR, 0x7FF);
28
    /* Baud rate: 115200 (IBRD=26, FBRD=3 for 48MHz clock) */
29
    mmio_write(UART_IBRD, 26);
30
    mmio_write(UART_FBRD, 3);
31
    /* 8-bit word, FIFO enabled */
32
    mmio_write(UART_LCRH, (3 << 5) | (1 << 4));
33
    /* Mask all interrupts */
34
    mmio_write(UART_IMSC, 0);
35
    /* Enable UART, TX, RX */
36
    mmio_write(UART_CR, (1 << 0) | (1 << 8) | (1 << 9));
37
}
38
39
void uart_putc(char c) {
40
    while (mmio_read(UART_FR) & (1 << 5)) {}
41
    mmio_write(UART_DR, (unsigned int)c);
42
}
43
44
void uart_puts(const char *s) {
45
    while (*s) uart_putc(*s++);
46
}
47
48
int uart_getc(void) {
49
    if (mmio_read(UART_FR) & (1 << 4)) return -1;
50
    return (int)(mmio_read(UART_DR) & 0xFF);
51
}
52
53
int uart_poll(void) {
54
    return !(mmio_read(UART_FR) & (1 << 4));
55
}
56