summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2012-08-08 16:57:40 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2012-08-08 17:00:24 +0530
commit70002205cda63da3d09d76fce823e5a55e5d61bd (patch)
tree6d8f85830d44762524570cc41698ec77b3d372b4 /arch
parentf36c81a66da50096f1e76272ad684fe1f790640e (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.c45
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)) {