Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14910
-gerrit
commit bd406a7814fc9d7181deaa2286c5827adddda5d7 Author: Akshay Saraswat akshay.s@samsung.com Date: Thu Aug 7 15:34:50 2014 +0530
Exynos7: Add UART initialization
This patch adds UART setup for Exynos7. It also enables UART-2 as default serial port.
TEST=Built and booted Coreboot Over Jazz. Saw prints over console.
Change-Id: Id5f3f69d6d3aef9efa888259534d3ad93cfed8ba Signed-off-by: Akshay Saraswat akshay.s@samsung.com Signed-off-by: Stefan Reinauer stefan.reinauer@coreboot.org --- src/soc/samsung/exynos7/Makefile.inc | 7 ++ src/soc/samsung/exynos7/include/soc/uart.h | 39 ++++++++ src/soc/samsung/exynos7/uart.c | 153 +++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+)
diff --git a/src/soc/samsung/exynos7/Makefile.inc b/src/soc/samsung/exynos7/Makefile.inc index 898260d..f17c2b0 100644 --- a/src/soc/samsung/exynos7/Makefile.inc +++ b/src/soc/samsung/exynos7/Makefile.inc @@ -28,6 +28,9 @@ bootblock-y += monotonic_timer.c bootblock-y += pinmux.c bootblock-y += power.c bootblock-y += timer.c +ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c +endif
# ROMSTAGE : Run primitive tests and remaining basic stuff romstage-y += clock.c @@ -37,6 +40,9 @@ romstage-y += monotonic_timer.c romstage-y += pinmux.c romstage-y += power.c romstage-y += timer.c +ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) +romstage-$(CONFIG_EARLY_CONSOLE) += uart.c +endif
# RAMSTAGE : Prepare and load payload ramstage-y += clock.c @@ -47,6 +53,7 @@ ramstage-y += monotonic_timer.c ramstage-y += pinmux.c ramstage-y += power.c ramstage-y += timer.c +ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c
$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf cp $< $@ diff --git a/src/soc/samsung/exynos7/include/soc/uart.h b/src/soc/samsung/exynos7/include/soc/uart.h new file mode 100644 index 0000000..d3abb43 --- /dev/null +++ b/src/soc/samsung/exynos7/include/soc/uart.h @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CPU_SAMSUNG_EXYNOS7_UART_H_ +#define _CPU_SAMSUNG_EXYNOS7_UART_H_ + +#include <stddef.h> + +struct exynos_uart { + unsigned int ulcon; + unsigned int ucon; + unsigned int ufcon; + unsigned int umcon; + unsigned int utrstat; + unsigned int uerstat; + unsigned int ufstat; + unsigned int umstat; + unsigned char utxh; + unsigned char res1[3]; + unsigned char urxh; + unsigned char res2[3]; + unsigned int ubrdiv; + unsigned char res3[0xffd0]; +}; +check_member(exynos_uart, ubrdiv, 0x28); + +#endif /* _CPU_SAMSUNG_EXYNOS7_UART_H_ */ diff --git a/src/soc/samsung/exynos7/uart.c b/src/soc/samsung/exynos7/uart.c new file mode 100644 index 0000000..3c041a7 --- /dev/null +++ b/src/soc/samsung/exynos7/uart.c @@ -0,0 +1,153 @@ +/* This file is part of the coreboot project. + * + * Copyright (C) 2014 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <types.h> +#include <uart.h> +#include <arch/io.h> +#include <console/console.h> /* for __console definition */ +#include <soc/clock.h> +#include <soc/cpu.h> +#include <soc/periph.h> +#include <soc/uart.h> + +#define RX_FIFO_COUNT_MASK 0xff +#define RX_FIFO_FULL_MASK (1 << 8) +#define TX_FIFO_FULL_MASK (1 << 24) + +static struct exynos_uart * base_port = + (struct exynos_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + +static void serial_setbrg_dev(void) +{ + struct exynos_uart *uart = base_port; + u32 uclk; + u32 baudrate = CONFIG_TTYS0_BAUD; + u32 val; + + /* All UARTs share the same clock */ + uclk = get_uart_clk(PERIPH_ID_UART2); + val = uclk / baudrate; + + write32(&uart->ubrdiv, val / 16 - 1); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + */ +static void exynos7_init_dev(void) +{ + struct exynos_uart *uart = base_port; + + /* enable FIFOs */ + write32(&uart->ufcon, 0x1); + write32(&uart->umcon, 0); + /* 8N1 */ + write32(&uart->ulcon, 0x3); + /* No interrupts, no DMA, pure polling */ + write32(&uart->ucon, 0x245); + + serial_setbrg_dev(); +} + +static int exynos7_uart_err_check(int op) +{ + struct exynos_uart *uart = base_port; + unsigned int mask; + + /* + * UERSTAT + * Break Detect [3] + * Frame Err [2] : receive operation + * Parity Err [1] : receive operation + * Overrun Err [0] : receive operation + */ + if (op) + mask = 0x8; + else + mask = 0xf; + + return read32(&uart->uerstat) & mask; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +static unsigned char exynos7_uart_rx_byte(void) +{ + struct exynos_uart *uart = base_port; + + /* wait for character to arrive */ + while (!(read32(&uart->ufstat) & (RX_FIFO_COUNT_MASK | + RX_FIFO_FULL_MASK))) { + if (exynos7_uart_err_check(0)) + return 0; + } + + return readb(&uart->urxh) & 0xff; +} + +/* + * Output a single byte to the serial port. + */ +static void exynos7_uart_tx_byte(unsigned char data) +{ + struct exynos_uart *uart = base_port; + + /* wait for room in the tx FIFO */ + while ((read32(&uart->ufstat) & TX_FIFO_FULL_MASK)) { + if (exynos7_uart_err_check(1)) + return; + } + + writeb(data, &uart->utxh); +} + +#if !defined(__PRE_RAM__) + +static const struct console_driver exynos7_uart_console __console = { + .init = exynos7_init_dev, + .tx_byte = exynos7_uart_tx_byte, + .rx_byte = exynos7_uart_rx_byte, +}; + +uint32_t uartmem_getbaseaddr(void) +{ + return ((uint32_t) (uintptr_t) base_port); +} + +#else + +void uart_init(void) +{ + exynos7_init_dev(); +} + +unsigned char uart_rx_byte(void) +{ + return exynos7_uart_rx_byte(); +} + +void uart_tx_byte(unsigned char data) +{ + exynos7_uart_tx_byte(data); +} + +void uart_tx_flush(void) +{ +} + +#endif