aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-10-01 17:33:20 -0400
committerStephen Warren <swarren@nvidia.com>2012-11-16 14:22:17 -0500
commit1a6d3da8bc45502940efb19604d4c94c470ef6be (patch)
treeb0fcdf1c6950019c2eabed1ebd0f8513127418c8 /arch/arm/mach-tegra
parentadc18315889b3e67a4a2a9717fbbfab5cd2d7b57 (diff)
ARM: tegra: decouple uncompress.h and debug-macro.S
Prior to this change, Tegra's debug-macro.S relied on uncompress.h having determined which UART to use, and whether it was safe to use the UART (i.e. is it not in reset, and is clocked). This determination was communicated from uncompress.h to debug-macro.S using a few bytes of Tegra's IRAM (an on-SoC RAM). This had the disadvantage that uncompress.h was a required part of the kernel boot process; booting a non-compressed kernel would not allow earlyprintk to operate. This change duplicates the UART selection and validation logic into debug-macro.S so that the reliance on uncompress.h is removed. This also helps out with single-zImage work, since there is currently no support for using any uncompress.h with single-zImage. Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/common.c4
-rw-r--r--arch/arm/mach-tegra/include/mach/debug-macro.S151
-rw-r--r--arch/arm/mach-tegra/include/mach/uncompress.h13
-rw-r--r--arch/arm/mach-tegra/irammap.h9
4 files changed, 134 insertions, 43 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 8b41e4c0d53..bce8591cb72 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -44,13 +44,15 @@
44 * kernel is loaded. The data is declared here rather than debug-macro.S so 44 * kernel is loaded. The data is declared here rather than debug-macro.S so
45 * that multiple inclusions of debug-macro.S point at the same data. 45 * that multiple inclusions of debug-macro.S point at the same data.
46 */ 46 */
47u32 tegra_uart_config[3] = { 47u32 tegra_uart_config[4] = {
48 /* Debug UART initialization required */ 48 /* Debug UART initialization required */
49 1, 49 1,
50 /* Debug UART physical address */ 50 /* Debug UART physical address */
51 0, 51 0,
52 /* Debug UART virtual address */ 52 /* Debug UART virtual address */
53 0, 53 0,
54 /* Scratch space for debug macro */
55 0,
54}; 56};
55 57
56#ifdef CONFIG_OF 58#ifdef CONFIG_OF
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
index 44ca7b1d8b8..d4c23d60d44 100644
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -27,7 +27,42 @@
27#include <linux/serial_reg.h> 27#include <linux/serial_reg.h>
28 28
29#include "../../iomap.h" 29#include "../../iomap.h"
30#include "../../irammap.h" 30
31#define UART_SHIFT 2
32
33#define TEGRA_CLK_RST_DEVICES_L (TEGRA_CLK_RESET_BASE + 0x04)
34#define TEGRA_CLK_RST_DEVICES_H (TEGRA_CLK_RESET_BASE + 0x08)
35#define TEGRA_CLK_RST_DEVICES_U (TEGRA_CLK_RESET_BASE + 0x0c)
36#define TEGRA_CLK_OUT_ENB_L (TEGRA_CLK_RESET_BASE + 0x10)
37#define TEGRA_CLK_OUT_ENB_H (TEGRA_CLK_RESET_BASE + 0x14)
38#define TEGRA_CLK_OUT_ENB_U (TEGRA_CLK_RESET_BASE + 0x18)
39#define TEGRA_PMC_SCRATCH20 (TEGRA_PMC_BASE + 0xa0)
40#define TEGRA_APB_MISC_GP_HIDREV (TEGRA_APB_MISC_BASE + 0x804)
41
42#define checkuart(rp, rv, lhu, bit, uart) \
43 /* Load address of CLK_RST register */ \
44 movw rp, #TEGRA_CLK_RST_DEVICES_##lhu & 0xffff ; \
45 movt rp, #TEGRA_CLK_RST_DEVICES_##lhu >> 16 ; \
46 /* Load value from CLK_RST register */ \
47 ldr rp, [rp, #0] ; \
48 /* Test UART's reset bit */ \
49 tst rp, #(1 << bit) ; \
50 /* If set, can't use UART; jump to save no UART */ \
51 bne 90f ; \
52 /* Load address of CLK_OUT_ENB register */ \
53 movw rp, #TEGRA_CLK_OUT_ENB_##lhu & 0xffff ; \
54 movt rp, #TEGRA_CLK_OUT_ENB_##lhu >> 16 ; \
55 /* Load value from CLK_OUT_ENB register */ \
56 ldr rp, [rp, #0] ; \
57 /* Test UART's clock enable bit */ \
58 tst rp, #(1 << bit) ; \
59 /* If clear, can't use UART; jump to save no UART */ \
60 beq 90f ; \
61 /* Passed all tests, load address of UART registers */ \
62 movw rp, #TEGRA_UART##uart##_BASE & 0xffff ; \
63 movt rp, #TEGRA_UART##uart##_BASE >> 16 ; \
64 /* Jump to save UART address */ \
65 b 91f
31 66
32 .macro addruart, rp, rv, tmp 67 .macro addruart, rp, rv, tmp
33 adr \rp, 99f @ actual addr of 99f 68 adr \rp, 99f @ actual addr of 99f
@@ -36,22 +71,101 @@
36 ldr \rp, [\rp, #4] @ linked tegra_uart_config 71 ldr \rp, [\rp, #4] @ linked tegra_uart_config
37 sub \tmp, \rp, \rv @ actual tegra_uart_config 72 sub \tmp, \rp, \rv @ actual tegra_uart_config
38 ldr \rp, [\tmp] @ Load tegra_uart_config 73 ldr \rp, [\tmp] @ Load tegra_uart_config
39 cmp \rp, #1 @ needs intitialization? 74 cmp \rp, #1 @ needs initialization?
40 bne 100f @ no; go load the addresses 75 bne 100f @ no; go load the addresses
41 mov \rv, #0 @ yes; record init is done 76 mov \rv, #0 @ yes; record init is done
42 str \rv, [\tmp] 77 str \rv, [\tmp]
43 mov \rp, #TEGRA_IRAM_BASE @ See if cookie is in IRAM 78
44 ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET] 79#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
45 movw \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff 80 /* Check ODMDATA */
46 movt \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16 8110: movw \rp, #TEGRA_PMC_SCRATCH20 & 0xffff
47 cmp \rv, \rp @ Cookie present? 82 movt \rp, #TEGRA_PMC_SCRATCH20 >> 16
48 bne 100f @ No, use default UART 83 ldr \rp, [\rp, #0] @ Load PMC_SCRATCH20
49 mov \rp, #TEGRA_IRAM_BASE @ Load UART address from IRAM 84 ubfx \rv, \rp, #18, #2 @ 19:18 are console type
50 ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4] 85 cmp \rv, #2 @ 2 and 3 mean DCC, UART
51 str \rv, [\tmp, #4] @ Store in tegra_uart_phys 86 beq 11f @ some boards swap the meaning
52 sub \rv, \rv, #IO_APB_PHYS @ Calculate virt address 87 cmp \rv, #3 @ so accept either
88 bne 90f
8911: ubfx \rv, \rp, #15, #3 @ 17:15 are UART ID
90 cmp \rv, #0 @ UART 0?
91 beq 20f
92 cmp \rv, #1 @ UART 1?
93 beq 21f
94 cmp \rv, #2 @ UART 2?
95 beq 22f
96 cmp \rv, #3 @ UART 3?
97 beq 23f
98 cmp \rv, #4 @ UART 4?
99 beq 24f
100 b 90f @ invalid
101#endif
102
103#if defined(CONFIG_TEGRA_DEBUG_UARTA) || \
104 defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
105 /* Check UART A validity */
10620: checkuart(\rp, \rv, L, 6, A)
107#endif
108
109#if defined(CONFIG_TEGRA_DEBUG_UARTB) || \
110 defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
111 /* Check UART B validity */
11221: checkuart(\rp, \rv, L, 7, B)
113#endif
114
115#if defined(CONFIG_TEGRA_DEBUG_UARTC) || \
116 defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
117 /* Check UART C validity */
11822: checkuart(\rp, \rv, H, 23, C)
119#endif
120
121#if defined(CONFIG_TEGRA_DEBUG_UARTD) || \
122 defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
123 /* Check UART D validity */
12423: checkuart(\rp, \rv, U, 1, D)
125#endif
126
127#if defined(CONFIG_TEGRA_DEBUG_UARTE) || \
128 defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
129 /* Check UART E validity */
13024:
131 checkuart(\rp, \rv, U, 2, E)
132#endif
133
134 /* No valid UART found */
13590: mov \rp, #0
136 /* fall through */
137
138 /* Record whichever UART we chose */
13991: str \rp, [\tmp, #4] @ Store in tegra_uart_phys
140 cmp \rp, #0 @ Valid UART address?
141 bne 92f @ Yes, go process it
142 str \rp, [\tmp, #8] @ Store 0 in tegra_uart_phys
143 b 100f @ Done
14492: sub \rv, \rp, #IO_APB_PHYS @ Calculate virt address
53 add \rv, \rv, #IO_APB_VIRT 145 add \rv, \rv, #IO_APB_VIRT
54 str \rv, [\tmp, #8] @ Store in tegra_uart_virt 146 str \rv, [\tmp, #8] @ Store in tegra_uart_virt
147 movw \rv, #TEGRA_APB_MISC_GP_HIDREV & 0xffff
148 movt \rv, #TEGRA_APB_MISC_GP_HIDREV >> 16
149 ldr \rv, [\rv, #0] @ Load HIDREV
150 ubfx \rv, \rv, #8, #8 @ 15:8 are SoC version
151 cmp \rv, #0x20 @ Tegra20?
152 moveq \rv, #0x75 @ Tegra20 divisor
153 movne \rv, #0xdd @ Tegra30 divisor
154 str \rv, [\tmp, #12] @ Save divisor to scratch
155 /* uart[UART_LCR] = UART_LCR_WLEN8 | UART_LCR_DLAB; */
156 mov \rv, #UART_LCR_WLEN8 | UART_LCR_DLAB
157 str \rv, [\rp, #UART_LCR << UART_SHIFT]
158 /* uart[UART_DLL] = div & 0xff; */
159 ldr \rv, [\tmp, #12]
160 and \rv, \rv, #0xff
161 str \rv, [\rp, #UART_DLL << UART_SHIFT]
162 /* uart[UART_DLM] = div >> 8; */
163 ldr \rv, [\tmp, #12]
164 lsr \rv, \rv, #8
165 str \rv, [\rp, #UART_DLM << UART_SHIFT]
166 /* uart[UART_LCR] = UART_LCR_WLEN8; */
167 mov \rv, #UART_LCR_WLEN8
168 str \rv, [\rp, #UART_LCR << UART_SHIFT]
55 b 100f 169 b 100f
56 170
57 .align 171 .align
@@ -59,27 +173,24 @@
59 .word tegra_uart_config 173 .word tegra_uart_config
60 .ltorg 174 .ltorg
61 175
176 /* Load previously selected UART address */
62100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys 177100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys
63 ldr \rv, [\tmp, #8] @ Load tegra_uart_virt 178 ldr \rv, [\tmp, #8] @ Load tegra_uart_virt
64 .endm 179 .endm
65 180
66#define UART_SHIFT 2
67
68/* 181/*
69 * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra 182 * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
70 * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case. 183 * check to make sure that the UART address is actually valid.
71 * We use the fact that all 5 valid UART addresses all have something in the
72 * 2nd-to-lowest byte.
73 */ 184 */
74 185
75 .macro senduart, rd, rx 186 .macro senduart, rd, rx
76 tst \rx, #0x0000ff00 187 cmp \rx, #0
77 strneb \rd, [\rx, #UART_TX << UART_SHIFT] 188 strneb \rd, [\rx, #UART_TX << UART_SHIFT]
781001: 1891001:
79 .endm 190 .endm
80 191
81 .macro busyuart, rd, rx 192 .macro busyuart, rd, rx
82 tst \rx, #0x0000ff00 193 cmp \rx, #0
83 beq 1002f 194 beq 1002f
841001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT] 1951001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT]
85 and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE 196 and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
@@ -90,7 +201,7 @@
90 201
91 .macro waituart, rd, rx 202 .macro waituart, rd, rx
92#ifdef FLOW_CONTROL 203#ifdef FLOW_CONTROL
93 tst \rx, #0x0000ff00 204 cmp \rx, #0
94 beq 1002f 205 beq 1002f
951001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT] 2061001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT]
96 tst \rd, #UART_MSR_CTS 207 tst \rd, #UART_MSR_CTS
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
index 4150c71c006..485003f9b63 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -29,7 +29,6 @@
29#include <linux/serial_reg.h> 29#include <linux/serial_reg.h>
30 30
31#include "../../iomap.h" 31#include "../../iomap.h"
32#include "../../irammap.h"
33 32
34#define BIT(x) (1 << (x)) 33#define BIT(x) (1 << (x))
35#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 34#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -52,17 +51,6 @@ static inline void flush(void)
52{ 51{
53} 52}
54 53
55static inline void save_uart_address(void)
56{
57 u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
58
59 if (uart) {
60 buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
61 buf[1] = (u32)uart;
62 } else
63 buf[0] = 0;
64}
65
66static const struct { 54static const struct {
67 u32 base; 55 u32 base;
68 u32 reset_reg; 56 u32 reset_reg;
@@ -169,7 +157,6 @@ static inline void arch_decomp_setup(void)
169 else 157 else
170 uart = (volatile u8 *)uarts[uart_id].base; 158 uart = (volatile u8 *)uarts[uart_id].base;
171 159
172 save_uart_address();
173 if (uart == NULL) 160 if (uart == NULL)
174 return; 161 return;
175 162
diff --git a/arch/arm/mach-tegra/irammap.h b/arch/arm/mach-tegra/irammap.h
index 0cbe6326185..501952a8434 100644
--- a/arch/arm/mach-tegra/irammap.h
+++ b/arch/arm/mach-tegra/irammap.h
@@ -23,13 +23,4 @@
23#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0 23#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0
24#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K 24#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K
25 25
26/*
27 * These locations are written to by uncompress.h, and read by debug-macro.S.
28 * The first word holds the cookie value if the data is valid. The second
29 * word holds the UART physical address.
30 */
31#define TEGRA_IRAM_DEBUG_UART_OFFSET SZ_1K
32#define TEGRA_IRAM_DEBUG_UART_SIZE 8
33#define TEGRA_IRAM_DEBUG_UART_COOKIE 0x55415254
34
35#endif 26#endif