From 9796850a6b8716aa5eaddb864816cb61fcea4894 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 19 Oct 2010 14:45:50 -0700 Subject: [PATCH] [ARM] tegra: Use memblock_remove to allocate carveout and framebuffer 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 --- arch/arm/mach-tegra/board.h | 13 +++++ arch/arm/mach-tegra/common.c | 100 ++++++++++++++++++++++++++++++++++ arch/arm/mach-tegra/suspend.c | 45 ++------------- 3 files changed, 117 insertions(+), 41 deletions(-) diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 3d06354136f2..120b452bcda9 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -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 diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 99eb45eb30c3..d212e78a0360 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -33,6 +34,17 @@ #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); +} diff --git a/arch/arm/mach-tegra/suspend.c b/arch/arm/mach-tegra/suspend.c index b46d1bfff9b5..c7be121ea8d1 100644 --- a/arch/arm/mach-tegra/suspend.c +++ b/arch/arm/mach-tegra/suspend.c @@ -49,6 +49,7 @@ #include #include +#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; -- 2.34.1