blob: 1fe12d7d204a9b1b3c63099e2ce572824ab6cdc8 [file] [log] [blame]
Erik Gillingc5f80062010-01-21 16:53:02 -08001/*
Todd Poynor433cb7f2010-09-02 15:10:29 -07002 * arch/arm/mach-tegra/common.c
Erik Gillingc5f80062010-01-21 16:53:02 -08003 *
4 * Copyright (C) 2010 Google, Inc.
5 *
6 * Author:
7 * Colin Cross <ccross@android.com>
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -070020#include <linux/platform_device.h>
Dima Zavin7e158ac2010-11-11 15:28:46 -080021#include <linux/console.h>
Erik Gillingc5f80062010-01-21 16:53:02 -080022#include <linux/init.h>
23#include <linux/io.h>
Colin Cross4de3a8f2010-04-05 13:16:42 -070024#include <linux/clk.h>
25#include <linux/delay.h>
Colin Cross115467a2010-10-19 21:09:29 -070026#include <linux/highmem.h>
Colin Cross8e437c22010-11-28 22:36:08 -080027#include <linux/memblock.h>
Bo Yandf2009a2011-04-18 17:04:47 -070028#include <linux/notifier.h>
29#include <linux/reboot.h>
30#include <linux/mqueue.h>
Rakesh Bodla1ad210a2011-05-31 15:18:00 +053031#include <linux/bitops.h>
Erik Gillingc5f80062010-01-21 16:53:02 -080032
33#include <asm/hardware/cache-l2x0.h>
Dima Zavin7e158ac2010-11-11 15:28:46 -080034#include <asm/system.h>
Erik Gillingc5f80062010-01-21 16:53:02 -080035
Colin Cross45a1ca02011-03-28 17:47:31 -070036#include <mach/gpio.h>
Erik Gillingc5f80062010-01-21 16:53:02 -080037#include <mach/iomap.h>
Colin Cross120c3562011-03-28 17:48:56 -070038#include <mach/pinmux.h>
Dima Zavin7db7cbc2010-09-16 17:58:05 -070039#include <mach/powergate.h>
Colin Cross699fe142010-08-23 18:37:25 -070040#include <mach/system.h>
Erik Gillingc5f80062010-01-21 16:53:02 -080041
Jon Mayo6ae77a92010-12-21 15:09:33 -080042#include "apbio.h"
Erik Gillingc5f80062010-01-21 16:53:02 -080043#include "board.h"
Colin Crossd8611962010-01-28 16:40:29 -080044#include "clock.h"
Colin Cross73625e32010-06-23 15:49:17 -070045#include "fuse.h"
Colin Cross8e437c22010-11-28 22:36:08 -080046#include "pm.h"
47
Scott Williams816ab052010-12-07 11:19:20 -080048#define MC_SECURITY_CFG2 0x7c
Colin Crossf9c9bde2010-10-19 16:12:33 -070049
Rakesh Bodla1ad210a2011-05-31 15:18:00 +053050#define AHB_ARBITRATION_PRIORITY_CTRL 0x4
51#define AHB_PRIORITY_WEIGHT(x) (((x) & 0x7) << 29)
52#define PRIORITY_SELECT_USB BIT(6)
53#define PRIORITY_SELECT_USB2 BIT(18)
54#define PRIORITY_SELECT_USB3 BIT(17)
55
56#define AHB_GIZMO_AHB_MEM 0xc
57#define ENB_FAST_REARBITRATE BIT(2)
Jay Chengce4a7df2011-06-09 17:34:35 -040058#define DONT_SPLIT_AHB_WR BIT(7)
Rakesh Bodla1ad210a2011-05-31 15:18:00 +053059
60#define AHB_GIZMO_USB 0x1c
61#define AHB_GIZMO_USB2 0x78
62#define AHB_GIZMO_USB3 0x7c
63#define IMMEDIATE BIT(18)
64
65#define AHB_MEM_PREFETCH_CFG3 0xe0
66#define AHB_MEM_PREFETCH_CFG4 0xe4
67#define AHB_MEM_PREFETCH_CFG1 0xec
68#define AHB_MEM_PREFETCH_CFG2 0xf0
69#define PREFETCH_ENB BIT(31)
70#define MST_ID(x) (((x) & 0x1f) << 26)
71#define AHBDMA_MST_ID MST_ID(5)
72#define USB_MST_ID MST_ID(6)
73#define USB2_MST_ID MST_ID(18)
74#define USB3_MST_ID MST_ID(17)
75#define ADDR_BNDRY(x) (((x) & 0xf) << 21)
76#define INACTIVITY_TIMEOUT(x) (((x) & 0xffff) << 0)
77
Colin Cross838d7d62010-10-19 14:45:50 -070078unsigned long tegra_bootloader_fb_start;
79unsigned long tegra_bootloader_fb_size;
80unsigned long tegra_fb_start;
81unsigned long tegra_fb_size;
82unsigned long tegra_fb2_start;
83unsigned long tegra_fb2_size;
84unsigned long tegra_carveout_start;
85unsigned long tegra_carveout_size;
Colin Cross8e437c22010-11-28 22:36:08 -080086unsigned long tegra_lp0_vec_start;
87unsigned long tegra_lp0_vec_size;
Scott Williams03122532011-01-13 14:30:20 -080088unsigned long tegra_grhost_aperture = ~0ul;
Pradeep Goudagunta3dd04c42011-03-23 23:16:12 +053089static bool is_tegra_debug_uart_hsport;
Laxman Dewangan87d07ce2011-06-15 00:48:57 +053090static struct board_info pmu_board_info;
Colin Crossd8611962010-01-28 16:40:29 -080091
Alex Frid3a5fc7c2011-05-11 16:01:44 -070092static int pmu_core_edp = 1200; /* default 1.2V EDP limit */
Laxman Dewanganb1a6ea22011-05-09 19:15:29 +053093static int board_panel_type;
94
Colin Cross699fe142010-08-23 18:37:25 -070095void (*arch_reset)(char mode, const char *cmd) = tegra_assert_system_reset;
96
Scott Williams9bc40532011-01-28 03:26:28 -080097#define NEVER_RESET 1
98
Colin Cross699fe142010-08-23 18:37:25 -070099void tegra_assert_system_reset(char mode, const char *cmd)
100{
Scott Williams9bc40532011-01-28 03:26:28 -0800101#if defined(CONFIG_TEGRA_FPGA_PLATFORM) || NEVER_RESET
102 printk("tegra_assert_system_reset() call attempted on FPGA target platform.....");
103 do { } while (1);
104#else
Deepesh Gujarathi43921782010-12-07 14:09:22 +0530105 void __iomem *reset = IO_ADDRESS(TEGRA_PMC_BASE + 0x00);
Colin Cross699fe142010-08-23 18:37:25 -0700106 u32 reg;
107
Simon Glass375b19c2011-02-17 08:13:57 -0800108 /* use *_related to avoid spinlock since caches are off */
109 reg = readl_relaxed(reset);
Deepesh Gujarathi43921782010-12-07 14:09:22 +0530110 reg |= 0x10;
Simon Glass375b19c2011-02-17 08:13:57 -0800111 writel_relaxed(reg, reset);
Scott Williams4ad5ff12011-01-07 20:43:13 -0800112#endif
Colin Cross699fe142010-08-23 18:37:25 -0700113}
114
Laxman Dewangan844407d2011-04-27 19:11:08 +0530115/* WARNING: There is implicit client of pllp_out3 like i2c, uart, dsi
116 * and so this clock (pllp_out3) should never be disabled.
117 */
Colin Crossd8611962010-01-28 16:40:29 -0800118static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
119 /* name parent rate enabled */
120 { "clk_m", NULL, 0, true },
Scott Williams0aac1552011-06-10 12:58:11 -0700121#ifndef CONFIG_TEGRA_FPGA_PLATFORM
Alex Fridc86c2252011-05-28 00:21:30 -0700122#ifdef CONFIG_ARCH_TEGRA_2x_SOC
Scott Williams816ab052010-12-07 11:19:20 -0800123 { "pll_p", NULL, 216000000, true },
Colin Crossd8611962010-01-28 16:40:29 -0800124 { "pll_p_out1", "pll_p", 28800000, true },
125 { "pll_p_out2", "pll_p", 48000000, true },
126 { "pll_p_out3", "pll_p", 72000000, true },
127 { "pll_p_out4", "pll_p", 108000000, true },
Scott Williams07fc3312011-05-23 22:08:42 -0700128 { "pll_m", "clk_m", 600000000, true },
129 { "pll_m_out1", "pll_m", 120000000, true },
130 { "sclk", "pll_m_out1", 40000000, true },
131 { "hclk", "sclk", 40000000, true },
132 { "pclk", "hclk", 40000000, true },
133#else
Alex Fridc86c2252011-05-28 00:21:30 -0700134 { "pll_p", NULL, 408000000, true },
135 { "pll_p_out1", "pll_p", 9600000, true },
136 { "pll_p_out2", "pll_p", 48000000, true },
137 { "pll_p_out3", "pll_p", 102000000, true },
Alex Frid8b5ce662011-01-31 10:07:57 -0800138 { "pll_m_out1", "pll_m", 275000000, true },
Alex Frid623a8932011-05-17 18:14:36 -0700139 { "pll_c", NULL, ULONG_MAX, false },
Alex Frid805f1af2011-04-27 21:26:15 -0700140 { "pll_c_out1", "pll_c", 208000000, false },
Alex Fridc86c2252011-05-28 00:21:30 -0700141 { "pll_p_out4", "pll_p", 102000000, true },
142 { "sclk", "pll_p_out4", 102000000, true },
143 { "hclk", "sclk", 102000000, true },
144 { "pclk", "hclk", 51000000, true },
Alex Frid8b5ce662011-01-31 10:07:57 -0800145#endif
Scott Williams0aac1552011-06-10 12:58:11 -0700146#else
147 { "pll_p", NULL, 216000000, true },
148 { "pll_p_out1", "pll_p", 28800000, true },
149 { "pll_p_out2", "pll_p", 48000000, true },
150 { "pll_p_out3", "pll_p", 72000000, true },
151 { "pll_m_out1", "pll_m", 275000000, true },
152 { "pll_c", NULL, ULONG_MAX, false },
153 { "pll_c_out1", "pll_c", 208000000, false },
154 { "pll_p_out4", "pll_p", 108000000, true },
155 { "sclk", "pll_p_out4", 108000000, true },
156 { "hclk", "sclk", 108000000, true },
157 { "pclk", "hclk", 54000000, true },
158#endif
Colin Crosscd51d0e2011-02-21 17:05:36 -0800159 { "csite", NULL, 0, true },
160 { "emc", NULL, 0, true },
161 { "cpu", NULL, 0, true },
Alex Fridd3b4e362011-05-26 22:58:21 -0700162 { "kfuse", NULL, 0, true },
Scott Williams816ab052010-12-07 11:19:20 -0800163 { "pll_u", NULL, 480000000, false },
Alex Fridc86c2252011-05-28 00:21:30 -0700164 { "sdmmc1", "pll_p", 48000000, false},
Pavan Kunapuli0a420462011-03-16 19:29:42 +0530165 { "sdmmc3", "pll_p", 48000000, false},
166 { "sdmmc4", "pll_p", 48000000, false},
Scott Williams07fc3312011-05-23 22:08:42 -0700167#ifndef CONFIG_ARCH_TEGRA_2x_SOC
Alex Frid623a8932011-05-17 18:14:36 -0700168 { "vde", "pll_c", ULONG_MAX, false },
169 { "host1x", "pll_c", 0, false },
Bo Yan5cc19e92011-03-02 11:56:27 -0800170 { "mpe", "pll_c", 0, false },
171 { "3d", "pll_c", 0, false },
172 { "3d2", "pll_c", 0, false },
173 { "2d", "pll_c", 0, false },
Alex Frid8feae492011-04-07 14:15:37 -0700174 { "epp", "pll_c", 0, false },
175 { "se", "pll_c", 0, false },
Alex Frid7f970e72011-02-04 12:04:14 -0800176#endif
Colin Crossd8611962010-01-28 16:40:29 -0800177 { NULL, NULL, 0, 0},
178};
Erik Gillingc5f80062010-01-21 16:53:02 -0800179
Colin Cross8e437c22010-11-28 22:36:08 -0800180void tegra_init_cache(void)
Erik Gillingc5f80062010-01-21 16:53:02 -0800181{
182#ifdef CONFIG_CACHE_L2X0
183 void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
Scott Williams191914c2010-12-27 19:03:57 -0800184 u32 aux_ctrl;
Erik Gillingc5f80062010-01-21 16:53:02 -0800185
Scott Williams816ab052010-12-07 11:19:20 -0800186#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
Colin Cross535371c2011-01-22 00:36:14 -0800187 writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL);
188 writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL);
Erik Gillingc5f80062010-01-21 16:53:02 -0800189
Scott Williams816ab052010-12-07 11:19:20 -0800190#elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
191#ifdef CONFIG_TEGRA_FPGA_PLATFORM
192 writel(0x770, p + L2X0_TAG_LATENCY_CTRL);
193 writel(0x770, p + L2X0_DATA_LATENCY_CTRL);
Scott Williams816ab052010-12-07 11:19:20 -0800194#else
Scott Williams1245c8e2011-01-05 17:53:39 -0800195 /* PL310 RAM latency is CPU dependent. NOTE: Changes here
196 must also be reflected in __cortex_a9_l2x0_restart */
197
198 if (is_lp_cluster()) {
199 writel(0x221, p + L2X0_TAG_LATENCY_CTRL);
200 writel(0x221, p + L2X0_DATA_LATENCY_CTRL);
201 } else {
202 writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
203 writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
204 }
Scott Williams816ab052010-12-07 11:19:20 -0800205#endif
206
207 /* Enable PL310 double line fill feature. */
Scott Williamsebbc7e02011-05-26 13:20:13 -0700208 writel(((1<<30) | 0), p + L2X0_PREFETCH_CTRL);
Scott Williams816ab052010-12-07 11:19:20 -0800209#endif
Scott Williams191914c2010-12-27 19:03:57 -0800210 aux_ctrl = readl(p + L2X0_CACHE_TYPE);
211 aux_ctrl = (aux_ctrl & 0x700) << (17-8);
212 aux_ctrl |= 0x6C000001;
213 l2x0_init(p, aux_ctrl, 0x8200c3fe);
Erik Gillingc5f80062010-01-21 16:53:02 -0800214#endif
215}
216
Dima Zavin7db7cbc2010-09-16 17:58:05 -0700217static void __init tegra_init_power(void)
218{
219 tegra_powergate_power_off(TEGRA_POWERGATE_MPE);
220 tegra_powergate_power_off(TEGRA_POWERGATE_3D);
Scott Williams07fc3312011-05-23 22:08:42 -0700221#ifdef CONFIG_ARCH_TEGRA_2x_SOC
Shashank Gargb93af642011-05-17 16:55:23 +0530222 /* for TEGRA_3x_SOC it will be handled seperately */
Roger Hsiehac108442011-03-21 16:51:36 +0800223 tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
Narendra Damahe37a2c402011-04-29 12:09:25 -0700224#endif
Shashank Gargb93af642011-05-17 16:55:23 +0530225#ifndef CONFIG_ARCH_TEGRA_2x_SOC
226 tegra_powergate_power_off(TEGRA_POWERGATE_3D1);
227#endif
Dima Zavin7db7cbc2010-09-16 17:58:05 -0700228}
229
Rakesh Bodla1ad210a2011-05-31 15:18:00 +0530230static inline unsigned long gizmo_readl(unsigned long offset)
231{
232 return readl(IO_TO_VIRT(TEGRA_AHB_GIZMO_BASE + offset));
233}
234
235static inline void gizmo_writel(unsigned long value, unsigned long offset)
236{
237 writel(value, IO_TO_VIRT(TEGRA_AHB_GIZMO_BASE + offset));
238}
239
240static void __init tegra_init_ahb_gizmo_settings(void)
241{
242 unsigned long val;
243
244 val = gizmo_readl(AHB_GIZMO_AHB_MEM);
Jay Chengce4a7df2011-06-09 17:34:35 -0400245 val |= ENB_FAST_REARBITRATE | IMMEDIATE | DONT_SPLIT_AHB_WR;
Rakesh Bodla1ad210a2011-05-31 15:18:00 +0530246 gizmo_writel(val, AHB_GIZMO_AHB_MEM);
247
248 val = gizmo_readl(AHB_GIZMO_USB);
249 val |= IMMEDIATE;
250 gizmo_writel(val, AHB_GIZMO_USB);
251
252 val = gizmo_readl(AHB_GIZMO_USB2);
253 val |= IMMEDIATE;
254 gizmo_writel(val, AHB_GIZMO_USB2);
255
256 val = gizmo_readl(AHB_GIZMO_USB3);
257 val |= IMMEDIATE;
258 gizmo_writel(val, AHB_GIZMO_USB3);
259
260 val = gizmo_readl(AHB_ARBITRATION_PRIORITY_CTRL);
261 val |= PRIORITY_SELECT_USB | PRIORITY_SELECT_USB2 | PRIORITY_SELECT_USB3
262 | AHB_PRIORITY_WEIGHT(7);
263 gizmo_writel(val, AHB_ARBITRATION_PRIORITY_CTRL);
264
265 val = gizmo_readl(AHB_MEM_PREFETCH_CFG1);
266 val &= ~MST_ID(~0);
267 val |= PREFETCH_ENB | AHBDMA_MST_ID | ADDR_BNDRY(0xc) | INACTIVITY_TIMEOUT(0x1000);
268 gizmo_writel(val, AHB_MEM_PREFETCH_CFG1);
269
270 val = gizmo_readl(AHB_MEM_PREFETCH_CFG2);
271 val &= ~MST_ID(~0);
272 val |= PREFETCH_ENB | USB_MST_ID | ADDR_BNDRY(0xc) | INACTIVITY_TIMEOUT(0x1000);
273 gizmo_writel(val, AHB_MEM_PREFETCH_CFG2);
274
275 val = gizmo_readl(AHB_MEM_PREFETCH_CFG3);
276 val &= ~MST_ID(~0);
277 val |= PREFETCH_ENB | USB3_MST_ID | ADDR_BNDRY(0xc) | INACTIVITY_TIMEOUT(0x1000);
278 gizmo_writel(val, AHB_MEM_PREFETCH_CFG3);
279
280 val = gizmo_readl(AHB_MEM_PREFETCH_CFG4);
281 val &= ~MST_ID(~0);
282 val |= PREFETCH_ENB | USB2_MST_ID | ADDR_BNDRY(0xc) | INACTIVITY_TIMEOUT(0x1000);
283 gizmo_writel(val, AHB_MEM_PREFETCH_CFG4);
284}
285
Dima Zavin7e158ac2010-11-11 15:28:46 -0800286static bool console_flushed;
287
Bo Yandf2009a2011-04-18 17:04:47 -0700288static int tegra_pm_flush_console(struct notifier_block *this,
289 unsigned long code,
290 void *unused)
Dima Zavin7e158ac2010-11-11 15:28:46 -0800291{
292 if (console_flushed)
Bo Yandf2009a2011-04-18 17:04:47 -0700293 return NOTIFY_NONE;
Dima Zavin7e158ac2010-11-11 15:28:46 -0800294 console_flushed = true;
295
296 printk("\n");
297 pr_emerg("Restarting %s\n", linux_banner);
Colin Crossfec84b22011-04-07 14:40:23 -0700298 if (console_trylock()) {
299 console_unlock();
Bo Yandf2009a2011-04-18 17:04:47 -0700300 return NOTIFY_NONE;
Dima Zavin7e158ac2010-11-11 15:28:46 -0800301 }
302
303 mdelay(50);
304
305 local_irq_disable();
Colin Crossfec84b22011-04-07 14:40:23 -0700306 if (!console_trylock())
Dima Zavin7e158ac2010-11-11 15:28:46 -0800307 pr_emerg("tegra_restart: Console was locked! Busting\n");
308 else
309 pr_emerg("tegra_restart: Console was locked!\n");
Colin Crossfec84b22011-04-07 14:40:23 -0700310 console_unlock();
Bo Yandf2009a2011-04-18 17:04:47 -0700311 return NOTIFY_NONE;
Dima Zavin7e158ac2010-11-11 15:28:46 -0800312}
313
Bo Yandf2009a2011-04-18 17:04:47 -0700314static struct notifier_block tegra_reboot_notifier = {
315 .notifier_call = tegra_pm_flush_console,
316};
317
Dima Zavin7e158ac2010-11-11 15:28:46 -0800318static void tegra_pm_restart(char mode, const char *cmd)
319{
Dima Zavin7e158ac2010-11-11 15:28:46 -0800320 arm_machine_restart(mode, cmd);
321}
322
Colin Cross0cf62302011-02-21 17:10:14 -0800323void __init tegra_init_early(void)
Erik Gillingc5f80062010-01-21 16:53:02 -0800324{
Dima Zavin7e158ac2010-11-11 15:28:46 -0800325 arm_pm_restart = tegra_pm_restart;
Bo Yandf2009a2011-04-18 17:04:47 -0700326 register_reboot_notifier(&tegra_reboot_notifier);
Colin Cross73625e32010-06-23 15:49:17 -0700327 tegra_init_fuse();
Colin Cross45a1ca02011-03-28 17:47:31 -0700328 tegra_gpio_resume_init();
Colin Crossd8611962010-01-28 16:40:29 -0800329 tegra_init_clock();
Colin Cross120c3562011-03-28 17:48:56 -0700330 tegra_init_pinmux();
Colin Crossd8611962010-01-28 16:40:29 -0800331 tegra_clk_init_from_table(common_clk_init_table);
Dima Zavin7db7cbc2010-09-16 17:58:05 -0700332 tegra_init_power();
Erik Gillingc5f80062010-01-21 16:53:02 -0800333 tegra_init_cache();
Hiro Sugawarac00e4312011-01-19 13:57:30 -0800334#ifndef CONFIG_ARCH_TEGRA_2x_SOC
335 tegra_mc_init(); /* !!!FIXME!!! Change Tegra3 behavior to match Tegra2 */
336#endif
Rakesh Bodla1ad210a2011-05-31 15:18:00 +0530337 tegra_init_ahb_gizmo_settings();
Erik Gillingc5f80062010-01-21 16:53:02 -0800338}
Colin Cross8e437c22010-11-28 22:36:08 -0800339
340static int __init tegra_lp0_vec_arg(char *options)
341{
342 char *p = options;
343
344 tegra_lp0_vec_size = memparse(p, &p);
345 if (*p == '@')
346 tegra_lp0_vec_start = memparse(p+1, &p);
Scott Williams03122532011-01-13 14:30:20 -0800347 if (!tegra_lp0_vec_size || !tegra_lp0_vec_start) {
348 tegra_lp0_vec_size = 0;
349 tegra_lp0_vec_start = 0;
350 }
Colin Cross8e437c22010-11-28 22:36:08 -0800351
352 return 0;
353}
354early_param("lp0_vec", tegra_lp0_vec_arg);
355
Colin Cross838d7d62010-10-19 14:45:50 -0700356static int __init tegra_bootloader_fb_arg(char *options)
357{
358 char *p = options;
Scott Williams03122532011-01-13 14:30:20 -0800359 unsigned long start;
360 unsigned long size;
Colin Cross838d7d62010-10-19 14:45:50 -0700361
362 tegra_bootloader_fb_size = memparse(p, &p);
363 if (*p == '@')
364 tegra_bootloader_fb_start = memparse(p+1, &p);
365
366 pr_info("Found tegra_fbmem: %08lx@%08lx\n",
367 tegra_bootloader_fb_size, tegra_bootloader_fb_start);
368
369 return 0;
370}
371early_param("tegra_fbmem", tegra_bootloader_fb_arg);
372
Laxman Dewanganb1a6ea22011-05-09 19:15:29 +0530373enum panel_type get_panel_type(void)
374{
375 return board_panel_type;
376}
377static int __init tegra_board_panel_type(char *options)
378{
379 if (!strcmp(options, "lvds"))
380 board_panel_type = panel_type_lvds;
381 else if (!strcmp(options, "dsi"))
382 board_panel_type = panel_type_dsi;
383 else
384 return 0;
385 return 1;
386}
387__setup("panel=", tegra_board_panel_type);
388
389int get_core_edp(void)
390{
391 return pmu_core_edp;
392}
393static int __init tegra_pmu_core_edp(char *options)
394{
395 char *p = options;
Alex Frid3a5fc7c2011-05-11 16:01:44 -0700396 int core_edp = memparse(p, &p);
397 if (core_edp != 0)
398 pmu_core_edp = core_edp;
Laxman Dewanganb1a6ea22011-05-09 19:15:29 +0530399 return 1;
400}
401__setup("core_edp_mv=", tegra_pmu_core_edp);
402
Pradeep Goudagunta3dd04c42011-03-23 23:16:12 +0530403static int __init tegra_debug_uartport(char *info)
404{
405 if (!strcmp(info, "hsport"))
406 is_tegra_debug_uart_hsport = true;
407 else if (!strcmp(info, "lsport"))
408 is_tegra_debug_uart_hsport = false;
409
410 return 1;
411}
412
413bool is_tegra_debug_uartport_hs(void)
414{
415 return is_tegra_debug_uart_hsport;
416}
417
418__setup("debug_uartport=", tegra_debug_uartport);
419
Nitin Kumbhar637ced42010-12-10 15:16:37 +0530420void tegra_get_board_info(struct board_info *bi)
421{
Laxman Dewanganc0f18022011-02-05 16:26:42 +0530422 bi->board_id = (system_serial_high >> 16) & 0xFFFF;
423 bi->sku = (system_serial_high) & 0xFFFF;
424 bi->fab = (system_serial_low >> 24) & 0xFF;
425 bi->major_revision = (system_serial_low >> 16) & 0xFF;
426 bi->minor_revision = (system_serial_low >> 8) & 0xFF;
Nitin Kumbhar637ced42010-12-10 15:16:37 +0530427}
428
Laxman Dewangan87d07ce2011-06-15 00:48:57 +0530429static int __init tegra_pmu_board_info(char *info)
430{
431 char *p = info;
432 pmu_board_info.board_id = memparse(p, &p);
433 pmu_board_info.sku = memparse(p+1, &p);
434 pmu_board_info.fab = memparse(p+1, &p);
435 pmu_board_info.major_revision = memparse(p+1, &p);
436 pmu_board_info.minor_revision = memparse(p+1, &p);
437 return 1;
438}
439
440void tegra_get_pmu_board_info(struct board_info *bi)
441{
442 memcpy(bi, &pmu_board_info, sizeof(struct board_info));
443}
444
445__setup("pmuboard=", tegra_pmu_board_info);
446
447
Colin Crossf9c9bde2010-10-19 16:12:33 -0700448/*
449 * Tegra has a protected aperture that prevents access by most non-CPU
450 * memory masters to addresses above the aperture value. Enabling it
451 * secures the CPU's memory from the GPU, except through the GART.
452 */
453void __init tegra_protected_aperture_init(unsigned long aperture)
454{
455#ifndef CONFIG_NVMAP_ALLOW_SYSMEM
456 void __iomem *mc_base = IO_ADDRESS(TEGRA_MC_BASE);
457 pr_info("Enabling Tegra protected aperture at 0x%08lx\n", aperture);
458 writel(aperture, mc_base + MC_SECURITY_CFG2);
459#else
460 pr_err("Tegra protected aperture disabled because nvmap is using "
461 "system memory\n");
462#endif
463}
464
Colin Cross115467a2010-10-19 21:09:29 -0700465/*
466 * Due to conflicting restrictions on the placement of the framebuffer,
467 * the bootloader is likely to leave the framebuffer pointed at a location
468 * in memory that is outside the grhost aperture. This function will move
469 * the framebuffer contents from a physical address that is anywher (lowmem,
470 * highmem, or outside the memory map) to a physical address that is outside
471 * the memory map.
472 */
473void tegra_move_framebuffer(unsigned long to, unsigned long from,
474 unsigned long size)
475{
476 struct page *page;
477 void __iomem *to_io;
478 void *from_virt;
479 unsigned long i;
480
481 BUG_ON(PAGE_ALIGN((unsigned long)to) != (unsigned long)to);
482 BUG_ON(PAGE_ALIGN(from) != from);
483 BUG_ON(PAGE_ALIGN(size) != size);
484
485 to_io = ioremap(to, size);
486 if (!to_io) {
487 pr_err("%s: Failed to map target framebuffer\n", __func__);
488 return;
489 }
490
Colin Cross115467a2010-10-19 21:09:29 -0700491 if (pfn_valid(page_to_pfn(phys_to_page(from)))) {
492 for (i = 0 ; i < size; i += PAGE_SIZE) {
493 page = phys_to_page(from + i);
494 from_virt = kmap(page);
495 memcpy_toio(to_io + i, from_virt, PAGE_SIZE);
496 kunmap(page);
497 }
498 } else {
499 void __iomem *from_io = ioremap(from, size);
500 if (!from_io) {
501 pr_err("%s: Failed to map source framebuffer\n",
502 __func__);
503 goto out;
504 }
505
506 for (i = 0; i < size; i+= 4)
507 writel(readl(from_io + i), to_io + i);
508
509 iounmap(from_io);
510 }
511out:
512 iounmap(to_io);
513}
514
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -0700515#ifdef CONFIG_TEGRA_IOVMM_SMMU
516/* Support for Tegra3 A01 chip mask that needs to have SMMU IOVA reside in
517 * the upper half of 4GB IOVA space. A02 and after use the bottom 1GB and
518 * do not need to reserve memory.
519 */
520#define SUPPORT_TEGRA_3_IOVMM_SMMU_A01
521#endif
522
Colin Cross838d7d62010-10-19 14:45:50 -0700523void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
524 unsigned long fb2_size)
525{
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -0700526#ifdef SUPPORT_TEGRA_3_IOVMM_SMMU_A01
527 extern struct platform_device tegra_smmu_device;
528 int smmu_reserved = 0;
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -0700529 struct resource *smmu_window =
530 platform_get_resource_byname(&tegra_smmu_device,
531 IORESOURCE_MEM, "smmu");
532#endif
Colin Cross838d7d62010-10-19 14:45:50 -0700533 if (tegra_lp0_vec_size)
Scott Williams03122532011-01-13 14:30:20 -0800534 if (memblock_reserve(tegra_lp0_vec_start, tegra_lp0_vec_size)) {
Colin Cross838d7d62010-10-19 14:45:50 -0700535 pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
536 tegra_lp0_vec_size, tegra_lp0_vec_start);
Scott Williams03122532011-01-13 14:30:20 -0800537 tegra_lp0_vec_start = 0;
538 tegra_lp0_vec_size = 0;
539 }
Colin Cross838d7d62010-10-19 14:45:50 -0700540
Scott Williams03122532011-01-13 14:30:20 -0800541 if (carveout_size) {
542 tegra_carveout_start = memblock_end_of_DRAM() - carveout_size;
543 if (memblock_remove(tegra_carveout_start, carveout_size)) {
544 pr_err("Failed to remove carveout %08lx@%08lx "
545 "from memory map\n",
Hiro Sugawara5cb430a2011-03-10 15:19:03 -0800546 carveout_size, tegra_carveout_start);
Scott Williams03122532011-01-13 14:30:20 -0800547 tegra_carveout_start = 0;
548 tegra_carveout_size = 0;
549 }
550 else
551 tegra_carveout_size = carveout_size;
552 }
Colin Cross838d7d62010-10-19 14:45:50 -0700553
Scott Williams03122532011-01-13 14:30:20 -0800554 if (fb2_size) {
555 tegra_fb2_start = memblock_end_of_DRAM() - fb2_size;
556 if (memblock_remove(tegra_fb2_start, fb2_size)) {
557 pr_err("Failed to remove second framebuffer %08lx@%08lx "
558 "from memory map\n",
Hiro Sugawaradc1d2812011-04-29 11:59:37 -0700559 fb2_size, tegra_fb2_start);
Scott Williams03122532011-01-13 14:30:20 -0800560 tegra_fb2_start = 0;
561 tegra_fb2_size = 0;
562 } else
563 tegra_fb2_size = fb2_size;
564 }
Colin Cross838d7d62010-10-19 14:45:50 -0700565
Scott Williams03122532011-01-13 14:30:20 -0800566 if (fb_size) {
567 tegra_fb_start = memblock_end_of_DRAM() - fb_size;
568 if (memblock_remove(tegra_fb_start, fb_size)) {
569 pr_err("Failed to remove framebuffer %08lx@%08lx "
570 "from memory map\n",
Hiro Sugawara5cb430a2011-03-10 15:19:03 -0800571 fb_size, tegra_fb_start);
Scott Williams03122532011-01-13 14:30:20 -0800572 tegra_fb_start = 0;
573 tegra_fb_size = 0;
574 } else
575 tegra_fb_size = fb_size;
576 }
Colin Cross838d7d62010-10-19 14:45:50 -0700577
Colin Crossf9c9bde2010-10-19 16:12:33 -0700578 if (tegra_fb_size)
579 tegra_grhost_aperture = tegra_fb_start;
580
581 if (tegra_fb2_size && tegra_fb2_start < tegra_grhost_aperture)
582 tegra_grhost_aperture = tegra_fb2_start;
583
584 if (tegra_carveout_size && tegra_carveout_start < tegra_grhost_aperture)
585 tegra_grhost_aperture = tegra_carveout_start;
586
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -0700587#ifdef SUPPORT_TEGRA_3_IOVMM_SMMU_A01
588 if (!smmu_window) {
589 pr_err("No SMMU resources\n");
590 } else {
Hiro Sugawara0d218182011-04-08 13:21:02 -0700591 size_t smmu_window_size;
592
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -0700593 if (tegra_get_revision() == TEGRA_REVISION_A01) {
594 smmu_window->start = TEGRA_SMMU_BASE_A01;
595 smmu_window->end = TEGRA_SMMU_BASE_A01 +
596 TEGRA_SMMU_SIZE_A01 - 1;
597 }
598 smmu_window_size = smmu_window->end + 1 - smmu_window->start;
599 if (smmu_window->start >= 0x80000000) {
600 if (memblock_reserve(smmu_window->start,
601 smmu_window_size))
602 pr_err(
603 "Failed to reserve SMMU I/O VA window %08lx@%08lx\n",
Hiro Sugawara0d218182011-04-08 13:21:02 -0700604 (unsigned long)smmu_window_size,
605 (unsigned long)smmu_window->start);
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -0700606 else
607 smmu_reserved = 1;
608 }
Scott Williams599c1122011-02-10 14:35:32 -0800609 }
610#endif
611
Colin Cross838d7d62010-10-19 14:45:50 -0700612 /*
613 * TODO: We should copy the bootloader's framebuffer to the framebuffer
614 * allocated above, and then free this one.
615 */
616 if (tegra_bootloader_fb_size)
617 if (memblock_reserve(tegra_bootloader_fb_start,
Scott Williams03122532011-01-13 14:30:20 -0800618 tegra_bootloader_fb_size)) {
619 pr_err("Failed to reserve bootloader frame buffer %08lx@%08lx\n",
620 tegra_bootloader_fb_size, tegra_bootloader_fb_start);
621 tegra_bootloader_fb_start = 0;
622 tegra_bootloader_fb_size = 0;
623 }
Colin Cross838d7d62010-10-19 14:45:50 -0700624
625 pr_info("Tegra reserved memory:\n"
626 "LP0: %08lx - %08lx\n"
627 "Bootloader framebuffer: %08lx - %08lx\n"
628 "Framebuffer: %08lx - %08lx\n"
Scott Williams22d51692011-01-11 10:50:52 -0800629 "2nd Framebuffer: %08lx - %08lx\n"
Colin Cross838d7d62010-10-19 14:45:50 -0700630 "Carveout: %08lx - %08lx\n",
631 tegra_lp0_vec_start,
Scott Williams03122532011-01-13 14:30:20 -0800632 tegra_lp0_vec_size ?
633 tegra_lp0_vec_start + tegra_lp0_vec_size - 1 : 0,
Colin Cross838d7d62010-10-19 14:45:50 -0700634 tegra_bootloader_fb_start,
Scott Williams03122532011-01-13 14:30:20 -0800635 tegra_bootloader_fb_size ?
636 tegra_bootloader_fb_start + tegra_bootloader_fb_size - 1 : 0,
Colin Cross838d7d62010-10-19 14:45:50 -0700637 tegra_fb_start,
Scott Williams03122532011-01-13 14:30:20 -0800638 tegra_fb_size ?
639 tegra_fb_start + tegra_fb_size - 1 : 0,
Colin Cross838d7d62010-10-19 14:45:50 -0700640 tegra_fb2_start,
Scott Williams03122532011-01-13 14:30:20 -0800641 tegra_fb2_size ?
642 tegra_fb2_start + tegra_fb2_size - 1 : 0,
Colin Cross838d7d62010-10-19 14:45:50 -0700643 tegra_carveout_start,
Scott Williams03122532011-01-13 14:30:20 -0800644 tegra_carveout_size ?
645 tegra_carveout_start + tegra_carveout_size - 1 : 0);
Scott Williams599c1122011-02-10 14:35:32 -0800646
Hiro Sugawarad5ea29e2011-03-17 11:19:29 -0700647#ifdef SUPPORT_TEGRA_3_IOVMM_SMMU_A01
648 if (smmu_reserved)
649 pr_info("SMMU: %08x - %08x\n",
650 smmu_window->start, smmu_window->end);
Scott Williams599c1122011-02-10 14:35:32 -0800651#endif
Colin Cross838d7d62010-10-19 14:45:50 -0700652}