xref: /aosp_15_r20/external/coreboot/src/drivers/uart/pl011.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <boot/coreboot_tables.h>
5 #include <console/uart.h>
6 #include <drivers/uart/pl011.h>
7 
uart_init(unsigned int idx)8 void uart_init(unsigned int idx)
9 {
10 	struct pl011_uart *regs = uart_platform_baseptr(idx);
11 	uint32_t tmp;
12 
13 	if (!regs)
14 		return;
15 
16 	/* Disable UART */
17 	tmp = read32(&regs->cr);
18 	tmp &= ~PL011_UARTCR_UARTEN;
19 	write32(&regs->cr, tmp);
20 
21 	/*
22 	 * Program Divisor
23 	 * As per: PL011 Technical reference manual:
24 	 * BAUDDIV = (Fuartclk / (16 * baud_rate))
25 	 * Considering 6 bits(64) for UARTFBRD
26 	 * BAUDDIV = (Fuartclk * 4 / baud_rate)
27 	 */
28 	tmp = uart_platform_refclk() * 4 / get_uart_baudrate();
29 
30 	write32(&regs->ibrd, tmp >> 6);
31 	write32(&regs->fbrd, tmp & 0x3f);
32 
33 	/* Program LINE Control 8n1, FIFO enable */
34 	tmp = read32(&regs->lcr_h);
35 	tmp |= PL011_LINE_CONTROL;
36 	write32(&regs->lcr_h, tmp);
37 
38 	/* Enable UART */
39 	tmp = read32(&regs->cr);
40 	tmp |= PL011_UARTCR_UARTEN | PL011_UARTCR_RXE | PL011_UARTCR_TXE;
41 	write32(&regs->cr, tmp);
42 }
43 
uart_tx_byte(unsigned int idx,unsigned char data)44 void uart_tx_byte(unsigned int idx, unsigned char data)
45 {
46 	struct pl011_uart *regs = uart_platform_baseptr(idx);
47 
48 	write8(&regs->dr, data);
49 	uart_tx_flush(idx);
50 }
51 
uart_tx_flush(unsigned int idx)52 void uart_tx_flush(unsigned int idx)
53 {
54 	struct pl011_uart *regs = uart_platform_baseptr(idx);
55 
56 	/* FIXME: add a timeout */
57 	while (!(read32(&regs->fr) & PL011_UARTFR_TXFE))
58 		;
59 }
60 
uart_rx_byte(unsigned int idx)61 unsigned char uart_rx_byte(unsigned int idx)
62 {
63 	struct pl011_uart *regs = uart_platform_baseptr(idx);
64 
65 	while (read32(&regs->fr) & PL011_UARTFR_RXFE)
66 		;
67 	return read8(&regs->dr);
68 }
69 
fill_lb_serial(struct lb_serial * serial)70 enum cb_err fill_lb_serial(struct lb_serial *serial)
71 {
72 	serial->type = LB_SERIAL_TYPE_MEMORY_MAPPED;
73 	serial->baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
74 	serial->baud = get_uart_baudrate();
75 	serial->regwidth = 4;
76 	serial->input_hertz = uart_platform_refclk();
77 
78 	return CB_SUCCESS;
79 }
80