diff options
| author | Olof Johansson <olof@lixom.net> | 2012-05-10 02:53:05 -0400 |
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2012-05-10 02:53:05 -0400 |
| commit | af568679f51de779d0e9ad7d8360dc7727da546d (patch) | |
| tree | 3586a737ed6c1dec360150ce598e1f6216a107a0 | |
| parent | 7a3252f8374749ae4b5cc60e02f9b9eba79311cc (diff) | |
| parent | 80881dae52d05d3d6c920624157d68006390f01e (diff) | |
Merge branch 'for-3.5/debug' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/drivers
By Stephen Warren
via Stephen Warren
* 'for-3.5/debug' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra:
ARM: tegra: uncompress.h: Implement TEGRA_DEBUG_UART_AUTO_ODMDATA
| -rw-r--r-- | arch/arm/mach-tegra/Kconfig | 29 | ||||
| -rw-r--r-- | arch/arm/mach-tegra/include/mach/uncompress.h | 176 |
2 files changed, 153 insertions, 52 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index d0f2546706ca..204d3d4d7388 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig | |||
| @@ -111,7 +111,7 @@ config MACH_VENTANA | |||
| 111 | Support for the nVidia Ventana development platform | 111 | Support for the nVidia Ventana development platform |
| 112 | 112 | ||
| 113 | choice | 113 | choice |
| 114 | prompt "Low-level debug console UART" | 114 | prompt "Default low-level debug console UART" |
| 115 | default TEGRA_DEBUG_UART_NONE | 115 | default TEGRA_DEBUG_UART_NONE |
| 116 | 116 | ||
| 117 | config TEGRA_DEBUG_UART_NONE | 117 | config TEGRA_DEBUG_UART_NONE |
| @@ -134,6 +134,33 @@ config TEGRA_DEBUG_UARTE | |||
| 134 | 134 | ||
| 135 | endchoice | 135 | endchoice |
| 136 | 136 | ||
| 137 | choice | ||
| 138 | prompt "Automatic low-level debug console UART" | ||
| 139 | default TEGRA_DEBUG_UART_AUTO_NONE | ||
| 140 | |||
| 141 | config TEGRA_DEBUG_UART_AUTO_NONE | ||
| 142 | bool "None" | ||
| 143 | |||
| 144 | config TEGRA_DEBUG_UART_AUTO_ODMDATA | ||
| 145 | bool "Via ODMDATA" | ||
| 146 | help | ||
| 147 | Automatically determines which UART to use for low-level debug based | ||
| 148 | on the ODMDATA value. This value is part of the BCT, and is written | ||
| 149 | to the boot memory device using nvflash, or other flashing tool. | ||
| 150 | When bits 19:18 are 3, then bits 17:15 indicate which UART to use; | ||
| 151 | 0/1/2/3/4 are UART A/B/C/D/E. | ||
| 152 | |||
| 153 | config TEGRA_DEBUG_UART_AUTO_SCRATCH | ||
| 154 | bool "Via UART scratch register" | ||
| 155 | help | ||
| 156 | Automatically determines which UART to use for low-level debug based | ||
| 157 | on the UART scratch register value. Some bootloaders put ASCII 'D' | ||
| 158 | in this register when they initialize their own console UART output. | ||
| 159 | Using this option allows the kernel to automatically pick the same | ||
| 160 | UART. | ||
| 161 | |||
| 162 | endchoice | ||
| 163 | |||
| 137 | config TEGRA_SYSTEM_DMA | 164 | config TEGRA_SYSTEM_DMA |
| 138 | bool "Enable system DMA driver for NVIDIA Tegra SoCs" | 165 | bool "Enable system DMA driver for NVIDIA Tegra SoCs" |
| 139 | default y | 166 | default y |
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 5a440f315e57..937c4c50219e 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h | |||
| @@ -63,52 +63,86 @@ static inline void save_uart_address(void) | |||
| 63 | buf[0] = 0; | 63 | buf[0] = 0; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | /* | 66 | static const struct { |
| 67 | * Setup before decompression. This is where we do UART selection for | 67 | u32 base; |
| 68 | * earlyprintk and init the uart_base register. | 68 | u32 reset_reg; |
| 69 | */ | 69 | u32 clock_reg; |
| 70 | static inline void arch_decomp_setup(void) | 70 | u32 bit; |
| 71 | } uarts[] = { | ||
| 72 | { | ||
| 73 | TEGRA_UARTA_BASE, | ||
| 74 | TEGRA_CLK_RESET_BASE + 0x04, | ||
| 75 | TEGRA_CLK_RESET_BASE + 0x10, | ||
| 76 | 6, | ||
| 77 | }, | ||
| 78 | { | ||
| 79 | TEGRA_UARTB_BASE, | ||
| 80 | TEGRA_CLK_RESET_BASE + 0x04, | ||
| 81 | TEGRA_CLK_RESET_BASE + 0x10, | ||
| 82 | 7, | ||
| 83 | }, | ||
| 84 | { | ||
| 85 | TEGRA_UARTC_BASE, | ||
| 86 | TEGRA_CLK_RESET_BASE + 0x08, | ||
| 87 | TEGRA_CLK_RESET_BASE + 0x14, | ||
| 88 | 23, | ||
| 89 | }, | ||
| 90 | { | ||
| 91 | TEGRA_UARTD_BASE, | ||
| 92 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
| 93 | TEGRA_CLK_RESET_BASE + 0x18, | ||
| 94 | 1, | ||
| 95 | }, | ||
| 96 | { | ||
| 97 | TEGRA_UARTE_BASE, | ||
| 98 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
| 99 | TEGRA_CLK_RESET_BASE + 0x18, | ||
| 100 | 2, | ||
| 101 | }, | ||
| 102 | }; | ||
| 103 | |||
| 104 | static inline bool uart_clocked(int i) | ||
| 105 | { | ||
| 106 | if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit)) | ||
| 107 | return false; | ||
| 108 | |||
| 109 | if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit))) | ||
| 110 | return false; | ||
| 111 | |||
| 112 | return true; | ||
| 113 | } | ||
| 114 | |||
| 115 | #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA | ||
| 116 | int auto_odmdata(void) | ||
| 117 | { | ||
| 118 | volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE; | ||
| 119 | u32 odmdata = pmc[0xa0 / 4]; | ||
| 120 | |||
| 121 | /* | ||
| 122 | * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART | ||
| 123 | * Some boards apparently swap the last two values, but we don't have | ||
| 124 | * any way of catering for that here, so we just accept either. If this | ||
| 125 | * doesn't make sense for your board, just don't enable this feature. | ||
| 126 | * | ||
| 127 | * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E. | ||
| 128 | */ | ||
| 129 | |||
| 130 | switch ((odmdata >> 18) & 3) { | ||
| 131 | case 2: | ||
| 132 | case 3: | ||
| 133 | break; | ||
| 134 | default: | ||
| 135 | return -1; | ||
| 136 | } | ||
| 137 | |||
| 138 | return (odmdata >> 15) & 7; | ||
| 139 | } | ||
| 140 | #endif | ||
| 141 | |||
| 142 | #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH | ||
| 143 | int auto_scratch(void) | ||
| 71 | { | 144 | { |
| 72 | static const struct { | ||
| 73 | u32 base; | ||
| 74 | u32 reset_reg; | ||
| 75 | u32 clock_reg; | ||
| 76 | u32 bit; | ||
| 77 | } uarts[] = { | ||
| 78 | { | ||
| 79 | TEGRA_UARTA_BASE, | ||
| 80 | TEGRA_CLK_RESET_BASE + 0x04, | ||
| 81 | TEGRA_CLK_RESET_BASE + 0x10, | ||
| 82 | 6, | ||
| 83 | }, | ||
| 84 | { | ||
| 85 | TEGRA_UARTB_BASE, | ||
| 86 | TEGRA_CLK_RESET_BASE + 0x04, | ||
| 87 | TEGRA_CLK_RESET_BASE + 0x10, | ||
| 88 | 7, | ||
| 89 | }, | ||
| 90 | { | ||
| 91 | TEGRA_UARTC_BASE, | ||
| 92 | TEGRA_CLK_RESET_BASE + 0x08, | ||
| 93 | TEGRA_CLK_RESET_BASE + 0x14, | ||
| 94 | 23, | ||
| 95 | }, | ||
| 96 | { | ||
| 97 | TEGRA_UARTD_BASE, | ||
| 98 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
| 99 | TEGRA_CLK_RESET_BASE + 0x18, | ||
| 100 | 1, | ||
| 101 | }, | ||
| 102 | { | ||
| 103 | TEGRA_UARTE_BASE, | ||
| 104 | TEGRA_CLK_RESET_BASE + 0x0c, | ||
| 105 | TEGRA_CLK_RESET_BASE + 0x18, | ||
| 106 | 2, | ||
| 107 | }, | ||
| 108 | }; | ||
| 109 | int i; | 145 | int i; |
| 110 | volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; | ||
| 111 | u32 chip, div; | ||
| 112 | 146 | ||
| 113 | /* | 147 | /* |
| 114 | * Look for the first UART that: | 148 | * Look for the first UART that: |
| @@ -125,20 +159,60 @@ static inline void arch_decomp_setup(void) | |||
| 125 | * back to what's specified in TEGRA_DEBUG_UART_BASE. | 159 | * back to what's specified in TEGRA_DEBUG_UART_BASE. |
| 126 | */ | 160 | */ |
| 127 | for (i = 0; i < ARRAY_SIZE(uarts); i++) { | 161 | for (i = 0; i < ARRAY_SIZE(uarts); i++) { |
| 128 | if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit)) | 162 | if (!uart_clocked(i)) |
| 129 | continue; | ||
| 130 | |||
| 131 | if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit))) | ||
| 132 | continue; | 163 | continue; |
| 133 | 164 | ||
| 134 | uart = (volatile u8 *)uarts[i].base; | 165 | uart = (volatile u8 *)uarts[i].base; |
| 135 | if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D') | 166 | if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D') |
| 136 | continue; | 167 | continue; |
| 137 | 168 | ||
| 138 | break; | 169 | return i; |
| 139 | } | 170 | } |
| 140 | if (i == ARRAY_SIZE(uarts)) | 171 | |
| 141 | uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; | 172 | return -1; |
| 173 | } | ||
| 174 | #endif | ||
| 175 | |||
| 176 | /* | ||
| 177 | * Setup before decompression. This is where we do UART selection for | ||
| 178 | * earlyprintk and init the uart_base register. | ||
| 179 | */ | ||
| 180 | static inline void arch_decomp_setup(void) | ||
| 181 | { | ||
| 182 | int uart_id, auto_uart_id; | ||
| 183 | volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; | ||
| 184 | u32 chip, div; | ||
| 185 | |||
| 186 | #if defined(CONFIG_TEGRA_DEBUG_UARTA) | ||
| 187 | uart_id = 0; | ||
| 188 | #elif defined(CONFIG_TEGRA_DEBUG_UARTB) | ||
| 189 | uart_id = 1; | ||
| 190 | #elif defined(CONFIG_TEGRA_DEBUG_UARTC) | ||
| 191 | uart_id = 2; | ||
| 192 | #elif defined(CONFIG_TEGRA_DEBUG_UARTD) | ||
| 193 | uart_id = 3; | ||
| 194 | #elif defined(CONFIG_TEGRA_DEBUG_UARTE) | ||
| 195 | uart_id = 4; | ||
| 196 | #else | ||
| 197 | uart_id = -1; | ||
| 198 | #endif | ||
| 199 | |||
| 200 | #if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA) | ||
| 201 | auto_uart_id = auto_odmdata(); | ||
| 202 | #elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH) | ||
| 203 | auto_uart_id = auto_scratch(); | ||
| 204 | #else | ||
| 205 | auto_uart_id = -1; | ||
| 206 | #endif | ||
| 207 | if (auto_uart_id != -1) | ||
| 208 | uart_id = auto_uart_id; | ||
| 209 | |||
| 210 | if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) || | ||
| 211 | !uart_clocked(uart_id)) | ||
| 212 | uart = NULL; | ||
| 213 | else | ||
| 214 | uart = (volatile u8 *)uarts[uart_id].base; | ||
| 215 | |||
| 142 | save_uart_address(); | 216 | save_uart_address(); |
| 143 | if (uart == NULL) | 217 | if (uart == NULL) |
| 144 | return; | 218 | return; |
