diff options
author | Varun Wadekar <vwadekar@nvidia.com> | 2012-08-08 16:57:40 +0530 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2012-08-08 17:00:24 +0530 |
commit | 70002205cda63da3d09d76fce823e5a55e5d61bd (patch) | |
tree | 6d8f85830d44762524570cc41698ec77b3d372b4 /arch | |
parent | f36c81a66da50096f1e76272ad684fe1f790640e (diff) |
ARM: Tegra: allocate non-cacheable page to hold cpu context
This page would be used by the Trusted Foundations code to
hold the CPU context during suspend.
Change-Id: Ia1c887c1ddf799ed2dce2c818eaf1d50b6d4e499
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/pm.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index e28b53b3fddb..fd7a67190336 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -105,6 +105,9 @@ struct suspend_context { }; #ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_TRUSTED_FOUNDATIONS +void *tegra_cpu_context; /* non-cacheable page for CPU context */ +#endif phys_addr_t tegra_pgd_phys; /* pgd used by hotplug & LP2 bootup */ static pgd_t *tegra_pgd; static DEFINE_SPINLOCK(tegra_lp2_lock); @@ -655,6 +658,41 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags) return remain; } +/* + * alloc_suspend_context + * + * Allocate a non-cacheable page to hold the CPU contexts. + */ +static int alloc_suspend_context(void) +{ +#if CONFIG_TRUSTED_FOUNDATIONS + pgprot_t prot = __pgprot_modify(pgprot_kernel, L_PTE_MT_MASK, + L_PTE_MT_BUFFERABLE | L_PTE_XN); + struct page *ctx_page; + + ctx_page = alloc_pages(GFP_KERNEL, 0); + if (IS_ERR_OR_NULL(ctx_page)) + goto fail; + + tegra_cpu_context = vm_map_ram(&ctx_page, 1, -1, prot); + if (IS_ERR_OR_NULL(tegra_cpu_context)) + goto fail; + + return 0; + +fail: + if (ctx_page) + __free_page(ctx_page); + if (tegra_cpu_context) + vm_unmap_ram((void*)tegra_cpu_context, 1); + tegra_cpu_context = NULL; + + return -ENOMEM; +#else + return 0; +#endif +} + static int tegra_common_suspend(void) { void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE); @@ -1099,6 +1137,13 @@ void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat) goto fail; } + if (alloc_suspend_context() < 0) { + pr_err("%s: CPU context alloc failed -- LP0/LP1/LP2 unavailable\n", + __func__); + plat->suspend_mode = TEGRA_SUSPEND_NONE; + goto fail; + } + if ((tegra_get_chipid() == TEGRA_CHIPID_TEGRA3) && (tegra_revision == TEGRA_REVISION_A01) && (plat->suspend_mode == TEGRA_SUSPEND_LP0)) { |