Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uncompress.h
Go to the documentation of this file.
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 <[email protected]>
10  * Erik Gilling <[email protected]>
11  * Doug Anderson <[email protected]>
12  * Stephen Warren <[email protected]>
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/iomap.h>
32 #include <mach/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 
47  barrier();
49 }
50 
51 static inline void flush(void)
52 {
53 }
54 
55 static inline void save_uart_address(void)
56 {
58 
59  if (uart) {
61  buf[1] = (u32)uart;
62  } else
63  buf[0] = 0;
64 }
65 
66 static const struct {
71 } uarts[] = {
72  {
74  TEGRA_CLK_RESET_BASE + 0x04,
75  TEGRA_CLK_RESET_BASE + 0x10,
76  6,
77  },
78  {
80  TEGRA_CLK_RESET_BASE + 0x04,
81  TEGRA_CLK_RESET_BASE + 0x10,
82  7,
83  },
84  {
86  TEGRA_CLK_RESET_BASE + 0x08,
87  TEGRA_CLK_RESET_BASE + 0x14,
88  23,
89  },
90  {
92  TEGRA_CLK_RESET_BASE + 0x0c,
93  TEGRA_CLK_RESET_BASE + 0x18,
94  1,
95  },
96  {
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 
227  uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
228  uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
230 }
231 
232 static inline void arch_decomp_wdog(void)
233 {
234 }
235 
236 #endif