]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/blob - arch/arm/mach-tegra/include/mach/uncompress.h
mm/bootmem.c: remove unused wrapper function reserve_bootmem_generic()
[can-eth-gw-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 "../../iomap.h"
32 #include "../../irammap.h"
33
34 #define BIT(x) (1 << (x))
35 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
36
37 #define DEBUG_UART_SHIFT 2
38
39 volatile u8 *uart;
40
41 static void putc(int c)
42 {
43         if (uart == NULL)
44                 return;
45
46         while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE))
47                 barrier();
48         uart[UART_TX << DEBUG_UART_SHIFT] = c;
49 }
50
51 static inline void flush(void)
52 {
53 }
54
55 static inline void save_uart_address(void)
56 {
57         u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
58
59         if (uart) {
60                 buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
61                 buf[1] = (u32)uart;
62         } else
63                 buf[0] = 0;
64 }
65
66 static const struct {
67         u32 base;
68         u32 reset_reg;
69         u32 clock_reg;
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)
144 {
145         int i;
146
147         /*
148          * Look for the first UART that:
149          * a) Is not in reset.
150          * b) Is clocked.
151          * c) Has a 'D' in the scratchpad register.
152          *
153          * Note that on Tegra30, the first two conditions are required, since
154          * if not true, accesses to the UART scratch register will hang.
155          * Tegra20 doesn't have this issue.
156          *
157          * The intent is that the bootloader will tell the kernel which UART
158          * to use by setting up those conditions. If nothing found, we'll fall
159          * back to what's specified in TEGRA_DEBUG_UART_BASE.
160          */
161         for (i = 0; i < ARRAY_SIZE(uarts); i++) {
162                 if (!uart_clocked(i))
163                         continue;
164
165                 uart = (volatile u8 *)uarts[i].base;
166                 if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
167                         continue;
168
169                 return i;
170         }
171
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
216         save_uart_address();
217         if (uart == NULL)
218                 return;
219
220         chip = (apb_misc[0x804 / 4] >> 8) & 0xff;
221         if (chip == 0x20)
222                 div = 0x0075;
223         else
224                 div = 0x00dd;
225
226         uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB;
227         uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
228         uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
229         uart[UART_LCR << DEBUG_UART_SHIFT] = 3;
230 }
231
232 static inline void arch_decomp_wdog(void)
233 {
234 }
235
236 #endif