[ARM/tegra] Add Tegra3 support
[linux-2.6.git] / arch / arm / mach-tegra / common.c
1 /*
2  * arch/arm/mach-tegra/common.c
3  *
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
20 #include <linux/console.h>
21 #include <linux/init.h>
22 #include <linux/io.h>
23 #include <linux/clk.h>
24 #include <linux/delay.h>
25 #include <linux/highmem.h>
26 #include <linux/memblock.h>
27
28 #include <asm/hardware/cache-l2x0.h>
29 #include <asm/system.h>
30
31 #include <mach/gpio.h>
32 #include <mach/iomap.h>
33 #include <mach/pinmux.h>
34 #include <mach/powergate.h>
35 #include <mach/system.h>
36
37 #include "apbio.h"
38 #include "board.h"
39 #include "clock.h"
40 #include "fuse.h"
41 #include "pm.h"
42
43 #define MC_SECURITY_CFG2        0x7c
44
45 unsigned long tegra_bootloader_fb_start;
46 unsigned long tegra_bootloader_fb_size;
47 unsigned long tegra_fb_start;
48 unsigned long tegra_fb_size;
49 unsigned long tegra_fb2_start;
50 unsigned long tegra_fb2_size;
51 unsigned long tegra_carveout_start;
52 unsigned long tegra_carveout_size;
53 unsigned long tegra_lp0_vec_start;
54 unsigned long tegra_lp0_vec_size;
55 unsigned long tegra_grhost_aperture;
56 static   bool is_tegra_debug_uart_hsport;
57
58 void (*arch_reset)(char mode, const char *cmd) = tegra_assert_system_reset;
59
60 void tegra_assert_system_reset(char mode, const char *cmd)
61 {
62         void __iomem *reset = IO_ADDRESS(TEGRA_PMC_BASE + 0x00);
63         u32 reg;
64
65         /* use *_related to avoid spinlock since caches are off */
66         reg = readl_relaxed(reset);
67         reg |= 0x10;
68         writel_relaxed(reg, reset);
69 }
70
71 static struct board_info tegra_board_info = {
72         .board_id = -1,
73         .sku = -1,
74         .fab = -1,
75         .major_revision = -1,
76         .minor_revision = -1,
77 };
78
79 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
80         /* name         parent          rate            enabled */
81         { "clk_m",      NULL,           0,              true },
82         { "pll_m",      "clk_m",        600000000,      true },
83         { "pll_p",      NULL,           216000000,      true },
84         { "pll_p_out1", "pll_p",        28800000,       true },
85         { "pll_p_out2", "pll_p",        48000000,       true },
86         { "pll_p_out3", "pll_p",        72000000,       true },
87         { "pll_p_out4", "pll_p",        108000000,      true },
88         { "pll_m_out1", "pll_m",        120000000,      true },
89         { "sclk",       "pll_m_out1",   120000000,      true },
90         { "hclk",       "sclk",         120000000,      true },
91         { "pclk",       "hclk",         60000000,       true },
92         { "csite",      NULL,           0,              true },
93         { "emc",        NULL,           0,              true },
94         { "cpu",        NULL,           0,              true },
95         { "kfuse",      NULL,           0,              true },
96         { "pll_u",      NULL,           480000000,      false },
97         { "sdmmc1",     "pll_p",        48000000,       false},
98         { "sdmmc2",     "pll_p",        48000000,       false},
99         { "sdmmc3",     "pll_p",        48000000,       false},
100         { "sdmmc4",     "pll_p",        48000000,       false},
101         { NULL,         NULL,           0,              0},
102 };
103
104 void tegra_init_cache(void)
105 {
106 #ifdef CONFIG_CACHE_L2X0
107         void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
108
109 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
110         writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL);
111         writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL);
112
113 #elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
114 #ifdef CONFIG_TEGRA_FPGA_PLATFORM
115         writel(0x770, p + L2X0_TAG_LATENCY_CTRL);
116         writel(0x770, p + L2X0_DATA_LATENCY_CTRL);
117         {
118                 void __iomem *misc = IO_ADDRESS(TEGRA_APB_MISC_BASE);
119                 u32 val = readl(misc + APB_MISC_HIDREV);
120                 u32 major = (val>>4) & 0xf;
121                 u32 netlist = readl(misc + 0x860);
122
123                 if ((major == 0) && ((netlist & 0xFFFF) >= 12)) {
124                         /* Enable PL310 double line fill feature. */
125                         writel(((1<<30) | 7), p + L2X0_PREFETCH_CTRL);
126                 } else {
127                         writel(7, p + L2X0_PREFETCH_CTRL);
128                 }
129         }
130 #else
131         /* FIXME: Need characterized timing parameters for real silicon */
132         writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
133         writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
134         writel(7, p + L2X0_PREFETCH_CTRL);
135         writel(2, p + L2X0_PWR_CTRL);
136 #endif
137
138         /* Enable PL310 double line fill feature. */
139         writel(((1<<30) | 7), p + L2X0_PREFETCH_CTRL);
140 #endif
141         l2x0_init(p, 0x6C480001, 0x8200c3fe);
142 #endif
143
144 }
145
146 static void __init tegra_init_power(void)
147 {
148         tegra_powergate_power_off(TEGRA_POWERGATE_MPE);
149         tegra_powergate_power_off(TEGRA_POWERGATE_3D);
150         tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
151 }
152
153 static bool console_flushed;
154
155 static void tegra_pm_flush_console(void)
156 {
157         if (console_flushed)
158                 return;
159         console_flushed = true;
160
161         printk("\n");
162         pr_emerg("Restarting %s\n", linux_banner);
163         if (console_trylock()) {
164                 console_unlock();
165                 return;
166         }
167
168         mdelay(50);
169
170         local_irq_disable();
171         if (!console_trylock())
172                 pr_emerg("tegra_restart: Console was locked! Busting\n");
173         else
174                 pr_emerg("tegra_restart: Console was locked!\n");
175         console_unlock();
176 }
177
178 static void tegra_pm_restart(char mode, const char *cmd)
179 {
180         tegra_pm_flush_console();
181         arm_machine_restart(mode, cmd);
182 }
183
184 void __init tegra_init_early(void)
185 {
186         arm_pm_restart = tegra_pm_restart;
187         tegra_init_fuse();
188         tegra_gpio_resume_init();
189         tegra_init_clock();
190         tegra_init_pinmux();
191         tegra_clk_init_from_table(common_clk_init_table);
192         tegra_init_power();
193         tegra_init_cache();
194 }
195
196 static int __init tegra_lp0_vec_arg(char *options)
197 {
198         char *p = options;
199
200         tegra_lp0_vec_size = memparse(p, &p);
201         if (*p == '@')
202                 tegra_lp0_vec_start = memparse(p+1, &p);
203
204         return 0;
205 }
206 early_param("lp0_vec", tegra_lp0_vec_arg);
207
208 static int __init tegra_bootloader_fb_arg(char *options)
209 {
210         char *p = options;
211
212         tegra_bootloader_fb_size = memparse(p, &p);
213         if (*p == '@')
214                 tegra_bootloader_fb_start = memparse(p+1, &p);
215
216         pr_info("Found tegra_fbmem: %08lx@%08lx\n",
217                 tegra_bootloader_fb_size, tegra_bootloader_fb_start);
218
219         return 0;
220 }
221 early_param("tegra_fbmem", tegra_bootloader_fb_arg);
222
223 static int __init tegra_board_info_parse(char *info)
224 {
225         char *p;
226         int pos = 0;
227         struct board_info *bi = &tegra_board_info;
228
229         while (info && *info) {
230                 if ((p = strchr(info, ':')))
231                         *p++ = '\0';
232
233                 if (strlen(info) > 0) {
234                         switch(pos) {
235                         case 0:
236                                 bi->board_id = simple_strtol(info, NULL, 16);
237                                 break;
238                         case 1:
239                                 bi->sku = simple_strtol(info, NULL, 16);
240                                 break;
241                         case 2:
242                                 bi->fab = simple_strtol(info, NULL, 16);
243                                 break;
244                         case 3:
245                                 bi->major_revision = simple_strtol(info, NULL, 16);
246                                 break;
247                         case 4:
248                                 bi->minor_revision = simple_strtol(info, NULL, 16);
249                                 break;
250                         default:
251                                 break;
252                         }
253                 }
254
255                 info = p;
256                 pos++;
257         }
258
259         pr_info("board info: Id:%d%2d SKU:%d Fab:%d Rev:%c MinRev:%d\n",
260                         bi->board_id >> 8 & 0xFF, bi->board_id & 0xFF,
261                         bi->sku, bi->fab, bi->major_revision, bi->minor_revision);
262
263         return 1;
264 }
265
266 __setup("board_info=", tegra_board_info_parse);
267
268 static int __init tegra_debug_uartport(char *info)
269 {
270         if (!strcmp(info, "hsport"))
271                 is_tegra_debug_uart_hsport = true;
272         else if (!strcmp(info, "lsport"))
273                 is_tegra_debug_uart_hsport = false;
274
275         return 1;
276 }
277
278 bool is_tegra_debug_uartport_hs(void)
279 {
280         return is_tegra_debug_uart_hsport;
281 }
282
283 __setup("debug_uartport=", tegra_debug_uartport);
284
285 void tegra_get_board_info(struct board_info *bi)
286 {
287         memcpy(bi, &tegra_board_info, sizeof(*bi));
288 }
289
290 /*
291  * Tegra has a protected aperture that prevents access by most non-CPU
292  * memory masters to addresses above the aperture value.  Enabling it
293  * secures the CPU's memory from the GPU, except through the GART.
294  */
295 void __init tegra_protected_aperture_init(unsigned long aperture)
296 {
297 #ifndef CONFIG_NVMAP_ALLOW_SYSMEM
298         void __iomem *mc_base = IO_ADDRESS(TEGRA_MC_BASE);
299         pr_info("Enabling Tegra protected aperture at 0x%08lx\n", aperture);
300         writel(aperture, mc_base + MC_SECURITY_CFG2);
301 #else
302         pr_err("Tegra protected aperture disabled because nvmap is using "
303                 "system memory\n");
304 #endif
305 }
306
307 /*
308  * Due to conflicting restrictions on the placement of the framebuffer,
309  * the bootloader is likely to leave the framebuffer pointed at a location
310  * in memory that is outside the grhost aperture.  This function will move
311  * the framebuffer contents from a physical address that is anywher (lowmem,
312  * highmem, or outside the memory map) to a physical address that is outside
313  * the memory map.
314  */
315 void tegra_move_framebuffer(unsigned long to, unsigned long from,
316         unsigned long size)
317 {
318         struct page *page;
319         void __iomem *to_io;
320         void *from_virt;
321         unsigned long i;
322
323         BUG_ON(PAGE_ALIGN((unsigned long)to) != (unsigned long)to);
324         BUG_ON(PAGE_ALIGN(from) != from);
325         BUG_ON(PAGE_ALIGN(size) != size);
326
327         to_io = ioremap(to, size);
328         if (!to_io) {
329                 pr_err("%s: Failed to map target framebuffer\n", __func__);
330                 return;
331         }
332
333         if (pfn_valid(page_to_pfn(phys_to_page(from)))) {
334                 for (i = 0 ; i < size; i += PAGE_SIZE) {
335                         page = phys_to_page(from + i);
336                         from_virt = kmap(page);
337                         memcpy_toio(to_io + i, from_virt, PAGE_SIZE);
338                         kunmap(page);
339                 }
340         } else {
341                 void __iomem *from_io = ioremap(from, size);
342                 if (!from_io) {
343                         pr_err("%s: Failed to map source framebuffer\n",
344                                 __func__);
345                         goto out;
346                 }
347
348                 for (i = 0; i < size; i+= 4)
349                         writel(readl(from_io + i), to_io + i);
350
351                 iounmap(from_io);
352         }
353 out:
354         iounmap(to_io);
355 }
356
357 void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
358         unsigned long fb2_size)
359 {
360         if (tegra_lp0_vec_size)
361                 if (memblock_reserve(tegra_lp0_vec_start, tegra_lp0_vec_size))
362                         pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
363                                 tegra_lp0_vec_size, tegra_lp0_vec_start);
364
365
366         tegra_carveout_start = memblock_end_of_DRAM() - carveout_size;
367         if (memblock_remove(tegra_carveout_start, carveout_size))
368                 pr_err("Failed to remove carveout %08lx@%08lx from memory "
369                         "map\n",
370                         tegra_carveout_start, carveout_size);
371         else
372                 tegra_carveout_size = carveout_size;
373
374         tegra_fb2_start = memblock_end_of_DRAM() - fb2_size;
375         if (memblock_remove(tegra_fb2_start, fb2_size))
376                 pr_err("Failed to remove second framebuffer %08lx@%08lx from "
377                         "memory map\n",
378                         tegra_fb2_start, fb2_size);
379         else
380                 tegra_fb2_size = fb2_size;
381
382         tegra_fb_start = memblock_end_of_DRAM() - fb_size;
383         if (memblock_remove(tegra_fb_start, fb_size))
384                 pr_err("Failed to remove framebuffer %08lx@%08lx from memory "
385                         "map\n",
386                         tegra_fb_start, fb_size);
387         else
388                 tegra_fb_size = fb_size;
389
390         if (tegra_fb_size)
391                 tegra_grhost_aperture = tegra_fb_start;
392
393         if (tegra_fb2_size && tegra_fb2_start < tegra_grhost_aperture)
394                 tegra_grhost_aperture = tegra_fb2_start;
395
396         if (tegra_carveout_size && tegra_carveout_start < tegra_grhost_aperture)
397                 tegra_grhost_aperture = tegra_carveout_start;
398
399         /*
400          * TODO: We should copy the bootloader's framebuffer to the framebuffer
401          * allocated above, and then free this one.
402          */
403         if (tegra_bootloader_fb_size)
404                 if (memblock_reserve(tegra_bootloader_fb_start,
405                                 tegra_bootloader_fb_size))
406                         pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
407                                 tegra_lp0_vec_size, tegra_lp0_vec_start);
408
409         pr_info("Tegra reserved memory:\n"
410                 "LP0:                    %08lx - %08lx\n"
411                 "Bootloader framebuffer: %08lx - %08lx\n"
412                 "Framebuffer:            %08lx - %08lx\n"
413                 "2nd Framebuffer:         %08lx - %08lx\n"
414                 "Carveout:               %08lx - %08lx\n",
415                 tegra_lp0_vec_start,
416                 tegra_lp0_vec_start + tegra_lp0_vec_size - 1,
417                 tegra_bootloader_fb_start,
418                 tegra_bootloader_fb_start + tegra_bootloader_fb_size - 1,
419                 tegra_fb_start,
420                 tegra_fb_start + tegra_fb_size - 1,
421                 tegra_fb2_start,
422                 tegra_fb2_start + tegra_fb2_size - 1,
423                 tegra_carveout_start,
424                 tegra_carveout_start + tegra_carveout_size - 1);
425 }