blob: 4ed38aa8e8df06c4d6d40f64becc33d3ac9bf5a4 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
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
10static 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 */
20int 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 */
AlexeiFedorov9fab0652023-08-23 10:59:50 +010050 write32(div & 0x3fU, (void *)((RMM_UART_ADDR) + UARTFBRD));
Soby Mathewb4c6df42022-11-09 11:13:29 +000051
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
AlexeiFedorov2ff329a2023-08-22 13:35:49 +010064static void uart_putc(char ch)
Soby Mathewb4c6df42022-11-09 11:13:29 +000065{
66 uart_wait();
AlexeiFedorov75e7cc52023-08-29 13:15:55 +010067 write8((uint8_t)ch, (void *)((RMM_UART_ADDR) + UARTDR));
Soby Mathewb4c6df42022-11-09 11:13:29 +000068}
69
70/* Serial output - called from printf */
71void _putchar(char ch)
72{
73 if (ch == '\n') {
74 uart_putc('\r');
75 }
76 uart_putc(ch);
77}