Ronald G. Minnich (rminnich@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2414
-gerrit
commit cfc311f8d0b3cbdf99ff427d6e2fac4a3b72f57d Author: Ronald G. Minnich rminnich@gmail.com Date: Fri Feb 15 09:44:28 2013 -0800
libpayload: add support for the exynos5 UART
This CL adds *limited* support for the exynos5 uart. IO operations are supported; because of the plethora of other hardware that it would bring in, we've decided for now to leave out configuration operations such as setting baud rate. Set it right in coreboot and leave it alone. We support read, write, and test for input as in the existing serial.c.
Add two new variables, EXYNOS5_SERIAL_CONSOLE -- enable it EXYNOS5_SERIAL_BASE -- set the base
in Config.in, add options for selecting the UART and setting its base address; a reasonable default is configured.
Set that default into sysinfo if EXYNOS5_SERIAL_CONSOLE is set.
Compile the UART in if EXYNOS5_SERIAL_CONSOLE is set.
Add the slightly truncated code from coreboot; don't bother with an include file, only this one file needs to see the structs. This is one case where an include file would do more harm than good.
Change-Id: Iff1f601a8ba5e69d63eb10763e748c92a03a3df8 Signed-off-by: Ronald G. Minnich rminnich@gmail.com --- payloads/libpayload/Config.in | 12 ++- payloads/libpayload/arch/armv7/sysinfo.c | 3 + payloads/libpayload/drivers/Makefile.inc | 1 + payloads/libpayload/drivers/exynos5250_uart.c | 128 ++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 1 deletion(-)
diff --git a/payloads/libpayload/Config.in b/payloads/libpayload/Config.in index a14291d..ccc9449 100644 --- a/payloads/libpayload/Config.in +++ b/payloads/libpayload/Config.in @@ -70,7 +70,7 @@ choice config ARCH_ARMV7 bool "ARMv7" help - Support the x86 architecture + Support the ARMV7 architecture
config ARCH_POWERPC bool "PowerPC" @@ -168,6 +168,16 @@ config SERIAL_CONSOLE bool "See output on the serial port console" default y
+config EXYNOS5_SERIAL_CONSOLE + bool "Exynos 5xxx serial console" + depends on ARCH_ARMV7 + default n + +config EXYNOS5_SERIAL_BASE + hex "Base for the Exynos5 serial port" + depends on EXYNOS5_SERIAL_CONSOLE + default 0x12c30000 + config SERIAL_IOBASE hex "I/O base for the serial port (default 0x3f8)" depends on SERIAL_CONSOLE diff --git a/payloads/libpayload/arch/armv7/sysinfo.c b/payloads/libpayload/arch/armv7/sysinfo.c index 5aa5175..fc527d2 100644 --- a/payloads/libpayload/arch/armv7/sysinfo.c +++ b/payloads/libpayload/arch/armv7/sysinfo.c @@ -37,6 +37,9 @@ */ struct sysinfo_t lib_sysinfo = { .cpu_khz = 200, +#ifdef CONFIG_SERIAL_CONSOLE + .ser_base = CONFIG_EXYNOS5_SERIAL_BASE, +#endif };
int lib_get_sysinfo(void) diff --git a/payloads/libpayload/drivers/Makefile.inc b/payloads/libpayload/drivers/Makefile.inc index e3bb995..71c2519 100644 --- a/payloads/libpayload/drivers/Makefile.inc +++ b/payloads/libpayload/drivers/Makefile.inc @@ -34,6 +34,7 @@ libc-$(CONFIG_PCI) += pci.c libc-$(CONFIG_SPEAKER) += speaker.c
libc-$(CONFIG_SERIAL_CONSOLE) += serial.c +libc-$(CONFIG_EXYNOS5_SERIAL_CONSOLE) += exynos5250_uart.c
libc-$(CONFIG_PC_KEYBOARD) += keyboard.c
diff --git a/payloads/libpayload/drivers/exynos5250_uart.c b/payloads/libpayload/drivers/exynos5250_uart.c new file mode 100644 index 0000000..731e41e --- /dev/null +++ b/payloads/libpayload/drivers/exynos5250_uart.c @@ -0,0 +1,128 @@ +/* + * (C) Copyright 2013 Google, Inc. + * (C) Copyright 2009 SAMSUNG Electronics + * Minkyu Kang mk7.kang@samsung.com + * Heungjun Kim riverful.kim@samsung.com + * + * based on drivers/serial/s3c64xx.c + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * this is a seriously cut-down UART implementation, the assumption + * being that you should let coreboot set it up. It's quite + * messy to keep doing UART setup everywhere on these ARM SOCs. + */ + +#include <libpayload-config.h> +#include <libpayload.h> + +/* baudrate rest value */ +union br_rest { + unsigned short slot; /* udivslot */ + unsigned char value; /* ufracval */ +}; + +struct s5p_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; + union br_rest rest; + unsigned char res3[0xffd0]; +}; + +#define MEMBASE (struct s5p_uart *)(phys_to_virt(lib_sysinfo.serial->baseaddr)) +#define RX_FIFO_COUNT_MASK 0xff +#define RX_FIFO_FULL_MASK (1 << 8) +#define TX_FIFO_FULL_MASK (1 << 24) + +/* + * Initialise the serial port. + * This hardware is really complex, and we're not going to pretend + * it's a good idea to mess with it here. So, take what coreboot did + * and leave it at that. + */ +void serial_init(void) +{ +} + +static int exynos5_uart_err_check(int op) +{ + struct s5p_uart *uart = MEMBASE; + 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 readl(&uart->uerstat) & mask; +} + +int serial_havechar(void) +{ + struct s5p_uart *uart = MEMBASE; + return (readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK | + RX_FIFO_FULL_MASK)); +} + +int serial_getchar(void) +{ + struct s5p_uart *uart = MEMBASE; + + /* wait for character to arrive */ + while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK | + RX_FIFO_FULL_MASK))) { + if (exynos5_uart_err_check(0)) + return 0; + } + + return readb(&uart->urxh) & 0xff; +} + +/* + * Output a single byte to the serial port. + */ +void serial_putchar(unsigned int c) +{ + struct s5p_uart *uart = MEMBASE; + + /* wait for room in the tx FIFO */ + while ((readl(uart->ufstat) & TX_FIFO_FULL_MASK)) { + if (exynos5_uart_err_check(1)) + return; + } + + writeb(c, &uart->utxh); +}