uncompress.h now saves the selected UART's physical address in Tegra's
IRAM, along with a cookie to indicate validity.

The first time it's run, macro addruart in debug-macro.S looks for this
cookie, and if it's present, uses the UART address stored there. If not,
the static value TEGRA_DEBUG_UART_BASE is used, as was previous behaviour.
The static behaviour will thus be used when not booting using a zImage.

This work was inspired by work by Doug Anderson <[email protected]>;
see http://lkml.org/lkml/2011/9/26/284. However, this patch relies on
the data passing describe above, rather than duplicating the UART
selection logic in debug-macro.S; the latest selection logic is more
complex due to the need to check reset/clock bits too.

Signed-off-by: Stephen Warren <[email protected]>
---
 arch/arm/mach-tegra/common.c                   |   17 +++++
 arch/arm/mach-tegra/include/mach/debug-macro.S |   87 +++++++++++++++++++++---
 arch/arm/mach-tegra/include/mach/uncompress.h  |   12 +++
 3 files changed, 105 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index a2eb901..76210e5 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -33,6 +33,23 @@
 #include "clock.h"
 #include "fuse.h"
 
+/*
+ * Storage for debug-macro.S's state.
+ *
+ * This must be in .data not .bss so that it gets initialized each time the
+ * kernel is loaded. The data is declared here rather than debug-macro.S so
+ * that multiple inclusions of debug-macro.S point at the same data.
+ */
+#define TEGRA_DEBUG_UART_OFFSET (TEGRA_DEBUG_UART_BASE & 0xFFFF)
+u32 tegra_uart_config[3] = {
+       /* Debug UART initialization required */
+       1,
+       /* Debug UART physical address */
+       (u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET),
+       /* Debug UART virtual address */
+       (u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET),
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id tegra_dt_irq_match[] __initconst = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init },
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S 
b/arch/arm/mach-tegra/include/mach/debug-macro.S
index 619abc6..94802a5 100644
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -1,11 +1,17 @@
 /*
  * arch/arm/mach-tegra/include/mach/debug-macro.S
  *
- * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010,2011 Google, Inc.
+ * Copyright (C) 2011 NVIDIA CORPORATION. All Rights Reserved.
  *
  * Author:
  *     Colin Cross <[email protected]>
  *     Erik Gilling <[email protected]>
+ *     Doug Anderson <[email protected]>
+ *     Stephen Warren <[email protected]>
+ *
+ * Portions based on mach-omap2's debug-macro.S
+ * Copyright (C) 1994-1999 Russell King
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -18,18 +24,77 @@
  *
  */
 
+#include <linux/serial_reg.h>
+
 #include <mach/io.h>
 #include <mach/iomap.h>
 
-       .macro  addruart, rp, rv, tmp
-        ldr     \rp, =IO_APB_PHYS       @ physical
-        ldr     \rv, =IO_APB_VIRT        @ virtual
-       orr     \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
-       orr     \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
-       orr     \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF)
-       orr     \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
-       .endm
+               .macro  addruart, rp, rv, tmp
+               adr     \rp, 99f                @ actual addr of 99f
+               ldr     \rv, [\rp]              @ linked addr is stored there
+               sub     \rv, \rv, \rp           @ offset between the two
+               ldr     \rp, [\rp, #4]          @ linked tegra_uart_config
+               sub     \tmp, \rp, \rv          @ actual tegra_uart_config
+               ldr     \rp, [\tmp]             @ Load tegra_uart_config
+               cmp     \rp, #1                 @ needs intitialization?
+               bne     100f                    @ no; go load the addresses
+               mov     \rv, #0                 @ yes; record init is done
+               str     \rv, [\tmp]
+               mov     \rp, #TEGRA_IRAM_BASE   @ See if cookie is in IRAM
+               ldr     \rv, [\rp, #0x100]
+               movw    \rp, #0x5254            @ "UART"
+               movt    \rp, #0x5541
+               cmp     \rv, \rp                @ Cookie present?
+               bne     100f                    @ No, use default UART
+               mov     \rp, #TEGRA_IRAM_BASE   @ Load UART address from IRAM
+               ldr     \rv, [\rp, #0x104]
+               str     \rv, [\tmp, #4]         @ Store in tegra_uart_phys
+               sub     \rv, \rv, #IO_APB_PHYS  @ Calculate virt address
+               add     \rv, \rv, #IO_APB_VIRT
+               str     \rv, [\tmp, #8]         @ Store in tegra_uart_virt
+               b       100f
+
+               .align
+99:            .word   .
+               .word   tegra_uart_config
+               .ltorg
+
+100:           ldr     \rp, [\tmp, #4]         @ Load tegra_uart_phys
+               ldr     \rv, [\tmp, #8]         @ Load tegra_uart_virt
+               .endm
+
+#define UART_SHIFT 2
+
+/*
+ * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
+ * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case.
+ * We use the fact that all 5 valid UART addresses all have something in the
+ * 2nd-to-lowest byte.
+ */
+
+               .macro  senduart, rd, rx
+               tst     \rx, #0x0000ff00
+               strneb  \rd, [\rx, #UART_TX << UART_SHIFT]
+1001:
+               .endm
 
-#define UART_SHIFT     2
-#include <asm/hardware/debug-8250.S>
+               .macro  busyuart, rd, rx
+               tst     \rx, #0x0000ff00
+               beq     1002f
+1001:          ldrb    \rd, [\rx, #UART_LSR << UART_SHIFT]
+               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               bne     1001b
+1002:
+               .endm
 
+               .macro  waituart, rd, rx
+#ifdef FLOW_CONTROL
+               tst     \rx, #0x0000ff00
+               beq     1002f
+1001:          ldrb    \rd, [\rx, #UART_MSR << UART_SHIFT]
+               tst     \rd, #UART_MSR_CTS
+               beq     1001b
+1002:
+#endif
+               .endm
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h 
b/arch/arm/mach-tegra/include/mach/uncompress.h
index 4d8e1b7..6bcb2bd 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -48,6 +48,17 @@ static inline void flush(void)
 {
 }
 
+static inline void save_uart_address(void)
+{
+       u32 *iram = (u32 *)(TEGRA_IRAM_BASE + 0x100);
+
+       if (uart) {
+               iram[0] = 0x55415254; /* "UART" */
+               iram[1] = (u32)uart;
+       } else
+               iram[0] = 0;
+}
+
 /*
  * Setup before decompression.  This is where we do UART selection for
  * earlyprintk and init the uart_base register.
@@ -124,6 +135,7 @@ static inline void arch_decomp_setup(void)
        }
        if (i == ARRAY_SIZE(uarts))
                uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
+       save_uart_address();
        if (uart == NULL)
                return;
 
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to