ARM: tegra: move iomap.h to mach-tegra
[deliverable/linux.git] / arch / arm / mach-tegra / include / mach / uncompress.h
1 /*
2 * arch/arm/mach-tegra/include/mach/uncompress.h
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 2011 Google, Inc.
6 * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
7 *
8 * Author:
9 * Colin Cross <ccross@google.com>
10 * Erik Gilling <konkers@google.com>
11 * Doug Anderson <dianders@chromium.org>
12 * Stephen Warren <swarren@nvidia.com>
13 *
14 * This software is licensed under the terms of the GNU General Public
15 * License version 2, as published by the Free Software Foundation, and
16 * may be copied, distributed, and modified under those terms.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 */
24
25 #ifndef __MACH_TEGRA_UNCOMPRESS_H
26 #define __MACH_TEGRA_UNCOMPRESS_H
27
28 #include <linux/types.h>
29 #include <linux/serial_reg.h>
30
31 #include <mach/irammap.h>
32
33 #include "../../iomap.h"
34
35 #define BIT(x) (1 << (x))
36 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
37
38 #define DEBUG_UART_SHIFT 2
39
40 volatile u8 *uart;
41
42 static void putc(int c)
43 {
44 if (uart == NULL)
45 return;
46
47 while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE))
48 barrier();
49 uart[UART_TX << DEBUG_UART_SHIFT] = c;
50 }
51
52 static inline void flush(void)
53 {
54 }
55
56 static inline void save_uart_address(void)
57 {
58 u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
59
60 if (uart) {
61 buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
62 buf[1] = (u32)uart;
63 } else
64 buf[0] = 0;
65 }
66
67 static const struct {
68 u32 base;
69 u32 reset_reg;
70 u32 clock_reg;
71 u32 bit;
72 } uarts[] = {
73 {
74 TEGRA_UARTA_BASE,
75 TEGRA_CLK_RESET_BASE + 0x04,
76 TEGRA_CLK_RESET_BASE + 0x10,
77 6,
78 },
79 {
80 TEGRA_UARTB_BASE,
81 TEGRA_CLK_RESET_BASE + 0x04,
82 TEGRA_CLK_RESET_BASE + 0x10,
83 7,
84 },
85 {
86 TEGRA_UARTC_BASE,
87 TEGRA_CLK_RESET_BASE + 0x08,
88 TEGRA_CLK_RESET_BASE + 0x14,
89 23,
90 },
91 {
92 TEGRA_UARTD_BASE,
93 TEGRA_CLK_RESET_BASE + 0x0c,
94 TEGRA_CLK_RESET_BASE + 0x18,
95 1,
96 },
97 {
98 TEGRA_UARTE_BASE,
99 TEGRA_CLK_RESET_BASE + 0x0c,
100 TEGRA_CLK_RESET_BASE + 0x18,
101 2,
102 },
103 };
104
105 static inline bool uart_clocked(int i)
106 {
107 if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
108 return false;
109
110 if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
111 return false;
112
113 return true;
114 }
115
116 #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
117 int auto_odmdata(void)
118 {
119 volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE;
120 u32 odmdata = pmc[0xa0 / 4];
121
122 /*
123 * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART
124 * Some boards apparently swap the last two values, but we don't have
125 * any way of catering for that here, so we just accept either. If this
126 * doesn't make sense for your board, just don't enable this feature.
127 *
128 * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E.
129 */
130
131 switch ((odmdata >> 18) & 3) {
132 case 2:
133 case 3:
134 break;
135 default:
136 return -1;
137 }
138
139 return (odmdata >> 15) & 7;
140 }
141 #endif
142
143 #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
144 int auto_scratch(void)
145 {
146 int i;
147
148 /*
149 * Look for the first UART that:
150 * a) Is not in reset.
151 * b) Is clocked.
152 * c) Has a 'D' in the scratchpad register.
153 *
154 * Note that on Tegra30, the first two conditions are required, since
155 * if not true, accesses to the UART scratch register will hang.
156 * Tegra20 doesn't have this issue.
157 *
158 * The intent is that the bootloader will tell the kernel which UART
159 * to use by setting up those conditions. If nothing found, we'll fall
160 * back to what's specified in TEGRA_DEBUG_UART_BASE.
161 */
162 for (i = 0; i < ARRAY_SIZE(uarts); i++) {
163 if (!uart_clocked(i))
164 continue;
165
166 uart = (volatile u8 *)uarts[i].base;
167 if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
168 continue;
169
170 return i;
171 }
172
173 return -1;
174 }
175 #endif
176
177 /*
178 * Setup before decompression. This is where we do UART selection for
179 * earlyprintk and init the uart_base register.
180 */
181 static inline void arch_decomp_setup(void)
182 {
183 int uart_id, auto_uart_id;
184 volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
185 u32 chip, div;
186
187 #if defined(CONFIG_TEGRA_DEBUG_UARTA)
188 uart_id = 0;
189 #elif defined(CONFIG_TEGRA_DEBUG_UARTB)
190 uart_id = 1;
191 #elif defined(CONFIG_TEGRA_DEBUG_UARTC)
192 uart_id = 2;
193 #elif defined(CONFIG_TEGRA_DEBUG_UARTD)
194 uart_id = 3;
195 #elif defined(CONFIG_TEGRA_DEBUG_UARTE)
196 uart_id = 4;
197 #else
198 uart_id = -1;
199 #endif
200
201 #if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
202 auto_uart_id = auto_odmdata();
203 #elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
204 auto_uart_id = auto_scratch();
205 #else
206 auto_uart_id = -1;
207 #endif
208 if (auto_uart_id != -1)
209 uart_id = auto_uart_id;
210
211 if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
212 !uart_clocked(uart_id))
213 uart = NULL;
214 else
215 uart = (volatile u8 *)uarts[uart_id].base;
216
217 save_uart_address();
218 if (uart == NULL)
219 return;
220
221 chip = (apb_misc[0x804 / 4] >> 8) & 0xff;
222 if (chip == 0x20)
223 div = 0x0075;
224 else
225 div = 0x00dd;
226
227 uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB;
228 uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
229 uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
230 uart[UART_LCR << DEBUG_UART_SHIFT] = 3;
231 }
232
233 static inline void arch_decomp_wdog(void)
234 {
235 }
236
237 #endif
This page took 0.044666 seconds and 5 git commands to generate.