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