6dc6bfc59b54c16c83e9e6d2410b5eb761a787fe
[linux-3.10.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  * Copyright (C) 2010-2012 NVIDIA Corporation
15  *
16  * This software is licensed under the terms of the GNU General Public
17  * License version 2, as published by the Free Software Foundation, and
18  * may be copied, distributed, and modified under those terms.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  */
26
27 #ifndef __MACH_TEGRA_UNCOMPRESS_H
28 #define __MACH_TEGRA_UNCOMPRESS_H
29
30 #include <linux/types.h>
31 #include <linux/serial_reg.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 #if defined(CONFIG_TEGRA_DEBUG_UARTA)
43 #define DEBUG_UART_CLK_SRC              (TEGRA_CLK_RESET_BASE + 0x178)
44 #define DEBUG_UART_CLK_ENB_SET_REG      (TEGRA_CLK_RESET_BASE + 0x320)
45 #define DEBUG_UART_CLK_ENB_SET_BIT      (1 << 6)
46 #define DEBUG_UART_RST_CLR_REG          (TEGRA_CLK_RESET_BASE + 0x304)
47 #define DEBUG_UART_RST_CLR_BIT          (1 << 6)
48 #elif defined(CONFIG_TEGRA_DEBUG_UARTB)
49 #define DEBUG_UART_CLK_SRC              (TEGRA_CLK_RESET_BASE + 0x17c)
50 #define DEBUG_UART_CLK_ENB_SET_REG      (TEGRA_CLK_RESET_BASE + 0x320)
51 #define DEBUG_UART_CLK_ENB_SET_BIT      (1 << 7)
52 #define DEBUG_UART_RST_CLR_REG          (TEGRA_CLK_RESET_BASE + 0x304)
53 #define DEBUG_UART_RST_CLR_BIT          (1 << 7)
54 #elif defined(CONFIG_TEGRA_DEBUG_UARTC)
55 #define DEBUG_UART_CLK_SRC              (TEGRA_CLK_RESET_BASE + 0x1a0)
56 #define DEBUG_UART_CLK_ENB_SET_REG      (TEGRA_CLK_RESET_BASE + 0x328)
57 #define DEBUG_UART_CLK_ENB_SET_BIT      (1 << 23)
58 #define DEBUG_UART_RST_CLR_REG          (TEGRA_CLK_RESET_BASE + 0x30C)
59 #define DEBUG_UART_RST_CLR_BIT          (1 << 23)
60 #elif defined(CONFIG_TEGRA_DEBUG_UARTD)
61 #define DEBUG_UART_CLK_SRC              (TEGRA_CLK_RESET_BASE + 0x1c0)
62 #define DEBUG_UART_CLK_ENB_SET_REG      (TEGRA_CLK_RESET_BASE + 0x330)
63 #define DEBUG_UART_CLK_ENB_SET_BIT      (1 << 1)
64 #define DEBUG_UART_RST_CLR_REG          (TEGRA_CLK_RESET_BASE + 0x314)
65 #define DEBUG_UART_RST_CLR_BIT          (1 << 1)
66 #elif defined(CONFIG_TEGRA_DEBUG_UARTE)
67 #define DEBUG_UART_CLK_SRC              (TEGRA_CLK_RESET_BASE + 0x1c4)
68 #define DEBUG_UART_CLK_ENB_SET_REG      (TEGRA_CLK_RESET_BASE + 0x330)
69 #define DEBUG_UART_CLK_ENB_SET_BIT      (1 << 2)
70 #define DEBUG_UART_RST_CLR_REG          (TEGRA_CLK_RESET_BASE + 0x314)
71 #define DEBUG_UART_RST_CLR_BIT          (1 << 2)
72 #else
73 #define DEBUG_UART_CLK_SRC              0
74 #define DEBUG_UART_CLK_ENB_SET_REG      0
75 #define DEBUG_UART_CLK_ENB_SET_BIT      0
76 #define DEBUG_UART_RST_CLR_REG          0
77 #define DEBUG_UART_RST_CLR_BIT          0
78 #endif
79 #define PLLP_BASE                       (TEGRA_CLK_RESET_BASE + 0x0a0)
80 #define PLLP_BASE_OVERRIDE              (1 << 28)
81 #define PLLP_BASE_DIVP_SHIFT            20
82 #define PLLP_BASE_DIVP_MASK             (0x7 << 20)
83 #define PLLP_BASE_DIVN_SHIFT            8
84 #define PLLP_BASE_DIVN_MASK             (0x3FF << 8)
85
86 #define DEBUG_UART_DLL_216              0x75
87 #define DEBUG_UART_DLL_408              0xdd
88 #define DEBUG_UART_DLL_204              0x6f
89
90 static void putc(int c)
91 {
92         if (uart == NULL)
93                 return;
94
95         while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE))
96                 barrier();
97         uart[UART_TX << DEBUG_UART_SHIFT] = c;
98 }
99
100 static inline void flush(void)
101 {
102 }
103
104 static const struct {
105         u32 base;
106         u32 reset_reg;
107         u32 clock_reg;
108         u32 bit;
109 } uarts[] = {
110         {
111                 TEGRA_UARTA_BASE,
112                 TEGRA_CLK_RESET_BASE + 0x04,
113                 TEGRA_CLK_RESET_BASE + 0x10,
114                 6,
115         },
116         {
117                 TEGRA_UARTB_BASE,
118                 TEGRA_CLK_RESET_BASE + 0x04,
119                 TEGRA_CLK_RESET_BASE + 0x10,
120                 7,
121         },
122         {
123                 TEGRA_UARTC_BASE,
124                 TEGRA_CLK_RESET_BASE + 0x08,
125                 TEGRA_CLK_RESET_BASE + 0x14,
126                 23,
127         },
128         {
129                 TEGRA_UARTD_BASE,
130                 TEGRA_CLK_RESET_BASE + 0x0c,
131                 TEGRA_CLK_RESET_BASE + 0x18,
132                 1,
133         },
134         {
135                 TEGRA_UARTE_BASE,
136                 TEGRA_CLK_RESET_BASE + 0x0c,
137                 TEGRA_CLK_RESET_BASE + 0x18,
138                 2,
139         },
140 };
141
142 static inline bool uart_clocked(int i)
143 {
144         if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
145                 return false;
146
147         if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
148                 return false;
149
150         return true;
151 }
152
153 #ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
154 int auto_odmdata(void)
155 {
156         volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE;
157         u32 odmdata = pmc[0xa0 / 4];
158
159         /*
160          * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART
161          * Some boards apparently swap the last two values, but we don't have
162          * any way of catering for that here, so we just accept either. If this
163          * doesn't make sense for your board, just don't enable this feature.
164          *
165          * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E.
166          */
167
168         switch  ((odmdata >> 18) & 3) {
169         case 2:
170         case 3:
171                 break;
172         default:
173                 return -1;
174         }
175
176         return (odmdata >> 15) & 7;
177 }
178 #endif
179
180 /*
181  * Setup before decompression.  This is where we do UART selection for
182  * earlyprintk and init the uart_base register.
183  */
184 static inline void arch_decomp_setup(void)
185 {
186         int uart_id;
187         volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
188         volatile u32 *addr;
189         u32 div = DEBUG_UART_DLL_216;
190         u32 val;
191
192 #if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
193         uart_id = auto_odmdata();
194 #elif defined(CONFIG_TEGRA_DEBUG_UARTA)
195         uart_id = 0;
196 #elif defined(CONFIG_TEGRA_DEBUG_UARTB)
197         uart_id = 1;
198 #elif defined(CONFIG_TEGRA_DEBUG_UARTC)
199         uart_id = 2;
200 #elif defined(CONFIG_TEGRA_DEBUG_UARTD)
201         uart_id = 3;
202 #elif defined(CONFIG_TEGRA_DEBUG_UARTE)
203         uart_id = 4;
204 #endif
205
206         if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
207             !uart_clocked(uart_id))
208                 uart = NULL;
209         else
210                 uart = (volatile u8 *)uarts[uart_id].base;
211
212         if (uart == NULL)
213                 return;
214
215         /*
216          * On Tegra2 platforms PLLP always run at 216MHz
217          * On Tegra3 platforms PLLP can run at 216MHz, 204MHz, or 408MHz
218          * Discrimantion algorithm below assumes that PLLP is configured
219          * according to h/w recomendations with update rate 1MHz or 1.2MHz
220          * depending on oscillator frequency
221          */
222         addr = (volatile u32 *)PLLP_BASE;
223         val = *addr;
224         if (val & PLLP_BASE_OVERRIDE) {
225                 u32 p = (val & PLLP_BASE_DIVP_MASK) >> PLLP_BASE_DIVP_SHIFT;
226                 val = (val & PLLP_BASE_DIVN_MASK) >> (PLLP_BASE_DIVN_SHIFT + p);
227                 switch (val) {
228                 case 170:
229                 case 204:
230                         div = DEBUG_UART_DLL_204;
231                         break;
232                 case 340:
233                 case 408:
234                         div = DEBUG_UART_DLL_408;
235                         break;
236                 case 180:
237                 case 216:
238                 default:
239                         break;
240                 }
241         }
242
243         uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB;
244         uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
245         uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
246         uart[UART_LCR << DEBUG_UART_SHIFT] = 3;
247 }
248
249 #endif