From 9a3993d39599d1637d7c04218e6a634f914e9f91 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Wed, 20 Jul 2011 17:20:25 +0530 Subject: arm: tegra: pm: Relocate lp0 vector LP0 vector is allocated by BL and address is shared to kernel. For platform with memory less than 1GB it was allocated in the overlapping region of carveout memory. Because of it during AVP operation it gets corrupted, which prevents resume. Relocate AVP vector to some other location where overlapping will not occur. Bug 827199 Change-Id: I8ec066d8c38c34b0bd9314abe20b2e01b4a3a293 Reviewed-on: http://git-master/r/42113 Reviewed-by: Prashant Gaikwad Tested-by: Prashant Gaikwad Reviewed-by: Mayuresh Kulkarni Reviewed-by: Bharat Nihalani --- arch/arm/mach-tegra/common.c | 6 ------ arch/arm/mach-tegra/suspend.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 0eee187abe38..4091b6de2bcc 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -438,12 +438,6 @@ out: 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 " diff --git a/arch/arm/mach-tegra/suspend.c b/arch/arm/mach-tegra/suspend.c index f05acc6cb65f..6920d87c8982 100644 --- a/arch/arm/mach-tegra/suspend.c +++ b/arch/arm/mach-tegra/suspend.c @@ -851,6 +851,37 @@ void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat) (void)reg; (void)mode; + if (plat->suspend_mode == TEGRA_SUSPEND_LP0 && tegra_lp0_vec_size) { + unsigned char *reloc_lp0; + unsigned long tmp; + void __iomem *orig; + reloc_lp0 = kmalloc(tegra_lp0_vec_size + L1_CACHE_BYTES - 1, + GFP_KERNEL); + WARN_ON(!reloc_lp0); + if (!reloc_lp0) { + pr_err("%s: Failed to allocate reloc_lp0\n", + __func__); + goto out; + } + + orig = ioremap(tegra_lp0_vec_start, tegra_lp0_vec_size); + WARN_ON(!orig); + if (!orig) { + pr_err("%s: Failed to map tegra_lp0_vec_start %08lx\n", + __func__, tegra_lp0_vec_start); + 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, tegra_lp0_vec_size); + iounmap(orig); + tegra_lp0_vec_start = virt_to_phys(reloc_lp0); + } + +out: if (plat->suspend_mode == TEGRA_SUSPEND_LP0 && tegra_lp0_vec_size) { wb0_restore = tegra_lp0_vec_start; } else { -- cgit v1.2.3