1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6 #include <mmio.h>
7 #include <pl011.h>
8 #include <utils_def.h>
9
uart_wait(void)10 static inline void uart_wait(void)
11 {
12 /* Wait until there is room in the Tx FIFO */
13 while ((read32((void *)((RMM_UART_ADDR) + UARTFR))
14 & PL011_UARTFR_TXFF) != 0U) {
15 /* Do nothing */
16 }
17 }
18
19 /* Function that initializes UART for console output */
uart_init(uintptr_t base_addr,unsigned int uart_clk,unsigned int baud_rate)20 int uart_init(uintptr_t base_addr,
21 unsigned int uart_clk,
22 unsigned int baud_rate)
23 {
24 unsigned int div;
25
26 /* Check Base address, baud rate and UART clock for sanity */
27
28 if (base_addr == 0UL) {
29 return -1;
30 }
31
32 if (uart_clk == 0U) {
33 return -1;
34 }
35
36 if (baud_rate == 0U) {
37 return -1;
38 }
39
40 /* Disable UART before programming */
41 write32(0U, (void *)((RMM_UART_ADDR) + UARTCR));
42
43 /* Program the baudrate */
44 div = (uart_clk * 4)/baud_rate;
45
46 /* IBRD = Divisor >> 6 */
47 write32(div >> 6, (void *)((RMM_UART_ADDR) + UARTIBRD));
48
49 /* FBRD = Divisor & 0x3F */
50 write32(div & 0x3f, (void *)((RMM_UART_ADDR) + UARTFBRD));
51
52 /* Enable FIFO and set word length, parity and number of stop bits */
53 write32(PL011_LINE_CONTROL, (void *)((RMM_UART_ADDR) + UARTLCR_H));
54
55 /* Clear any pending errors */
56 write32(0U, (void *)((RMM_UART_ADDR) + UARTECR));
57
58 /* Enable Tx, Rx, and UART overall */
59 write32(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN,
60 (void *)((RMM_UART_ADDR) + UARTCR));
61 return 0;
62 }
63
uart_putc(char ch)64 void uart_putc(char ch)
65 {
66 uart_wait();
67 write8(ch, (void *)((RMM_UART_ADDR) + UARTDR));
68 }
69
70 /* Serial output - called from printf */
_putchar(char ch)71 void _putchar(char ch)
72 {
73 if (ch == '\n') {
74 uart_putc('\r');
75 }
76 uart_putc(ch);
77 }
78