blob: 9081652473ff53a3c9488e67628bf226d78c4b1c [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>
AlexeiFedorovee2fc822023-10-31 14:54:39 +00008#include <stdio.h>
Soby Mathewb4c6df42022-11-09 11:13:29 +00009#include <utils_def.h>
10
11static inline void uart_wait(void)
12{
13 /* Wait until there is room in the Tx FIFO */
14 while ((read32((void *)((RMM_UART_ADDR) + UARTFR))
15 & PL011_UARTFR_TXFF) != 0U) {
16 /* Do nothing */
17 }
18}
19
20/* Function that initializes UART for console output */
21int uart_init(uintptr_t base_addr,
22 unsigned int uart_clk,
23 unsigned int baud_rate)
24{
25 unsigned int div;
26
27 /* Check Base address, baud rate and UART clock for sanity */
Soby Mathewb4c6df42022-11-09 11:13:29 +000028 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
AlexeiFedorov33656a32023-08-30 11:51:41 +010043 /* Program the baud rate */
44 div = (uart_clk * 4U) / baud_rate;
Soby Mathewb4c6df42022-11-09 11:13:29 +000045
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 */
AlexeiFedorovb0de4d52023-10-10 11:46:16 +010071/* coverity[misra_c_2012_rule_8_7_violation:SUPPRESS] */
AlexeiFedorovee2fc822023-10-31 14:54:39 +000072void putchar(char character)
Soby Mathewb4c6df42022-11-09 11:13:29 +000073{
AlexeiFedorovee2fc822023-10-31 14:54:39 +000074 if (character == '\n') {
Soby Mathewb4c6df42022-11-09 11:13:29 +000075 uart_putc('\r');
76 }
AlexeiFedorovee2fc822023-10-31 14:54:39 +000077 uart_putc(character);
Soby Mathewb4c6df42022-11-09 11:13:29 +000078}