[ARM] tegra: Use memblock_remove to allocate carveout and framebuffer
authorColin Cross <ccross@android.com>
Tue, 19 Oct 2010 21:45:50 +0000 (14:45 -0700)
committerColin Cross <ccross@android.com>
Wed, 20 Oct 2010 21:30:17 +0000 (14:30 -0700)
This uses the patch by rmk to allow memblock_remove to be used to
remove areas of memory from the 1:1 mapping, allowing them to be
remapped later using iomap or, for Tegra, nvmap.

Also uses memblock_reserve to reserve the lp0 boot vector, so it
doesn't need to be copied later in tegra_init_suspend.

tegra_reserve should be called from the machine reserve callback
after any board-specific memory areas are reserved.

Change-Id: I26be8544a03b6da74fe66dc53a77681d431c303c
Signed-off-by: Colin Cross <ccross@android.com>
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/suspend.c

index 3d06354136f2663ff2f80cdbfa9b441671dc4146..120b452bcda99a5a87e21a13f494abb4bb5e55c7 100644 (file)
@@ -27,6 +27,19 @@ void __init tegra_common_init(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_init_clock(void);
+void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
+       unsigned long fb2_size);
+
+extern unsigned long tegra_bootloader_fb_start;
+extern unsigned long tegra_bootloader_fb_size;
+extern unsigned long tegra_fb_start;
+extern unsigned long tegra_fb_size;
+extern unsigned long tegra_fb2_start;
+extern unsigned long tegra_fb2_size;
+extern unsigned long tegra_carveout_start;
+extern unsigned long tegra_carveout_size;
+extern unsigned long tegra_lp0_vec_start;
+extern unsigned long tegra_lp0_vec_size;
 
 extern struct sys_timer tegra_timer;
 #endif
index 99eb45eb30c3eb0d1da22a706c7442b8669ce7e0..d212e78a0360858d8b6aa119b41c12a7c2031924 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/memblock.h>
 
 #include <asm/hardware/cache-l2x0.h>
 
 #include "clock.h"
 #include "fuse.h"
 
+unsigned long tegra_bootloader_fb_start;
+unsigned long tegra_bootloader_fb_size;
+unsigned long tegra_fb_start;
+unsigned long tegra_fb_size;
+unsigned long tegra_fb2_start;
+unsigned long tegra_fb2_size;
+unsigned long tegra_carveout_start;
+unsigned long tegra_carveout_size;
+unsigned long tegra_lp0_vec_start;
+unsigned long tegra_lp0_vec_size;
+
 void (*tegra_reset)(char mode, const char *cmd);
 
 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
@@ -84,3 +96,91 @@ void __init tegra_common_init(void)
        tegra_dma_init();
 #endif
 }
