diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-10-01 17:33:20 -0400 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2012-11-16 14:22:17 -0500 |
commit | 1a6d3da8bc45502940efb19604d4c94c470ef6be (patch) | |
tree | b0fcdf1c6950019c2eabed1ebd0f8513127418c8 | |
parent | adc18315889b3e67a4a2a9717fbbfab5cd2d7b57 (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>
-rw-r--r-- | arch/arm/mach-tegra/common.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/debug-macro.S | 151 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/uncompress.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-tegra/irammap.h | 9 |
4 files changed, 134 insertions, 43 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 8b41e4c0d53f..bce8591cb72b 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 | */ |
47 | u32 tegra_uart_config[3] = { | 47 | u32 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 44ca7b1d8b8a..d4c23d60d448 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 | 81 | 10: 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 | ||
89 | 11: 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 */ | ||
106 | 20: 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 */ | ||
112 | 21: 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 */ | ||
118 | 22: 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 */ | ||
124 | 23: 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 */ | ||
130 | 24: | ||
131 | checkuart(\rp, \rv, U, 2, E) | ||
132 | #endif | ||
133 | |||
134 | /* No valid UART found */ | ||
135 | 90: mov \rp, #0 | ||
136 | /* fall through */ | ||
137 | |||
138 | /* Record whichever UART we chose */ | ||
139 | 91: 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 | ||
144 | 92: 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 */ | ||
62 | 100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys | 177 | 100: 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] |
78 | 1001: | 189 | 1001: |
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 |
84 | 1001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT] | 195 | 1001: 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 |
95 | 1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT] | 206 | 1001: 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 4150c71c006f..485003f9b636 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 | ||
55 | static 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 | |||
66 | static const struct { | 54 | static 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 0cbe63261854..501952a84344 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 |