blob: 6c087b6974b249d09f04743c6f0b6165f0a81299 [file] [log] [blame]
Erik Gillingc5f80062010-01-21 16:53:02 -08001/*
2 * arch/arm/mach-tegra/include/mach/uncompress.h
3 *
4 * Copyright (C) 2010 Google, Inc.
Doug Anderson229c7b22012-01-06 10:43:19 +00005 * Copyright (C) 2011 Google, Inc.
Stephen Warrenfe263982012-01-06 10:43:21 +00006 * Copyright (C) 2011 NVIDIA CORPORATION. All Rights Reserved.
Erik Gillingc5f80062010-01-21 16:53:02 -08007 *
8 * Author:
9 * Colin Cross <ccross@google.com>
10 * Erik Gilling <konkers@google.com>
Doug Anderson229c7b22012-01-06 10:43:19 +000011 * Doug Anderson <dianders@chromium.org>
Stephen Warrenfe263982012-01-06 10:43:21 +000012 * Stephen Warren <swarren@nvidia.com>
Erik Gillingc5f80062010-01-21 16:53:02 -080013 *
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
Stephen Warrenfe263982012-01-06 10:43:21 +000028#include <linux/kernel.h>
Erik Gillingc5f80062010-01-21 16:53:02 -080029#include <linux/types.h>
30#include <linux/serial_reg.h>
31
32#include <mach/iomap.h>
33
Doug Anderson229c7b22012-01-06 10:43:19 +000034#define DEBUG_UART_SHIFT 2
35
Doug Anderson31bac132012-01-06 10:43:20 +000036volatile u8 *uart;
37
Erik Gillingc5f80062010-01-21 16:53:02 -080038static void putc(int c)
39{
Erik Gillingc5f80062010-01-21 16:53:02 -080040 if (uart == NULL)
41 return;
42
Doug Anderson229c7b22012-01-06 10:43:19 +000043 while (!(uart[UART_LSR << DEBUG_UART_SHIFT] & UART_LSR_THRE))
Erik Gillingc5f80062010-01-21 16:53:02 -080044 barrier();
Doug Anderson229c7b22012-01-06 10:43:19 +000045 uart[UART_TX << DEBUG_UART_SHIFT] = c;
Erik Gillingc5f80062010-01-21 16:53:02 -080046}
47
48static inline void flush(void)
49{
50}
51
Stephen Warrenfe263982012-01-06 10:43:21 +000052/*
53 * Setup before decompression. This is where we do UART selection for
54 * earlyprintk and init the uart_base register.
55 */
Erik Gillingc5f80062010-01-21 16:53:02 -080056static inline void arch_decomp_setup(void)
57{
Stephen Warrenfe263982012-01-06 10:43:21 +000058 static const struct {
59 u32 base;
60 u32 reset_reg;
61 u32 clock_reg;
62 u32 bit;
63 } uarts[] = {
64 {
65 TEGRA_UARTA_BASE,
66 TEGRA_CLK_RESET_BASE + 0x04,
67 TEGRA_CLK_RESET_BASE + 0x10,
68 6,
69 },
70 {
71 TEGRA_UARTB_BASE,
72 TEGRA_CLK_RESET_BASE + 0x04,
73 TEGRA_CLK_RESET_BASE + 0x10,
74 7,
75 },
76 {
77 TEGRA_UARTC_BASE,
78 TEGRA_CLK_RESET_BASE + 0x08,
79 TEGRA_CLK_RESET_BASE + 0x14,
80 23,
81 },
82 {
83 TEGRA_UARTD_BASE,
84 TEGRA_CLK_RESET_BASE + 0x0c,
85 TEGRA_CLK_RESET_BASE + 0x18,
86 1,
87 },
88 {
89 TEGRA_UARTE_BASE,
90 TEGRA_CLK_RESET_BASE + 0x0c,
91 TEGRA_CLK_RESET_BASE + 0x18,
92 2,
93 },
94 };
95 int i;
Stephen Warrene53b7d82012-01-03 12:05:47 +000096 volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
97 u32 chip, div;
Erik Gillingc5f80062010-01-21 16:53:02 -080098
Stephen Warrenfe263982012-01-06 10:43:21 +000099 /*
100 * Look for the first UART that:
101 * a) Is not in reset.
102 * b) Is clocked.
103 * c) Has a 'D' in the scratchpad register.
104 *
105 * Note that on Tegra30, the first two conditions are required, since
106 * if not true, accesses to the UART scratch register will hang.
107 * Tegra20 doesn't have this issue.
108 *
109 * The intent is that the bootloader will tell the kernel which UART
110 * to use by setting up those conditions. If nothing found, we'll fall
111 * back to what's specified in TEGRA_DEBUG_UART_BASE.
112 */
113 for (i = 0; i < ARRAY_SIZE(uarts); i++) {
114 if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
115 continue;
116
117 if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
118 continue;
119
120 uart = (volatile u8 *)uarts[i].base;
121 if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
122 continue;
123
124 break;
125 }
126 if (i == ARRAY_SIZE(uarts))
127 uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
Erik Gillingc5f80062010-01-21 16:53:02 -0800128 if (uart == NULL)
129 return;
130
Stephen Warrene53b7d82012-01-03 12:05:47 +0000131 chip = (apb_misc[0x804 / 4] >> 8) & 0xff;
132 if (chip == 0x20)
133 div = 0x0075;
134 else
135 div = 0x00dd;
136
Doug Anderson229c7b22012-01-06 10:43:19 +0000137 uart[UART_LCR << DEBUG_UART_SHIFT] |= UART_LCR_DLAB;
138 uart[UART_DLL << DEBUG_UART_SHIFT] = div & 0xff;
139 uart[UART_DLM << DEBUG_UART_SHIFT] = div >> 8;
140 uart[UART_LCR << DEBUG_UART_SHIFT] = 3;
Erik Gillingc5f80062010-01-21 16:53:02 -0800141}
142
143static inline void arch_decomp_wdog(void)
144{
145}
146
147#endif