Paul Menzel (paulepanter@users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3490
-gerrit
commit ce93a9b706d8401047a212057647b6efa01ae530 Author: Gabe Black gabeblack@chromium.org Date: Tue Jun 11 21:58:18 2013 -0400
am335x: Implement support for the Uart.
This patch was started by Dave Hendricks and implements the procedure for setting up the UART as described in the manual. Some unused code was removed.
Change-Id: If26a424cac401ef3eafaec081147f41184fbcee9 Signed-off-by: Gabe Black gabeblack@chromium.org --- src/cpu/ti/am335x/uart.c | 175 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 125 insertions(+), 50 deletions(-)
diff --git a/src/cpu/ti/am335x/uart.c b/src/cpu/ti/am335x/uart.c index fdf5c05..87ee86a 100644 --- a/src/cpu/ti/am335x/uart.c +++ b/src/cpu/ti/am335x/uart.c @@ -1,9 +1,5 @@ /* - * (C) Copyright 2009 SAMSUNG Electronics - * Minkyu Kang mk7.kang@samsung.com - * Heungjun Kim riverful.kim@samsung.com - * - * based on drivers/serial/s3c64xx.c + * Copyright 2013 Google Inc. * * 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 @@ -18,9 +14,9 @@ * 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 - * */
+#include <config.h> #include <types.h> #include <uart.h> #include <arch/io.h> @@ -29,9 +25,14 @@
#include <cpu/ti/am335x/uart.h>
-#define RX_FIFO_COUNT_MASK 0xff -#define RX_FIFO_FULL_MASK (1 << 8) -#define TX_FIFO_FULL_MASK (1 << 24) +#define EFR_ENHANCED_EN (1 << 4) +#define FCR_FIFO_EN (1 << 0) +#define MCR_TCR_TLR (1 << 6) +#define SYSC_SOFTRESET (1 << 1) +#define SYSS_RESETDONE (1 << 0) + +#define LSR_RXFIFOE (1 << 0) +#define LSR_TXFIFOE (1 << 5)
/* * Initialise the serial port with the given baudrate. The settings @@ -39,28 +40,116 @@ */ static void am335x_uart_init_dev(void) { + struct am335x_uart *uart = (struct am335x_uart *) + CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + uint16_t lcr_orig, efr_orig, mcr_orig; + /* FIXME: implement this * ref: section 19.4.1.1.1 for reset * ref: section 19.4.1.1.2 for FIFO, skip DMA * ref: section 19.4.1.1.3 for baud rate, skip * interrupts and protocol stuff. - * */ -#if 0 - struct s5p_uart *uart = (struct s5p_uart *)base_port; - - // TODO initialize with correct peripheral id by base_port. - exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); - - /* enable FIFOs */ - writel(0x1, &uart->ufcon); - writel(0, &uart->umcon); - /* 8N1 */ - writel(0x3, &uart->ulcon); - /* No interrupts, no DMA, pure polling */ - writel(0x245, &uart->ucon); - - serial_setbrg_dev(); -#endif + */ + + /* reset the UART */ + write16(uart->sysc | SYSC_SOFTRESET, &uart->sysc); + while (!(read16(&uart->syss) & SYSS_RESETDONE)) + ; + + /* 1. switch to register config mode B */ + lcr_orig = read16(&uart->lcr); + write16(0xbf, &uart->lcr); + + /* + * 2. Set EFR ENHANCED_EN bit. To access this bit, registers must + * be in TCR_TLR submode, meaning EFR[4] = 1 and MCR[6] = 1. + */ + efr_orig = read16(&uart->efr); + write16(efr_orig | EFR_ENHANCED_EN, &uart->efr); + + /* 3. Switch to register config mode A */ + write16(0x80, &uart->lcr); + + /* 4. Enable register submode TCR_TLR to access the UARTi.UART_TLR */ + mcr_orig = read16(&uart->mcr); + write16(mcr_orig | MCR_TCR_TLR, &uart->mcr); + + /* 5. Enable the FIFO. For now we'll ignore FIFO triggers and DMA */ + write16(FCR_FIFO_EN, &uart->fcr); + + /* 6. Switch to configuration mode B */ + write16(0xbf, &uart->lcr); + /* Skip steps 7 and 8 (setting up FIFO triggers for DMA) */ + + /* 9. Restore original EFR value */ + write16(efr_orig, &uart->efr); + + /* 10. Switch to config mode A */ + write16(0x80, &uart->lcr); + + /* 11. Restore original MCR value */ + write16(mcr_orig, &uart->mcr); + + /* 12. Restore original LCR value */ + write16(lcr_orig, &uart->lcr); + + /* Protocol, baud rate and interrupt settings */ + + /* 1. Disable UART access to DLL and DLH registers */ + write16(read16(&uart->mdr1) | 0x7, &uart->mdr1); + + /* 2. Switch to config mode B */ + write16(0xbf, &uart->lcr); + + /* 3. Enable access to IER[7:4] */ + write16(efr_orig | EFR_ENHANCED_EN, &uart->efr); + + /* 4. Switch to operational mode */ + write16(0x0, &uart->lcr); + + /* 5. Clear IER */ + write16(0x0, &uart->ier); + + /* 6. Switch to config mode B */ + write16(0xbf, &uart->lcr); + + /* 7. Set dll and dlh to the desired values (table 19-25) */ + if (CONFIG_CONSOLE_SERIAL_9600) { + write16(0x01, &uart->dlh); + write16(0x38, &uart->dll); + } else if (CONFIG_CONSOLE_SERIAL_19200) { + write16(0x00, &uart->dlh); + write16(0x9c, &uart->dll); + } else if (CONFIG_CONSOLE_SERIAL_38400) { + write16(0x00, &uart->dlh); + write16(0x4e, &uart->dll); + } else if (CONFIG_CONSOLE_SERIAL_57600) { + write16(0x00, &uart->dlh); + write16(0x34, &uart->dll); + } else if (CONFIG_CONSOLE_SERIAL_115200) { + write16(0x00, &uart->dlh); + write16(0x1a, &uart->dll); + } else { + /* Unrecognized baud rate? */ + } + + /* 8. Switch to operational mode to access ier */ + write16(0x0, &uart->lcr); + + /* 9. Clear ier to disable all interrupts */ + write16(0x0, &uart->ier); + + /* 10. Switch to config mode B */ + write16(0xbf, &uart->lcr); + + /* 11. Restore efr */ + write16(efr_orig, &uart->efr); + + /* 12. Set protocol formatting 8n1 (8 bit data, no parity, 1 stop bit) */ + write16(0x3, &uart->lcr); + + /* 13. Load the new UART mode */ + write16(0x0, &uart->mdr1); }
/* @@ -70,20 +159,12 @@ static void am335x_uart_init_dev(void) */ static unsigned char am335x_uart_rx_byte(void) { - /* FIXME: stub */ -#if 0 - struct s5p_uart *uart = (struct s5p_uart *)base_port; - - /* 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; - } + struct am335x_uart *uart = + (struct am335x_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
- return readb(&uart->urxh) & 0xff; -#endif - return 0xaa; + while (!(read16(&uart->lsr) & LSR_RXFIFOE)); + + return read8(&uart->rhr); }
/* @@ -91,18 +172,12 @@ static unsigned char am335x_uart_rx_byte(void) */ static void am335x_uart_tx_byte(unsigned char data) { - /* FIXME: stub */ -#if 0 - struct s5p_uart *uart = (struct s5p_uart *)base_port; - - /* wait for room in the tx FIFO */ - while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) { - if (exynos5_uart_err_check(1)) - return; - } + struct am335x_uart *uart = + (struct am335x_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
- writeb(data, &uart->utxh); -#endif + while (!(read16(&uart->lsr) & LSR_TXFIFOE)); + + return write8(data, &uart->thr); }
uint32_t uartmem_getbaseaddr(void)