Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2010,2011 Google, Inc. * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved. * * Author: * Colin Cross <ccross@google.com> * Erik Gilling <konkers@google.com> * Doug Anderson <dianders@chromium.org> * Stephen Warren <swarren@nvidia.com> * * Portions based on mach-omap2's debug-macro.S * Copyright (C) 1994-1999 Russell King */ #include <linux/serial_reg.h> #define UART_SHIFT 2 /* Physical addresses */ #define TEGRA_CLK_RESET_BASE 0x60006000 #define TEGRA_APB_MISC_BASE 0x70000000 #define TEGRA_UARTA_BASE 0x70006000 #define TEGRA_UARTB_BASE 0x70006040 #define TEGRA_UARTC_BASE 0x70006200 #define TEGRA_UARTD_BASE 0x70006300 #define TEGRA_UARTE_BASE 0x70006400 #define TEGRA_PMC_BASE 0x7000e400 #define TEGRA_CLK_RST_DEVICES_L (TEGRA_CLK_RESET_BASE + 0x04) #define TEGRA_CLK_RST_DEVICES_H (TEGRA_CLK_RESET_BASE + 0x08) #define TEGRA_CLK_RST_DEVICES_U (TEGRA_CLK_RESET_BASE + 0x0c) #define TEGRA_CLK_OUT_ENB_L (TEGRA_CLK_RESET_BASE + 0x10) #define TEGRA_CLK_OUT_ENB_H (TEGRA_CLK_RESET_BASE + 0x14) #define TEGRA_CLK_OUT_ENB_U (TEGRA_CLK_RESET_BASE + 0x18) #define TEGRA_PMC_SCRATCH20 (TEGRA_PMC_BASE + 0xa0) #define TEGRA_APB_MISC_GP_HIDREV (TEGRA_APB_MISC_BASE + 0x804) /* * Must be section-aligned since a section mapping is used early on. * Must not overlap with regions in mach-tegra/io.c:tegra_io_desc[]. */ #define UART_VIRTUAL_BASE 0xfe800000 #define checkuart(rp, rv, lhu, bit, uart) \ /* Load address of CLK_RST register */ \ ldr rp, =TEGRA_CLK_RST_DEVICES_##lhu ; \ /* Load value from CLK_RST register */ \ ldr rp, [rp, #0] ; \ /* Test UART's reset bit */ \ tst rp, #(1 << bit) ; \ /* If set, can't use UART; jump to save no UART */ \ bne 90f ; \ /* Load address of CLK_OUT_ENB register */ \ ldr rp, =TEGRA_CLK_OUT_ENB_##lhu ; \ /* Load value from CLK_OUT_ENB register */ \ ldr rp, [rp, #0] ; \ /* Test UART's clock enable bit */ \ tst rp, #(1 << bit) ; \ /* If clear, can't use UART; jump to save no UART */ \ beq 90f ; \ /* Passed all tests, load address of UART registers */ \ ldr rp, =TEGRA_UART##uart##_BASE ; \ /* Jump to save UART address */ \ b 91f .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 initialization? bne 100f @ no; go load the addresses mov \rv, #0 @ yes; record init is done str \rv, [\tmp] #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA /* Check ODMDATA */ 10: ldr \rp, =TEGRA_PMC_SCRATCH20 ldr \rp, [\rp, #0] @ Load PMC_SCRATCH20 lsr \rv, \rp, #18 @ 19:18 are console type and \rv, \rv, #3 cmp \rv, #2 @ 2 and 3 mean DCC, UART beq 11f @ some boards swap the meaning cmp \rv, #3 @ so accept either bne 90f 11: lsr \rv, \rp, #15 @ 17:15 are UART ID and \rv, #7 cmp \rv, #0 @ UART 0? beq 20f cmp \rv, #1 @ UART 1? beq 21f cmp \rv, #2 @ UART 2? beq 22f cmp \rv, #3 @ UART 3? beq 23f cmp \rv, #4 @ UART 4? beq 24f b 90f @ invalid #endif #if defined(CONFIG_TEGRA_DEBUG_UARTA) || \ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) /* Check UART A validity */ 20: checkuart(\rp, \rv, L, 6, A) #endif #if defined(CONFIG_TEGRA_DEBUG_UARTB) || \ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) /* Check UART B validity */ 21: checkuart(\rp, \rv, L, 7, B) #endif #if defined(CONFIG_TEGRA_DEBUG_UARTC) || \ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) /* Check UART C validity */ 22: checkuart(\rp, \rv, H, 23, C) #endif #if defined(CONFIG_TEGRA_DEBUG_UARTD) || \ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) /* Check UART D validity */ 23: checkuart(\rp, \rv, U, 1, D) #endif #if defined(CONFIG_TEGRA_DEBUG_UARTE) || \ defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) /* Check UART E validity */ 24: checkuart(\rp, \rv, U, 2, E) #endif /* No valid UART found */ 90: mov \rp, #0 /* fall through */ /* Record whichever UART we chose */ 91: str \rp, [\tmp, #4] @ Store in tegra_uart_phys cmp \rp, #0 @ Valid UART address? bne 92f @ Yes, go process it str \rp, [\tmp, #8] @ Store 0 in tegra_uart_virt b 100f @ Done 92: and \rv, \rp, #0xffffff @ offset within 1MB section add \rv, \rv, #UART_VIRTUAL_BASE str \rv, [\tmp, #8] @ Store in tegra_uart_virt b 100f .align 99: .word . #if defined(ZIMAGE) .word . + 4 /* * Storage for the state maintained by the macro. * * In the kernel proper, this data is located in arch/arm/mach-tegra/tegra.c. * That's because this header is included from multiple files, and we only * want a single copy of the data. In particular, the UART probing code above * assumes it's running using physical addresses. This is true when this file * is included from head.o, but not when included from debug.o. So we need * to share the probe results between the two copies, rather than having * to re-run the probing again later. * * In the decompressor, we put the storage right here, since common.c * isn't included in the decompressor build. This storage data gets put in * .text even though it's really data, since .data is discarded from the * decompressor. Luckily, .text is writeable in the decompressor, unless * CONFIG_ZBOOT_ROM. That dependency is handled in arch/arm/Kconfig.debug. */ /* Debug UART initialization required */ .word 1 /* Debug UART physical address */ .word 0 /* Debug UART virtual address */ .word 0 #else .word tegra_uart_config #endif .ltorg /* Load previously selected UART address */ 100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys ldr \rv, [\tmp, #8] @ Load tegra_uart_virt .endm /* * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra * check to make sure that the UART address is actually valid. */ .macro senduart, rd, rx cmp \rx, #0 strbne \rd, [\rx, #UART_TX << UART_SHIFT] 1001: .endm .macro busyuart, rd, rx cmp \rx, #0 beq 1002f 1001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT] and \rd, \rd, #UART_LSR_THRE teq \rd, #UART_LSR_THRE bne 1001b 1002: .endm .macro waituartcts, rd, rx cmp \rx, #0 beq 1002f 1001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT] tst \rd, #UART_MSR_CTS beq 1001b 1002: .endm .macro waituarttxrdy,rd,rx .endm |