12ce86b7ab9c7438bb6c2c479fc5056f2cc5f5ba
[firefly-linux-kernel-4.4.55.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/iomap.h>
32 #include <mach/dma.h>
33 #include <mach/powergate.h>
34 #include <mach/system.h>
35
36 #include "board.h"
37 #include "clock.h"
38 #include "fuse.h"
39
40 #define MC_SECURITY_CFG2 0x7c
41
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;
53
54 void (*tegra_reset)(char mode, const char *cmd);
55
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 },
74
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},
81         { NULL,         NULL,           0,              0},
82 };
83
84 void __init tegra_init_cache(void)
85 {
86 #ifdef CONFIG_CACHE_L2X0
87         void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
88
89         writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
90         writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
91
92         l2x0_init(p, 0x6C480001, 0x8200c3fe);
93 #endif
94
95 }
96
97 static void __init tegra_init_power(void)
98 {
99         tegra_powergate_power_off(TEGRA_POWERGATE_MPE);
100         tegra_powergate_power_off(TEGRA_POWERGATE_3D);
101 }
102
103 static bool console_flushed;
104
105 static void tegra_pm_flush_console(void)
106 {
107         if (console_flushed)
108                 return;
109         console_flushed = true;
110
111         printk("\n");
112         pr_emerg("Restarting %s\n", linux_banner);
113         if (!try_acquire_console_sem()) {
114                 release_console_sem();
115                 return;
116         }
117
118         mdelay(50);
119
120         local_irq_disable();
121         if (try_acquire_console_sem())
122                 pr_emerg("tegra_restart: Console was locked! Busting\n");
123         else
124                 pr_emerg("tegra_restart: Console was locked!\n");
125         release_console_sem();
126 }
127
128 static void tegra_pm_restart(char mode, const char *cmd)
129 {
130         tegra_pm_flush_console();
131         arm_machine_restart(mode, cmd);
132 }
133
134 void __init tegra_common_init(void)
135 {
136         arm_pm_restart = tegra_pm_restart;
137
138         tegra_init_fuse();
139         tegra_init_clock();
140         tegra_clk_init_from_table(common_clk_init_table);
141         tegra_init_power();
142         tegra_init_cache();
143 #ifdef CONFIG_TEGRA_SYSTEM_DMA
144         tegra_dma_init();
145 #endif
146 }
147
148 static int __init tegra_bootloader_fb_arg(char *options)
149 {
150         char *p = options;
151
152         tegra_bootloader_fb_size = memparse(p, &p);
153         if (*p == '@')
154                 tegra_bootloader_fb_start = memparse(p+1, &p);
155
156         pr_info("Found tegra_fbmem: %08lx@%08lx\n",
157                 tegra_bootloader_fb_size, tegra_bootloader_fb_start);
158
159         return 0;
160 }
161 early_param("tegra_fbmem", tegra_bootloader_fb_arg);
162
163 static int __init tegra_lp0_vec_arg(char *options)
164 {
165         char *p = options;
166
167         tegra_lp0_vec_size = memparse(p, &p);
168         if (*p == '@')
169                 tegra_lp0_vec_start = memparse(p+1, &p);
170
171         return 0;
172 }
173 early_param("lp0_vec", tegra_lp0_vec_arg);
174
175 /*
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.
179  */
180 void __init tegra_protected_aperture_init(unsigned long aperture)
181 {
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);
186 #else
187         pr_err("Tegra protected aperture disabled because nvmap is using "
188                 "system memory\n");
189 #endif
190 }
191
192 /*
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
198  * the memory map.
199  */
200 void tegra_move_framebuffer(unsigned long to, unsigned long from,
201         unsigned long size)
202 {
203         struct page *page;
204         void __iomem *to_io;
205         void *from_virt;
206         unsigned long i;
207
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);
211
212         to_io = ioremap(to, size);
213         if (!to_io) {
214                 pr_err("%s: Failed to map target framebuffer\n", __func__);
215                 return;
216         }
217
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);
223                         kunmap(page);
224                 }
225         } else {
226                 void __iomem *from_io = ioremap(from, size);
227                 if (!from_io) {
228                         pr_err("%s: Failed to map source framebuffer\n",
229                                 __func__);
230                         goto out;
231                 }
232
233                 for (i = 0; i < size; i+= 4)
234                         writel(readl(from_io + i), to_io + i);
235
236                 iounmap(from_io);
237         }
238 out:
239         iounmap(to_io);
240 }
241
242 void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
243         unsigned long fb2_size)
244 {
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);
249
250
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 "
254                         "map\n",
255                         tegra_carveout_start, carveout_size);
256         else
257                 tegra_carveout_size = carveout_size;
258
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 "
262                         "memory map\n",
263                         tegra_fb2_start, fb2_size);
264         else
265                 tegra_fb2_size = fb2_size;
266
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 "
270                         "map\n",
271                         tegra_fb_start, fb_size);
272         else
273                 tegra_fb_size = fb_size;
274
275         if (tegra_fb_size)
276                 tegra_grhost_aperture = tegra_fb_start;
277
278         if (tegra_fb2_size && tegra_fb2_start < tegra_grhost_aperture)
279                 tegra_grhost_aperture = tegra_fb2_start;
280
281         if (tegra_carveout_size && tegra_carveout_start < tegra_grhost_aperture)
282                 tegra_grhost_aperture = tegra_carveout_start;
283
284         /*
285          * TODO: We should copy the bootloader's framebuffer to the framebuffer
286          * allocated above, and then free this one.
287          */
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);
293
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",
300                 tegra_lp0_vec_start,
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,
304                 tegra_fb_start,
305                 tegra_fb_start + tegra_fb_size - 1,
306                 tegra_fb2_start,
307                 tegra_fb2_start + tegra_fb2_size - 1,
308                 tegra_carveout_start,
309                 tegra_carveout_start + tegra_carveout_size - 1);
310 }