Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af568679 authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge branch 'for-3.5/debug' of...

Merge branch 'for-3.5/debug' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/drivers

By Stephen Warren
via Stephen Warren
* 'for-3.5/debug' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra:
  ARM: tegra: uncompress.h: Implement TEGRA_DEBUG_UART_AUTO_ODMDATA
parents 7a3252f8 80881dae
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ config MACH_VENTANA
         Support for the nVidia Ventana development platform

choice
        prompt "Low-level debug console UART"
        prompt "Default low-level debug console UART"
        default TEGRA_DEBUG_UART_NONE

config TEGRA_DEBUG_UART_NONE
@@ -134,6 +134,33 @@ config TEGRA_DEBUG_UARTE

endchoice

choice
	prompt "Automatic low-level debug console UART"
	default TEGRA_DEBUG_UART_AUTO_NONE

config TEGRA_DEBUG_UART_AUTO_NONE
	bool "None"

config TEGRA_DEBUG_UART_AUTO_ODMDATA
	bool "Via ODMDATA"
	help
	  Automatically determines which UART to use for low-level debug based
	  on the ODMDATA value. This value is part of the BCT, and is written
	  to the boot memory device using nvflash, or other flashing tool.
	  When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
	  0/1/2/3/4 are UART A/B/C/D/E.

config TEGRA_DEBUG_UART_AUTO_SCRATCH
	bool "Via UART scratch register"
	help
	  Automatically determines which UART to use for low-level debug based
	  on the UART scratch register value. Some bootloaders put ASCII 'D'
	  in this register when they initialize their own console UART output.
	  Using this option allows the kernel to automatically pick the same
	  UART.

endchoice

config TEGRA_SYSTEM_DMA
	bool "Enable system DMA driver for NVIDIA Tegra SoCs"
	default y
+125 −51
Original line number Diff line number Diff line
@@ -63,12 +63,6 @@ static inline void save_uart_address(void)
		buf[0] = 0;
}

/*
 * 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;
@@ -106,9 +100,49 @@ static inline void arch_decomp_setup(void)
		2,
	},
};

static inline bool uart_clocked(int i)
{
	if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
		return false;

	if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
		return false;

	return true;
}

#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
int auto_odmdata(void)
{
	volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE;
	u32 odmdata = pmc[0xa0 / 4];

	/*
	 * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART
	 * Some boards apparently swap the last two values, but we don't have
	 * any way of catering for that here, so we just accept either. If this
	 * doesn't make sense for your board, just don't enable this feature.
	 *
	 * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E.
	 */

	switch  ((odmdata >> 18) & 3) {
	case 2:
	case 3:
		break;
	default:
		return -1;
	}

	return (odmdata >> 15) & 7;
}
#endif

#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
int auto_scratch(void)
{
	int i;
	volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
	u32 chip, div;

	/*
	 * Look for the first UART that:
@@ -125,20 +159,60 @@ static inline void arch_decomp_setup(void)
	 * 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)))
		if (!uart_clocked(i))
			continue;

		uart = (volatile u8 *)uarts[i].base;
		if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
			continue;

		break;
		return i;
	}
	if (i == ARRAY_SIZE(uarts))
		uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;

	return -1;
}
#endif

/*
 * 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)
{
	int uart_id, auto_uart_id;
	volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
	u32 chip, div;

#if defined(CONFIG_TEGRA_DEBUG_UARTA)
	uart_id = 0;
#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
	uart_id = 1;
#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
	uart_id = 2;
#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
	uart_id = 3;
#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
	uart_id = 4;
#else
	uart_id = -1;
#endif

#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
	auto_uart_id = auto_odmdata();
#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
	auto_uart_id = auto_scratch();
#else
	auto_uart_id = -1;
#endif
	if (auto_uart_id != -1)
		uart_id = auto_uart_id;

	if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
	    !uart_clocked(uart_id))
		uart = NULL;
	else
		uart = (volatile u8 *)uarts[uart_id].base;

	save_uart_address();
	if (uart == NULL)
		return;