| /* SPDX-License-Identifier: GPL-2.0-only */ |
| |
| #include <device/mmio.h> |
| #include <boot/coreboot_tables.h> |
| #include <console/uart.h> |
| #include <drivers/uart/pl011.h> |
| |
| void uart_init(unsigned int idx) |
| { |
| struct pl011_uart *regs = uart_platform_baseptr(idx); |
| uint32_t tmp; |
| |
| if (!regs) |
| return; |
| |
| /* Disable UART */ |
| tmp = read32(®s->cr); |
| tmp &= ~PL011_UARTCR_UARTEN; |
| write32(®s->cr, tmp); |
| |
| /* |
| * Program Divisor |
| * As per: PL011 Technical reference manual: |
| * BAUDDIV = (Fuartclk / (16 * baud_rate)) |
| * Considering 6 bits(64) for UARTFBRD |
| * BAUDDIV = (Fuartclk * 4 / baud_rate) |
| */ |
| tmp = uart_platform_refclk() * 4 / get_uart_baudrate(); |
| |
| write32(®s->ibrd, tmp >> 6); |
| write32(®s->fbrd, tmp & 0x3f); |
| |
| /* Program LINE Control 8n1, FIFO enable */ |
| tmp = read32(®s->lcr_h); |
| tmp |= PL011_LINE_CONTROL; |
| write32(®s->lcr_h, tmp); |
| |
| /* Enable UART */ |
| tmp = read32(®s->cr); |
| tmp |= PL011_UARTCR_UARTEN | PL011_UARTCR_RXE | PL011_UARTCR_TXE; |
| write32(®s->cr, tmp); |
| } |
| |
| void uart_tx_byte(unsigned int idx, unsigned char data) |
| { |
| struct pl011_uart *regs = uart_platform_baseptr(idx); |
| |
| write8(®s->dr, data); |
| uart_tx_flush(idx); |
| } |
| |
| void uart_tx_flush(unsigned int idx) |
| { |
| struct pl011_uart *regs = uart_platform_baseptr(idx); |
| |
| /* FIXME: add a timeout */ |
| while (!(read32(®s->fr) & PL011_UARTFR_TXFE)) |
| ; |
| } |
| |
| unsigned char uart_rx_byte(unsigned int idx) |
| { |
| struct pl011_uart *regs = uart_platform_baseptr(idx); |
| |
| while (read32(®s->fr) & PL011_UARTFR_RXFE) |
| ; |
| return read8(®s->dr); |
| } |
| |
| enum cb_err fill_lb_serial(struct lb_serial *serial) |
| { |
| serial->type = LB_SERIAL_TYPE_MEMORY_MAPPED; |
| serial->baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE); |
| serial->baud = get_uart_baudrate(); |
| serial->regwidth = 4; |
| serial->input_hertz = uart_platform_refclk(); |
| |
| return CB_SUCCESS; |
| } |