|
@@ -3,11 +3,13 @@
|
|
|
*
|
|
|
* Copyright (C) 2010 Google, Inc.
|
|
|
* Copyright (C) 2011 Google, Inc.
|
|
|
+ * Copyright (C) 2011 NVIDIA CORPORATION. All Rights Reserved.
|
|
|
*
|
|
|
* Author:
|
|
|
* Colin Cross <ccross@google.com>
|
|
|
* Erik Gilling <konkers@google.com>
|
|
|
* Doug Anderson <dianders@chromium.org>
|
|
|
+ * Stephen Warren <swarren@nvidia.com>
|
|
|
*
|
|
|
* This software is licensed under the terms of the GNU General Public
|
|
|
* License version 2, as published by the Free Software Foundation, and
|
|
@@ -23,6 +25,7 @@
|
|
|
#ifndef __MACH_TEGRA_UNCOMPRESS_H
|
|
|
#define __MACH_TEGRA_UNCOMPRESS_H
|
|
|
|
|
|
+#include <linux/kernel.h>
|
|
|
#include <linux/types.h>
|
|
|
#include <linux/serial_reg.h>
|
|
|
|
|
@@ -46,12 +49,82 @@ static inline void flush(void)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Setup before decompression. This is where we do UART selection for
|
|
|
+ * earlyprintk and init the uart_base register.
|
|
|
+ */
|
|
|
static inline void arch_decomp_setup(void)
|
|
|
{
|
|
|
+ static const struct {
|
|
|
+ u32 base;
|
|
|
+ u32 reset_reg;
|
|
|
+ u32 clock_reg;
|
|
|
+ u32 bit;
|
|
|
+ } uarts[] = {
|
|
|
+ {
|
|
|
+ TEGRA_UARTA_BASE,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x04,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x10,
|
|
|
+ 6,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TEGRA_UARTB_BASE,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x04,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x10,
|
|
|
+ 7,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TEGRA_UARTC_BASE,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x08,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x14,
|
|
|
+ 23,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TEGRA_UARTD_BASE,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x0c,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x18,
|
|
|
+ 1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TEGRA_UARTE_BASE,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x0c,
|
|
|
+ TEGRA_CLK_RESET_BASE + 0x18,
|
|
|
+ 2,
|
|
|
+ },
|
|
|
+ };
|
|
|
+ int i;
|
|
|
volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
|
|
|
u32 chip, div;
|
|
|
|
|
|
- uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
|
|
|
+ /*
|
|
|
+ * Look for the first UART that:
|
|
|
+ * a) Is not in reset.
|
|
|
+ * b) Is clocked.
|
|
|
+ * c) Has a 'D' in the scratchpad register.
|
|
|
+ *
|
|
|
+ * Note that on Tegra30, the first two conditions are required, since
|
|
|
+ * if not true, accesses to the UART scratch register will hang.
|
|
|
+ * Tegra20 doesn't have this issue.
|
|
|
+ *
|
|
|
+ * The intent is that the bootloader will tell the kernel which UART
|
|
|
+ * to use by setting up those conditions. If nothing found, we'll fall
|
|
|
+ * back to what's specified in TEGRA_DEBUG_UART_BASE.
|
|
|
+ */
|
|
|
+ for (i = 0; i < ARRAY_SIZE(uarts); i++) {
|
|
|
+ if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ uart = (volatile u8 *)uarts[i].base;
|
|
|
+ if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
|
|
|
+ continue;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (i == ARRAY_SIZE(uarts))
|
|
|
+ uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
|
|
|
if (uart == NULL)
|
|
|
return;
|
|
|
|