2 * arch/arm/mach-tegra/common.c
4 * Copyright (C) 2010 Google, Inc.
7 * Colin Cross <ccross@android.com>
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.
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.
20 #include <linux/console.h>
21 #include <linux/init.h>
23 #include <linux/clk.h>
24 #include <linux/delay.h>
25 #include <linux/highmem.h>
26 #include <linux/memblock.h>
28 #include <asm/hardware/cache-l2x0.h>
29 #include <asm/system.h>
31 #include <mach/iomap.h>
33 #include <mach/powergate.h>
34 #include <mach/system.h>
40 #define MC_SECURITY_CFG2 0x7c
42 unsigned long tegra_bootloader_fb_start;
43 unsigned long tegra_bootloader_fb_size;
44 unsigned long tegra_fb_start;
45 unsigned long tegra_fb_size;
46 unsigned long tegra_fb2_start;
47 unsigned long tegra_fb2_size;
48 unsigned long tegra_carveout_start;
49 unsigned long tegra_carveout_size;
50 unsigned long tegra_lp0_vec_start;
51 unsigned long tegra_lp0_vec_size;
52 unsigned long tegra_grhost_aperture;
54 void (*tegra_reset)(char mode, const char *cmd);
56 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
57 /* set up clocks that should always be on */
58 /* name parent rate enabled */
59 { "clk_m", NULL, 0, true },
60 { "pll_p", "clk_m", 216000000, true },
61 { "pll_p_out1", "pll_p", 28800000, true },
62 { "pll_p_out2", "pll_p", 48000000, true },
63 { "pll_p_out3", "pll_p", 72000000, true },
64 { "pll_m_out1", "pll_m", 120000000, true },
65 { "sclk", "pll_m_out1", 120000000, true },
66 { "hclk", "sclk", 120000000, true },
67 { "pclk", "hclk", 60000000, true },
68 { "pll_x", NULL, 0, true },
69 { "cpu", NULL, 0, true },
70 { "emc", NULL, 0, true },
71 { "csite", NULL, 0, true },
72 { "timer", NULL, 0, true },
73 { "rtc", NULL, 0, true },
75 /* set frequencies of some device clocks */
76 { "pll_u", "clk_m", 480000000, false },
77 { "sdmmc1", "pll_p", 48000000, false},
78 { "sdmmc2", "pll_p", 48000000, false},
79 { "sdmmc3", "pll_p", 48000000, false},
80 { "sdmmc4", "pll_p", 48000000, false},
84 void __init tegra_init_cache(void)
86 #ifdef CONFIG_CACHE_L2X0
87 void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
89 writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
90 writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
92 l2x0_init(p, 0x6C480001, 0x8200c3fe);
97 static void __init tegra_init_power(void)
99 tegra_powergate_power_off(TEGRA_POWERGATE_MPE);
100 tegra_powergate_power_off(TEGRA_POWERGATE_3D);
103 static bool console_flushed;
105 static void tegra_pm_flush_console(void)
109 console_flushed = true;
112 pr_emerg("Restarting %s\n", linux_banner);
113 if (!try_acquire_console_sem()) {
114 release_console_sem();
121 if (try_acquire_console_sem())
122 pr_emerg("tegra_restart: Console was locked! Busting\n");
124 pr_emerg("tegra_restart: Console was locked!\n");
125 release_console_sem();
128 static void tegra_pm_restart(char mode, const char *cmd)
130 tegra_pm_flush_console();
131 arm_machine_restart(mode, cmd);
134 void __init tegra_common_init(void)
136 arm_pm_restart = tegra_pm_restart;
140 tegra_clk_init_from_table(common_clk_init_table);
143 #ifdef CONFIG_TEGRA_SYSTEM_DMA
148 static int __init tegra_bootloader_fb_arg(char *options)
152 tegra_bootloader_fb_size = memparse(p, &p);
154 tegra_bootloader_fb_start = memparse(p+1, &p);
156 pr_info("Found tegra_fbmem: %08lx@%08lx\n",
157 tegra_bootloader_fb_size, tegra_bootloader_fb_start);
161 early_param("tegra_fbmem", tegra_bootloader_fb_arg);
163 static int __init tegra_lp0_vec_arg(char *options)
167 tegra_lp0_vec_size = memparse(p, &p);
169 tegra_lp0_vec_start = memparse(p+1, &p);
173 early_param("lp0_vec", tegra_lp0_vec_arg);
176 * Tegra has a protected aperture that prevents access by most non-CPU
177 * memory masters to addresses above the aperture value. Enabling it
178 * secures the CPU's memory from the GPU, except through the GART.
180 void __init tegra_protected_aperture_init(unsigned long aperture)
182 #ifndef CONFIG_NVMAP_ALLOW_SYSMEM
183 void __iomem *mc_base = IO_ADDRESS(TEGRA_MC_BASE);
184 pr_info("Enabling Tegra protected aperture at 0x%08lx\n", aperture);
185 writel(aperture, mc_base + MC_SECURITY_CFG2);
187 pr_err("Tegra protected aperture disabled because nvmap is using "
193 * Due to conflicting restrictions on the placement of the framebuffer,
194 * the bootloader is likely to leave the framebuffer pointed at a location
195 * in memory that is outside the grhost aperture. This function will move
196 * the framebuffer contents from a physical address that is anywher (lowmem,
197 * highmem, or outside the memory map) to a physical address that is outside
200 void tegra_move_framebuffer(unsigned long to, unsigned long from,
208 BUG_ON(PAGE_ALIGN((unsigned long)to) != (unsigned long)to);
209 BUG_ON(PAGE_ALIGN(from) != from);
210 BUG_ON(PAGE_ALIGN(size) != size);
212 to_io = ioremap(to, size);
214 pr_err("%s: Failed to map target framebuffer\n", __func__);
218 if (pfn_valid(page_to_pfn(phys_to_page(from)))) {
219 for (i = 0 ; i < size; i += PAGE_SIZE) {
220 page = phys_to_page(from + i);
221 from_virt = kmap(page);
222 memcpy_toio(to_io + i, from_virt, PAGE_SIZE);
226 void __iomem *from_io = ioremap(from, size);
228 pr_err("%s: Failed to map source framebuffer\n",
233 for (i = 0; i < size; i+= 4)
234 writel(readl(from_io + i), to_io + i);
242 void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
243 unsigned long fb2_size)
245 if (tegra_lp0_vec_size)
246 if (memblock_reserve(tegra_lp0_vec_start, tegra_lp0_vec_size))
247 pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
248 tegra_lp0_vec_size, tegra_lp0_vec_start);
251 tegra_carveout_start = memblock_end_of_DRAM() - carveout_size;
252 if (memblock_remove(tegra_carveout_start, carveout_size))
253 pr_err("Failed to remove carveout %08lx@%08lx from memory "
255 tegra_carveout_start, carveout_size);
257 tegra_carveout_size = carveout_size;
259 tegra_fb2_start = memblock_end_of_DRAM() - fb2_size;
260 if (memblock_remove(tegra_fb2_start, fb2_size))
261 pr_err("Failed to remove second framebuffer %08lx@%08lx from "
263 tegra_fb2_start, fb2_size);
265 tegra_fb2_size = fb2_size;
267 tegra_fb_start = memblock_end_of_DRAM() - fb_size;
268 if (memblock_remove(tegra_fb_start, fb_size))
269 pr_err("Failed to remove framebuffer %08lx@%08lx from memory "
271 tegra_fb_start, fb_size);
273 tegra_fb_size = fb_size;
276 tegra_grhost_aperture = tegra_fb_start;
278 if (tegra_fb2_size && tegra_fb2_start < tegra_grhost_aperture)
279 tegra_grhost_aperture = tegra_fb2_start;
281 if (tegra_carveout_size && tegra_carveout_start < tegra_grhost_aperture)
282 tegra_grhost_aperture = tegra_carveout_start;
285 * TODO: We should copy the bootloader's framebuffer to the framebuffer
286 * allocated above, and then free this one.
288 if (tegra_bootloader_fb_size)
289 if (memblock_reserve(tegra_bootloader_fb_start,
290 tegra_bootloader_fb_size))
291 pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
292 tegra_lp0_vec_size, tegra_lp0_vec_start);
294 pr_info("Tegra reserved memory:\n"
295 "LP0: %08lx - %08lx\n"
296 "Bootloader framebuffer: %08lx - %08lx\n"
297 "Framebuffer: %08lx - %08lx\n"
298 "2nd Framebuffer: %08lx - %08lx\n"
299 "Carveout: %08lx - %08lx\n",
301 tegra_lp0_vec_start + tegra_lp0_vec_size - 1,
302 tegra_bootloader_fb_start,
303 tegra_bootloader_fb_start + tegra_bootloader_fb_size - 1,
305 tegra_fb_start + tegra_fb_size - 1,
307 tegra_fb2_start + tegra_fb2_size - 1,
308 tegra_carveout_start,
309 tegra_carveout_start + tegra_carveout_size - 1);