blob: 3d9d81e89de3183db765c9f559b3306afcd43204 [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 */
Soby Mathewb4c6df42022-11-09 11:13:29 +000027 if (base_addr == 0UL) {
28 return -1;
29 }
30
31 if (uart_clk == 0U) {
32 return -1;
33 }
34
35 if (baud_rate == 0U) {
36 return -1;
37 }
38
39 /* Disable UART before programming */
40 write32(0U, (void *)((RMM_UART_ADDR) + UARTCR));
41
AlexeiFedorov33656a32023-08-30 11:51:41 +010042 /* Program the baud rate */
43 div = (uart_clk * 4U) / baud_rate;
Soby Mathewb4c6df42022-11-09 11:13:29 +000044
45 /* IBRD = Divisor >> 6 */
46 write32(div >> 6, (void *)((RMM_UART_ADDR) + UARTIBRD));
47
48 /* FBRD = Divisor & 0x3F */
AlexeiFedorov9fab0652023-08-23 10:59:50 +010049 write32(div & 0x3fU, (void *)((RMM_UART_ADDR) + UARTFBRD));
Soby Mathewb4c6df42022-11-09 11:13:29 +000050
51 /* Enable FIFO and set word length, parity and number of stop bits */
52 write32(PL011_LINE_CONTROL, (void *)((RMM_UART_ADDR) + UARTLCR_H));
53
54 /* Clear any pending errors */
55 write32(0U, (void *)((RMM_UART_ADDR) + UARTECR));
56
57 /* Enable Tx, Rx, and UART overall */
58 write32(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN,
59 (void *)((RMM_UART_ADDR) + UARTCR));
60 return 0;
61}
62
AlexeiFedorov2ff329a2023-08-22 13:35:49 +010063static void uart_putc(char ch)
Soby Mathewb4c6df42022-11-09 11:13:29 +000064{
65 uart_wait();
AlexeiFedorov75e7cc52023-08-29 13:15:55 +010066 write8((uint8_t)ch, (void *)((RMM_UART_ADDR) + UARTDR));
Soby Mathewb4c6df42022-11-09 11:13:29 +000067}
68
69/* Serial output - called from printf */
AlexeiFedorovb0de4d52023-10-10 11:46:16 +010070/* coverity[misra_c_2012_rule_8_7_violation:SUPPRESS] */
Chuyue Luoe4da13f2023-09-22 11:22:37 +010071void putchar(char ch)
Soby Mathewb4c6df42022-11-09 11:13:29 +000072{
73 if (ch == '\n') {
74 uart_putc('\r');
75 }
76 uart_putc(ch);
77}