aboutsummaryrefslogtreecommitdiff
path: root/src/soc/nvidia/tegra132/uart.c
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@google.com>2014-06-09 13:20:04 -0700
committerMarc Jones <marc.jones@se-eng.com>2015-03-02 21:17:21 +0100
commit732b83ed3667d7c3066d2c16406ab6acdd8f32b9 (patch)
treec8b7252aeab5fe29c175b50e17201e23340daa33 /src/soc/nvidia/tegra132/uart.c
parent280a29d5bb5ea53ae92380a95cf8eb4543f96749 (diff)
tegra132: Enable bootblock support in tegra132 including UART support
BUG=None BRANCH=None TEST=Compiles successfully Original-Change-Id: Ia9420cfec5333dd5477f04cf080bdad8a37db025 Original-Signed-off-by: Furquan Shaikh <furquan@google.com> Original-Reviewed-on: https://chromium-review.googlesource.com/203143 Original-Tested-by: Furquan Shaikh <furquan@chromium.org> Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org> Original-Commit-Queue: Aaron Durbin <adurbin@chromium.org> (cherry picked from commit a1037f203c6a07cb116eeb1632cb7200ad022cd3) This cherry-pick was modified to match the tegra124 uart.c, which uses the idx and base address calculations instead of Kconfig settings. This driver could use the 8250MEM driver when the ARM vs x86 IO calling convention is worked out. Change-Id: I6e439359b8bb541db4679ac144c519cf251ffed6 Signed-off-by: Marc Jones <marc.jones@se-eng.com> Reviewed-on: http://review.coreboot.org/8517 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-by: Aaron Durbin <adurbin@google.com>
Diffstat (limited to 'src/soc/nvidia/tegra132/uart.c')
-rw-r--r--src/soc/nvidia/tegra132/uart.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/soc/nvidia/tegra132/uart.c b/src/soc/nvidia/tegra132/uart.c
new file mode 100644
index 0000000000..80328af9bf
--- /dev/null
+++ b/src/soc/nvidia/tegra132/uart.c
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/uart.h>
+#include <arch/io.h>
+#include <boot/coreboot_tables.h>
+#include <console/console.h> /* for __console definition */
+#include <stdint.h>
+#include <drivers/uart/uart8250reg.h>
+
+/*
+ * TODO: Use DRIVERS_UART_8250MEM driver instead.
+ * There is an issue in the IO call functions where x86 and ARM
+ * ordering is reversed. This 8250MEM driver uses the x86 convention.
+ * This driver can be replaced once the IO calls are sorted.
+ */
+struct tegra132_uart {
+ union {
+ uint32_t thr; // Transmit holding register.
+ uint32_t rbr; // Receive buffer register.
+ uint32_t dll; // Divisor latch lsb.
+ };
+ union {
+ uint32_t ier; // Interrupt enable register.
+ uint32_t dlm; // Divisor latch msb.
+ };
+ union {
+ uint32_t iir; // Interrupt identification register.
+ uint32_t fcr; // FIFO control register.
+ };
+ uint32_t lcr; // Line control register.
+ uint32_t mcr; // Modem control register.
+ uint32_t lsr; // Line status register.
+ uint32_t msr; // Modem status register.
+} __attribute__ ((packed));
+
+static void tegra132_uart_tx_flush(struct tegra132_uart *uart_ptr);
+static int tegra132_uart_tst_byte(struct tegra132_uart *uart_ptr);
+
+static void tegra132_uart_init(struct tegra132_uart *uart_ptr)
+{
+ const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1
+
+ uint16_t divisor = (u16) uart_baudrate_divisor(default_baudrate(),
+ uart_platform_refclk(), 16);
+
+ tegra132_uart_tx_flush(uart_ptr);
+
+ // Disable interrupts.
+ write8(0, &uart_ptr->ier);
+ // Force DTR and RTS to high.
+ write8(UART8250_MCR_DTR | UART8250_MCR_RTS, &uart_ptr->mcr);
+ // Set line configuration, access divisor latches.
+ write8(UART8250_LCR_DLAB | line_config, &uart_ptr->lcr);
+ // Set the divisor.
+ write8(divisor & 0xff, &uart_ptr->dll);
+ write8((divisor >> 8) & 0xff, &uart_ptr->dlm);
+ // Hide the divisor latches.
+ write8(line_config, &uart_ptr->lcr);
+ // Enable FIFOs, and clear receive and transmit.
+ write8(UART8250_FCR_FIFO_EN |
+ UART8250_FCR_CLEAR_RCVR |
+ UART8250_FCR_CLEAR_XMIT, &uart_ptr->fcr);
+}
+
+static unsigned char tegra132_uart_rx_byte(struct tegra132_uart *uart_ptr)
+{
+ if (!tegra132_uart_tst_byte(uart_ptr))
+ return 0;
+ return read8(&uart_ptr->rbr);
+}
+
+static void tegra132_uart_tx_byte(struct tegra132_uart *uart_ptr, unsigned char data)
+{
+ while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE));
+ write8(data, &uart_ptr->thr);
+}
+
+static void tegra132_uart_tx_flush(struct tegra132_uart *uart_ptr)
+{
+ while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT));
+}
+
+static int tegra132_uart_tst_byte(struct tegra132_uart *uart_ptr)
+{
+ return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR;
+}
+
+/* FIXME: Add mainboard override */
+unsigned int uart_platform_refclk(void)
+{
+ return 408000000;
+}
+
+uintptr_t uart_platform_base(int idx)
+{
+ /* Default to UART A */
+ unsigned int base = 0x70006000;
+ /* UARTs A - E are mapped as index 0 - 4 */
+ if ((idx < 5) && (idx >= 0)) {
+ if (idx != 1) { /* Not UART B */
+ base += idx * 0x100;
+ } else {
+ base += 0x40;
+ }
+ }
+ return base;
+}
+
+void uart_init(int idx)
+{
+ struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+ tegra132_uart_init(uart_ptr);
+}
+
+unsigned char uart_rx_byte(int idx)
+{
+ struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+ return tegra132_uart_rx_byte(uart_ptr);
+}
+
+void uart_tx_byte(int idx, unsigned char data)
+{
+ struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+ tegra132_uart_tx_byte(uart_ptr, data);
+}
+
+void uart_tx_flush(int idx)
+{
+ struct tegra132_uart *uart_ptr = uart_platform_baseptr(idx);
+ tegra132_uart_tx_flush(uart_ptr);
+}
+
+#ifndef __PRE_RAM__
+void uart_fill_lb(void *data)
+{
+ struct lb_serial serial;
+ serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
+ serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
+ serial.baud = default_baudrate();
+ lb_add_serial(&serial, data);
+
+ lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
+}
+#endif