diff options
| -rw-r--r-- | arch/arm/mach-tegra/include/mach/uncompress.h | 75 | 
1 files changed, 74 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index bb3fd359f9fa..6c087b6974b2 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h @@ -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;  | 