+
+static int __init tegra_bootloader_fb_arg(char *options)
+{
+       char *p = options;
+
+       tegra_bootloader_fb_size = memparse(p, &p);
+       if (*p == '@')
+               tegra_bootloader_fb_start = memparse(p+1, &p);
+
+       pr_info("Found tegra_fbmem: %08lx@%08lx\n",
+               tegra_bootloader_fb_size, tegra_bootloader_fb_start);
+
+       return 0;
+}
+early_param("tegra_fbmem", tegra_bootloader_fb_arg);
+
+static int __init tegra_lp0_vec_arg(char *options)
+{
+       char *p = options;
+
+       tegra_lp0_vec_size = memparse(p, &p);
+       if (*p == '@')
+               tegra_lp0_vec_start = memparse(p+1, &p);
+
+       return 0;
+}
+early_param("lp0_vec", tegra_lp0_vec_arg);
+
+void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
+       unsigned long fb2_size)
+{
+       if (tegra_lp0_vec_size)
+               if (memblock_reserve(tegra_lp0_vec_start, tegra_lp0_vec_size))
+                       pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
+                               tegra_lp0_vec_size, tegra_lp0_vec_start);
+
+
+       tegra_carveout_start = memblock_end_of_DRAM() - carveout_size;
+       if (memblock_remove(tegra_carveout_start, carveout_size))
+               pr_err("Failed to remove carveout %08lx@%08lx from memory "
+                       "map\n",
+                       tegra_carveout_start, carveout_size);
+       else
+               tegra_carveout_size = carveout_size;
+
+       tegra_fb2_start = memblock_end_of_DRAM() - fb2_size;
+       if (memblock_remove(tegra_fb2_start, fb2_size))
+               pr_err("Failed to remove second framebuffer %08lx@%08lx from "
+                       "memory map\n",
+                       tegra_fb2_start, fb2_size);
+       else
+               tegra_fb2_size = fb2_size;
+
+       tegra_fb_start = memblock_end_of_DRAM() - fb_size;
+       if (memblock_remove(tegra_fb_start, fb_size))
+               pr_err("Failed to remove framebuffer %08lx@%08lx from memory "
+                       "map\n",
+                       tegra_fb_start, fb_size);
+       else
+               tegra_fb_size = fb_size;
+
+       /*
+        * TODO: We should copy the bootloader's framebuffer to the framebuffer
+        * allocated above, and then free this one.
+        */
+       if (tegra_bootloader_fb_size)
+               if (memblock_reserve(tegra_bootloader_fb_start,
+                               tegra_bootloader_fb_size))
+                       pr_err("Failed to reserve lp0_vec %08lx@%08lx\n",
+                               tegra_lp0_vec_size, tegra_lp0_vec_start);
+
+       pr_info("Tegra reserved memory:\n"
+               "LP0:                    %08lx - %08lx\n"
+               "Bootloader framebuffer: %08lx - %08lx\n"
+               "Framebuffer:            %08lx - %08lx\n"
+               "2nd Framebuffer:         %08lx - %08lx\n"
+               "Carveout:               %08lx - %08lx\n",
+               tegra_lp0_vec_start,
+               tegra_lp0_vec_start + tegra_lp0_vec_size - 1,
+               tegra_bootloader_fb_start,
+               tegra_bootloader_fb_start + tegra_bootloader_fb_size - 1,
+               tegra_fb_start,
+               tegra_fb_start + tegra_fb_size - 1,
+               tegra_fb2_start,
+               tegra_fb2_start + tegra_fb2_size - 1,
+               tegra_carveout_start,
+               tegra_carveout_start + tegra_carveout_size - 1);
+}
index b46d1bfff9b52fa972f32e7422da3335bccc6e3d..c7be121ea8d15bcf736a82e1966ef338ae2bc19c 100644 (file)
@@ -49,6 +49,7 @@
 #include <mach/legacy_irq.h>
 #include <mach/suspend.h>
 
+#include "board.h"
 #include "power.h"
 
 /* NOTE: only add elements to the end of this structure, since the assembly
@@ -543,21 +544,6 @@ static struct platform_suspend_ops tegra_suspend_ops = {
 };
 #endif
 
-static unsigned long lp0_vec_orig_start = 0;
-static unsigned long lp0_vec_orig_size = 0;
-
-static int __init tegra_lp0_vec_arg(char *options)
-{
-       char *p = options;
-
-       lp0_vec_orig_size = memparse(p, &p);
-       if (*p == '@')
-               lp0_vec_orig_start = memparse(p+1, &p);
-
-       return 0;
-}
-__setup("lp0_vec=", tegra_lp0_vec_arg);
-
 void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat)
 {
        u32 reg, mode;
@@ -568,32 +554,9 @@ void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat)
        (void)reg;
        (void)mode;
 
-       if (plat->suspend_mode == TEGRA_SUSPEND_LP0 &&
-                       lp0_vec_orig_size && lp0_vec_orig_start) {
-               unsigned char *reloc_lp0;
-               unsigned long tmp;
-               void __iomem *orig;
-               reloc_lp0 = kmalloc(lp0_vec_orig_size+L1_CACHE_BYTES-1,
-                                   GFP_KERNEL);
-               WARN_ON(!reloc_lp0);
-               if (!reloc_lp0)
-                       goto out;
-
-               orig = ioremap(lp0_vec_orig_start, lp0_vec_orig_size);
-               WARN_ON(!orig);
-               if (!orig) {
-                       kfree(reloc_lp0);
-                       goto out;
-               }
-               tmp = (unsigned long) reloc_lp0;
-               tmp = (tmp + L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES-1);
-               reloc_lp0 = (unsigned char *)tmp;
-               memcpy(reloc_lp0, orig, lp0_vec_orig_size);
-               iounmap(orig);
-               wb0_restore = virt_to_phys(reloc_lp0);
-       }
-out:
-       if (plat->suspend_mode == TEGRA_SUSPEND_LP0 && !wb0_restore) {
+       if (plat->suspend_mode == TEGRA_SUSPEND_LP0 && tegra_lp0_vec_size) {
+               wb0_restore = tegra_lp0_vec_start;
+       } else {
                pr_warning("Suspend mode LP0 requested, but missing lp0_vec\n");
                pr_warning("Disabling LP0\n");
                plat->suspend_mode = TEGRA_SUSPEND_LP1;