diff options
Diffstat (limited to 'arch/arm/mach-tegra/include/mach/uncompress.h')
-rw-r--r-- | arch/arm/mach-tegra/include/mach/uncompress.h | 176 |
1 files changed, 125 insertions, 51 deletions
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; |