[coreboot-gerrit] New patch to review for coreboot: 7f8216f AM335x UART WIP

Gabe Black (gabeblack@chromium.org) gerrit at coreboot.org
Mon Jun 17 10:40:08 CEST 2013


Gabe Black (gabeblack at 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 at chromium.org>
Date:   Tue Jun 11 21:58:18 2013 -0400

    AM335x UART WIP
    
    Change-Id: If26a424cac401ef3eafaec081147f41184fbcee9
    Signed-off-by: Gabe Black <gabeblack at 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 at samsung.com>
- * Heungjun Kim <riverful.kim at 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);
 }



More information about the coreboot-gerrit mailing list