summaryrefslogtreecommitdiff
path: root/src/cpu/allwinner/a10/uart.c
diff options
context:
space:
mode:
authorAlexandru Gagniuc <mr.nuke.me@gmail.com>2013-12-13 20:44:48 -0600
committerAlexandru Gagniuc <mr.nuke.me@gmail.com>2014-01-08 22:54:08 +0100
commitf64111b4865d611821950b25dc1ea235d8d9ca79 (patch)
treed61eef4c9476ada907f0d91e93c2707aed44df96 /src/cpu/allwinner/a10/uart.c
parent34286b861a9427520f3f3afb8bf64bfa7de37c24 (diff)
downloadcoreboot-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.c98
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);
+}