blob: 06782a3b980f8ef5b4dfba7bacbef4f00fcbd099 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Hung-Te Lin7635a602013-02-12 00:07:38 +08002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +02004#include <boot/coreboot_tables.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +02005#include <console/uart.h>
David Hendricksff0d8692017-12-28 20:18:10 -08006#include <drivers/uart/pl011.h>
Hung-Te Lin7635a602013-02-12 00:07:38 +08007
Felix Helde3a12472020-09-11 15:47:09 +02008void uart_init(unsigned int idx)
Hung-Te Lin7635a602013-02-12 00:07:38 +08009{
Naresh Solanki54662612023-08-10 13:21:44 +020010 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);
Hung-Te Lin7635a602013-02-12 00:07:38 +080042}
43
Felix Helde3a12472020-09-11 15:47:09 +020044void uart_tx_byte(unsigned int idx, unsigned char data)
Hung-Te Lin7635a602013-02-12 00:07:38 +080045{
David Hendricksff0d8692017-12-28 20:18:10 -080046 struct pl011_uart *regs = uart_platform_baseptr(idx);
47
48 write8(&regs->dr, data);
49 uart_tx_flush(idx);
Hung-Te Lin7635a602013-02-12 00:07:38 +080050}
51
Felix Helde3a12472020-09-11 15:47:09 +020052void uart_tx_flush(unsigned int idx)
Kyösti Mälkki7e75f202014-02-10 23:21:14 +020053{
David Hendricksff0d8692017-12-28 20:18:10 -080054 struct pl011_uart *regs = uart_platform_baseptr(idx);
55
56 /* FIXME: add a timeout */
57 while (!(read32(&regs->fr) & PL011_UARTFR_TXFE))
58 ;
Hung-Te Lin7635a602013-02-12 00:07:38 +080059}
Kyösti Mälkki0567c912014-02-14 10:31:38 +020060
Felix Helde3a12472020-09-11 15:47:09 +020061unsigned char uart_rx_byte(unsigned int idx)
Kyösti Mälkki0567c912014-02-14 10:31:38 +020062{
Marcello Sylvester Bauer24231892018-04-11 15:55:02 +020063 struct pl011_uart *regs = uart_platform_baseptr(idx);
64
65 while (read32(&regs->fr) & PL011_UARTFR_RXFE)
66 ;
67 return read8(&regs->dr);
Kyösti Mälkki0567c912014-02-14 10:31:38 +020068}
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +020069
Arthur Heymans9948c522022-10-24 14:37:40 +020070enum cb_err fill_lb_serial(struct lb_serial *serial)
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +020071{
Arthur Heymans9948c522022-10-24 14:37:40 +020072 serial->type = LB_SERIAL_TYPE_MEMORY_MAPPED;
73 serial->baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
74 serial->baud = get_uart_baudrate();
Arthur Heymanse67513e2023-08-02 19:52:45 +020075 serial->regwidth = 4;
Arthur Heymans9948c522022-10-24 14:37:40 +020076 serial->input_hertz = uart_platform_refclk();
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +020077
Arthur Heymans9948c522022-10-24 14:37:40 +020078 return CB_SUCCESS;
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +020079}