diff options
author | Alexandru Gagniuc <mr.nuke.me@gmail.com> | 2013-12-13 20:44:48 -0600 |
---|---|---|
committer | Alexandru Gagniuc <mr.nuke.me@gmail.com> | 2014-01-08 22:54:08 +0100 |
commit | f64111b4865d611821950b25dc1ea235d8d9ca79 (patch) | |
tree | d61eef4c9476ada907f0d91e93c2707aed44df96 /src/cpu/allwinner/a10/uart.c | |
parent | 34286b861a9427520f3f3afb8bf64bfa7de37c24 (diff) | |
download | coreboot-f64111b4865d611821950b25dc1ea235d8d9ca79.tar.xz |
cpu: Add initial support for Allwinner A10 SoC
Add minimal support needed to get a bootblock capable of initialising
a serial console.
Change-Id: I50dd85544549baf9c5ea0aa3b4296972136c02a4
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Reviewed-on: http://review.coreboot.org/4549
Tested-by: build bot (Jenkins)
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/cpu/allwinner/a10/uart.c')
-rw-r--r-- | src/cpu/allwinner/a10/uart.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/cpu/allwinner/a10/uart.c b/src/cpu/allwinner/a10/uart.c new file mode 100644 index 0000000000..dc98bffbdf --- /dev/null +++ b/src/cpu/allwinner/a10/uart.c @@ -0,0 +1,98 @@ +/* + * Uart setup helpers for Allwinner SoCs + * + * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com> + * Subject to the GNU GPL v2, or (at your option) any later version. + */ + +#include "uart.h" +#include <arch/io.h> + +/* Give me my 8250 UART definitions!!!! */ +/* TODO: Clean this up when uart8250mem works on ARM */ +#undef CONFIG_CONSOLE_SERIAL8250MEM +#define CONFIG_CONSOLE_SERIAL8250MEM 1 +#include <uart8250.h> + +/** + * \brief Configure line control settings for UART + */ +void a10_uart_configure(void *uart_base, u32 baud_rate, u8 data_bits, + enum uart_parity parity, u8 stop_bits) +{ + u32 reg32; + u16 div; + struct a10_uart *uart = uart_base; + + /* Enable access to Divisor Latch register */ + write32(UART_LCR_DLAB, &uart->lcr); + /* Set baudrate */ + /* FIXME: We assume clock is 24MHz, which may not be the case */ + div = 24000000 / 16 / baud_rate; + write32((div >> 8) & 0xff, &uart->dlh); + write32(div & 0xff, &uart->dll); + /* Set line control */ + reg32 = (data_bits - 5) & UART_LCR_WLS_MSK; + switch (parity) { + case UART_PARITY_ODD: + reg32 |= UART_LCR_PEN; + break; + case UART_PARITY_EVEN: + reg32 |= UART_LCR_PEN; + reg32 |= UART_LCR_EPS; + break; + case UART_PARITY_NONE: /* Fall through */ + default: + break; + } + write32(reg32, &uart->lcr); +} + +void a10_uart_enable_fifos(void *uart_base) +{ + struct a10_uart *uart = uart_base; + + write32(UART_FCR_FIFO_EN, &uart->fcr); +} + +static int tx_fifo_full(struct a10_uart *uart) +{ + /* This may be a misnomer, or a typo in the datasheet. THRE indicates + * that the TX register is empty, not that the FIFO is not full, but + * this may be due to a datasheet typo. Keep the current name to signal + * intent. */ + return !(read32(&uart->lsr) & UART_LSR_THRE); +} + +static int rx_fifo_empty(struct a10_uart *uart) +{ + return !(read32(&uart->lsr) & UART_LSR_DR); +} + +/** + * \brief Read a single byte from the UART. + * + * Blocks until at least a byte is available. + */ +u8 a10_uart_rx_blocking(void *uart_base) +{ + struct a10_uart *uart = uart_base; + + while (rx_fifo_empty(uart)) ; + + return read32(&uart->rbr); +} + +/** + * \brief Write a single byte to the UART. + * + * Blocks until there is space in the FIFO. + */ +void a10_uart_tx_blocking(void *uart_base, u8 data) +{ + struct a10_uart *uart = uart_base; + + while (tx_fifo_full(uart)) ; + + return write32(data, &uart->thr); +} |