Gabe Black (gabeblack@chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3490
-gerrit
commit 7f8216f2344c3b8f87a1284bb6c7c7baee540df2 Author: Gabe Black gabeblack@chromium.org Date: Tue Jun 11 21:58:18 2013 -0400
AM335x UART WIP
Change-Id: If26a424cac401ef3eafaec081147f41184fbcee9 Signed-off-by: Gabe Black gabeblack@chromium.org --- src/cpu/ti/am335x/uart.c | 187 ++++++++++++++++++++++++-------- src/mainboard/ti/beaglebone/bootblock.c | 31 ++++++ 2 files changed, 173 insertions(+), 45 deletions(-)
diff --git a/src/cpu/ti/am335x/uart.c b/src/cpu/ti/am335x/uart.c index fdf5c05..51254048 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,36 @@
#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) + +#if 0 +enum register_mode { + CONFIG_A, /* config mode A, LCR[7] = 1, LCR[7:0] != 0xBF */ + CONFIG_B, /* config mode B, LCR[7] = 1, LCR[7:0] = 0xBF */ + OP, /* operational mode LCR[7] = 0 */ +}; + +static void set_register_mode(enum register_mode mode) +{ + switch (mode) { + case CONFIG_A: + break; + case CONFIG_B: + break; + case OP: + break; + default: + break; + }; +} +#endif
/* * Initialise the serial port with the given baudrate. The settings @@ -39,28 +62,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; + */ + + /* 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? */ + }
- // TODO initialize with correct peripheral id by base_port. - exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); + /* 8. Switch to operational mode to access ier */ + write16(0x0, &uart->lcr);
- /* 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); + /* 9. Clear ier to disable all interrupts */ + write16(0x0, &uart->ier);
- serial_setbrg_dev(); -#endif + /* 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 +181,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; + struct am335x_uart *uart = + (struct am335x_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
- /* 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; - } + while (!(read16(&uart->lsr) & LSR_RXFIFOE));
- return readb(&uart->urxh) & 0xff; -#endif - return 0xaa; + return read8(&uart->rhr); }
/* @@ -91,18 +194,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; + struct am335x_uart *uart = + (struct am335x_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
- /* wait for room in the tx FIFO */ - while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) { - if (exynos5_uart_err_check(1)) - return; - } + while (!(read16(&uart->lsr) & LSR_TXFIFOE));
- writeb(data, &uart->utxh); -#endif + return write8(data, &uart->thr); }
uint32_t uartmem_getbaseaddr(void) diff --git a/src/mainboard/ti/beaglebone/bootblock.c b/src/mainboard/ti/beaglebone/bootblock.c index fbe73ea..18b5738 100644 --- a/src/mainboard/ti/beaglebone/bootblock.c +++ b/src/mainboard/ti/beaglebone/bootblock.c @@ -21,10 +21,13 @@ #include <types.h> #include <uart.h> #include <console/console.h> +#include <cpu/ti/am335x/pinmux.h>
void bootblock_mainboard_init(void); void bootblock_mainboard_init(void) { + void *uart_clock_ctrl = NULL; + /* Enable the GPIO module */ writel((0x2 << 0) | (1 << 18), (uint32_t *)(0x44e00000 + 0xac));
@@ -38,8 +41,36 @@ void bootblock_mainboard_init(void) clrbits_le32((uint32_t *)(0x4804c000 + 0x13c), 0xf << 21); setbits_le32((uint32_t *)(0x4804c000 + 0x13c), 0x5 << 21);
+ writel(0x2, ((uint32_t *)(0x44e00000 + 0x0))); + + /* Set up the UART we're going to use */ + if (CONFIG_CONSOLE_SERIAL_UART0) { + am335x_pinmux_uart0(); + uart_clock_ctrl = (void *)(uintptr_t)(0x44e00400 + 0xb4); + } else if (CONFIG_CONSOLE_SERIAL_UART1) { + am335x_pinmux_uart1(); + uart_clock_ctrl = (void *)(uintptr_t)(0x44e00000 + 0x6c); + } else if (CONFIG_CONSOLE_SERIAL_UART2) { + am335x_pinmux_uart2(); + uart_clock_ctrl = (void *)(uintptr_t)(0x44e00000 + 0x70); + } else if (CONFIG_CONSOLE_SERIAL_UART3) { + am335x_pinmux_uart3(); + uart_clock_ctrl = (void *)(uintptr_t)(0x44e00000 + 0x74); + } else if (CONFIG_CONSOLE_SERIAL_UART4) { + am335x_pinmux_uart4(); + uart_clock_ctrl = (void *)(uintptr_t)(0x44e00000 + 0x78); + } else if (CONFIG_CONSOLE_SERIAL_UART5) { + am335x_pinmux_uart5(); + uart_clock_ctrl = (void *)(uintptr_t)(0x44e00000 + 0x38); + } + if (uart_clock_ctrl) + writel(0x2, uart_clock_ctrl); + /* Start monotonic timer */ //rtc_start();
console_init(); + + clrbits_le32((uint32_t *)(0x4804c000 + 0x13c), 0xf << 21); + setbits_le32((uint32_t *)(0x4804c000 + 0x13c), 0x3 << 21); }