Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+134 -43
+3 -1
arch/arm/mach-tegra/common.c
··· 44 44 * kernel is loaded. The data is declared here rather than debug-macro.S so 45 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 48 /* Debug UART initialization required */ 49 49 1, 50 50 /* Debug UART physical address */ 51 51 0, 52 52 /* Debug UART virtual address */ 53 + 0, 54 + /* Scratch space for debug macro */ 53 55 0, 54 56 }; 55 57
+131 -20
arch/arm/mach-tegra/include/mach/debug-macro.S
··· 27 27 #include <linux/serial_reg.h> 28 28 29 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 67 .macro addruart, rp, rv, tmp 33 68 adr \rp, 99f @ actual addr of 99f ··· 71 36 ldr \rp, [\rp, #4] @ linked tegra_uart_config 72 37 sub \tmp, \rp, \rv @ actual tegra_uart_config 73 38 ldr \rp, [\tmp] @ Load tegra_uart_config 74 - cmp \rp, #1 @ needs intitialization? 39 + cmp \rp, #1 @ needs initialization? 75 40 bne 100f @ no; go load the addresses 76 41 mov \rv, #0 @ yes; record init is done 77 42 str \rv, [\tmp] 78 - mov \rp, #TEGRA_IRAM_BASE @ See if cookie is in IRAM 79 - ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET] 80 - movw \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff 81 - movt \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16 82 - cmp \rv, \rp @ Cookie present? 83 - bne 100f @ No, use default UART 84 - mov \rp, #TEGRA_IRAM_BASE @ Load UART address from IRAM 85 - ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4] 86 - str \rv, [\tmp, #4] @ Store in tegra_uart_phys 87 - sub \rv, \rv, #IO_APB_PHYS @ Calculate virt address 43 + 44 + #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA 45 + /* Check ODMDATA */ 46 + 10: movw \rp, #TEGRA_PMC_SCRATCH20 & 0xffff 47 + movt \rp, #TEGRA_PMC_SCRATCH20 >> 16 48 + ldr \rp, [\rp, #0] @ Load PMC_SCRATCH20 49 + ubfx \rv, \rp, #18, #2 @ 19:18 are console type 50 + cmp \rv, #2 @ 2 and 3 mean DCC, UART 51 + beq 11f @ some boards swap the meaning 52 + cmp \rv, #3 @ so accept either 53 + bne 90f 54 + 11: ubfx \rv, \rp, #15, #3 @ 17:15 are UART ID 55 + cmp \rv, #0 @ UART 0? 56 + beq 20f 57 + cmp \rv, #1 @ UART 1? 58 + beq 21f 59 + cmp \rv, #2 @ UART 2? 60 + beq 22f 61 + cmp \rv, #3 @ UART 3? 62 + beq 23f 63 + cmp \rv, #4 @ UART 4? 64 + beq 24f 65 + b 90f @ invalid 66 + #endif 67 + 68 + #if defined(CONFIG_TEGRA_DEBUG_UARTA) || \ 69 + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) 70 + /* Check UART A validity */ 71 + 20: checkuart(\rp, \rv, L, 6, A) 72 + #endif 73 + 74 + #if defined(CONFIG_TEGRA_DEBUG_UARTB) || \ 75 + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) 76 + /* Check UART B validity */ 77 + 21: checkuart(\rp, \rv, L, 7, B) 78 + #endif 79 + 80 + #if defined(CONFIG_TEGRA_DEBUG_UARTC) || \ 81 + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) 82 + /* Check UART C validity */ 83 + 22: checkuart(\rp, \rv, H, 23, C) 84 + #endif 85 + 86 + #if defined(CONFIG_TEGRA_DEBUG_UARTD) || \ 87 + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) 88 + /* Check UART D validity */ 89 + 23: checkuart(\rp, \rv, U, 1, D) 90 + #endif 91 + 92 + #if defined(CONFIG_TEGRA_DEBUG_UARTE) || \ 93 + defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) 94 + /* Check UART E validity */ 95 + 24: 96 + checkuart(\rp, \rv, U, 2, E) 97 + #endif 98 + 99 + /* No valid UART found */ 100 + 90: mov \rp, #0 101 + /* fall through */ 102 + 103 + /* Record whichever UART we chose */ 104 + 91: str \rp, [\tmp, #4] @ Store in tegra_uart_phys 105 + cmp \rp, #0 @ Valid UART address? 106 + bne 92f @ Yes, go process it 107 + str \rp, [\tmp, #8] @ Store 0 in tegra_uart_phys 108 + b 100f @ Done 109 + 92: sub \rv, \rp, #IO_APB_PHYS @ Calculate virt address 88 110 add \rv, \rv, #IO_APB_VIRT 89 111 str \rv, [\tmp, #8] @ Store in tegra_uart_virt 112 + movw \rv, #TEGRA_APB_MISC_GP_HIDREV & 0xffff 113 + movt \rv, #TEGRA_APB_MISC_GP_HIDREV >> 16 114 + ldr \rv, [\rv, #0] @ Load HIDREV 115 + ubfx \rv, \rv, #8, #8 @ 15:8 are SoC version 116 + cmp \rv, #0x20 @ Tegra20? 117 + moveq \rv, #0x75 @ Tegra20 divisor 118 + movne \rv, #0xdd @ Tegra30 divisor 119 + str \rv, [\tmp, #12] @ Save divisor to scratch 120 + /* uart[UART_LCR] = UART_LCR_WLEN8 | UART_LCR_DLAB; */ 121 + mov \rv, #UART_LCR_WLEN8 | UART_LCR_DLAB 122 + str \rv, [\rp, #UART_LCR << UART_SHIFT] 123 + /* uart[UART_DLL] = div & 0xff; */ 124 + ldr \rv, [\tmp, #12] 125 + and \rv, \rv, #0xff 126 + str \rv, [\rp, #UART_DLL << UART_SHIFT] 127 + /* uart[UART_DLM] = div >> 8; */ 128 + ldr \rv, [\tmp, #12] 129 + lsr \rv, \rv, #8 130 + str \rv, [\rp, #UART_DLM << UART_SHIFT] 131 + /* uart[UART_LCR] = UART_LCR_WLEN8; */ 132 + mov \rv, #UART_LCR_WLEN8 133 + str \rv, [\rp, #UART_LCR << UART_SHIFT] 90 134 b 100f 91 135 92 136 .align ··· 173 59 .word tegra_uart_config 174 60 .ltorg 175 61 62 + /* Load previously selected UART address */ 176 63 100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys 177 64 ldr \rv, [\tmp, #8] @ Load tegra_uart_virt 178 65 .endm 179 66 180 - #define UART_SHIFT 2 181 - 182 67 /* 183 68 * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra 184 - * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case. 185 - * We use the fact that all 5 valid UART addresses all have something in the 186 - * 2nd-to-lowest byte. 69 + * check to make sure that the UART address is actually valid. 187 70 */ 188 71 189 72 .macro senduart, rd, rx 190 - tst \rx, #0x0000ff00 73 + cmp \rx, #0 191 74 strneb \rd, [\rx, #UART_TX << UART_SHIFT] 192 75 1001: 193 76 .endm 194 77 195 78 .macro busyuart, rd, rx 196 - tst \rx, #0x0000ff00 79 + cmp \rx, #0 197 80 beq 1002f 198 81 1001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT] 199 82 and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE ··· 201 90 202 91 .macro waituart, rd, rx 203 92 #ifdef FLOW_CONTROL 204 - tst \rx, #0x0000ff00 93 + cmp \rx, #0 205 94 beq 1002f 206 95 1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT] 207 96 tst \rd, #UART_MSR_CTS
-13
arch/arm/mach-tegra/include/mach/uncompress.h
··· 29 29 #include <linux/serial_reg.h> 30 30 31 31 #include "../../iomap.h" 32 - #include "../../irammap.h" 33 32 34 33 #define BIT(x) (1 << (x)) 35 34 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) ··· 49 50 50 51 static inline void flush(void) 51 52 { 52 - } 53 - 54 - static inline void save_uart_address(void) 55 - { 56 - u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET); 57 - 58 - if (uart) { 59 - buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE; 60 - buf[1] = (u32)uart; 61 - } else 62 - buf[0] = 0; 63 53 } 64 54 65 55 static const struct { ··· 157 169 else 158 170 uart = (volatile u8 *)uarts[uart_id].base; 159 171 160 - save_uart_address(); 161 172 if (uart == NULL) 162 173 return; 163 174
-9
arch/arm/mach-tegra/irammap.h
··· 23 23 #define TEGRA_IRAM_RESET_HANDLER_OFFSET 0 24 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 26 #endif