msm: pm: warmboot entry/exit counters on IMEM
Add warmboot entry/exit counters for each core on a non-cacheable always
on IMEM memory. This is a useful feature during debug to understand if
the system has correctly warmbooted after a power collapse. The debug
counters start at a memory offset of 0x664 on the IMEM. Each core
reserves 4 words for events, of which 3 are being used to monitor the
following events,
1) power collapse entry
2) warmboot exit
3) failed power collapse when wfi returns with a pending interrupt.
Change-Id: I45aac8e4a4d3421d586790b3b66fd71a8d88ea9d
Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 8ddb9e1..dbb23d5 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -24,6 +24,7 @@
#include <linux/smp.h>
#include <linux/suspend.h>
#include <linux/tick.h>
+#include <linux/platform_device.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <mach/system.h>
@@ -71,7 +72,6 @@
);
static int msm_pm_retention_tz_call;
-
/******************************************************************************
* Sleep Modes and Parameters
*****************************************************************************/
@@ -491,7 +491,6 @@
#ifdef CONFIG_VFP
vfp_pm_suspend();
#endif
-
collapsed = msm_pm_l2x0_power_collapse();
msm_pm_boot_config_after_pc(cpu);
@@ -950,6 +949,46 @@
msm_pm_retention_tz_call = flag;
}
+static int __devinit msm_pc_debug_probe(struct platform_device *pdev)
+{
+ struct resource *res = NULL;
+ int i ;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto fail;
+
+ msm_pc_debug_counters_phys = res->start;
+ WARN_ON(resource_size(res) < SZ_64);
+ msm_pc_debug_counters = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+
+ if (!msm_pc_debug_counters)
+ goto fail;
+
+ for (i = 0; i < resource_size(res)/4; i++)
+ __raw_writel(0, msm_pc_debug_counters + i * 4);
+ return 0;
+fail:
+ msm_pc_debug_counters = 0;
+ msm_pc_debug_counters_phys = 0;
+ return -EFAULT;
+}
+
+static struct of_device_id msm_pc_debug_table[] = {
+ {.compatible = "qcom,pc-cntr"},
+ {},
+};
+
+static struct platform_driver msm_pc_counter_driver = {
+ .probe = msm_pc_debug_probe,
+ .driver = {
+ .name = "pc-cntr",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_pc_debug_table,
+ },
+};
+
static int __init msm_pm_init(void)
{
pgd_t *pc_pgd;
@@ -965,6 +1004,7 @@
unsigned long exit_phys;
/* Page table for cores to come back up safely. */
+
pc_pgd = pgd_alloc(&init_mm);
if (!pc_pgd)
return -ENOMEM;
@@ -1007,6 +1047,7 @@
suspend_set_ops(&msm_pm_ops);
msm_pm_qtimer_available();
msm_cpuidle_init();
+ platform_driver_register(&msm_pc_counter_driver);
return 0;
}