arm: tegra: Instrument cluster switch transitions
Scott Williams [Tue, 1 Feb 2011 03:56:16 +0000 (19:56 -0800)]
Original-Change-Id: I1526de69a1224f42ce3ff11ba1b6fa949c2f13a5
Reviewed-on: http://git-master/r/17787
Tested-by: Scott Williams <scwilliams@nvidia.com>
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Original-Change-Id: I43caec7348d970dc076f27cc2bb4b6ded234a38c

Rebase-Id: Ra122021184a1c12cc85e08cd3d7abe41345db058

arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/pm.h

index 269286e..f7c4eec 100644 (file)
@@ -166,6 +166,32 @@ static enum tegra_suspend_mode current_suspend_mode = TEGRA_SUSPEND_NONE;
 static DEFINE_SPINLOCK(tegra_lp2_lock);
 static cpumask_t tegra_in_lp2;
 
+#if INSTRUMENT_CLUSTER_SWITCH
+enum tegra_cluster_switch_time_id
+{
+       tegra_cluster_switch_time_id_start = 0,
+       tegra_cluster_switch_time_id_prolog,
+       tegra_cluster_switch_time_id_switch,
+       tegra_cluster_switch_time_id_epilog,
+       tegra_cluster_switch_time_id_max
+};
+
+static unsigned long tegra_cluster_switch_times[tegra_cluster_switch_time_id_max];
+#define tegra_cluster_switch_time(flags, id) \
+       do { \
+               barrier(); \
+               if (flags & TEGRA_POWER_CLUSTER_MASK) { \
+                       void __iomem *timer_us = IO_ADDRESS(TEGRA_TMRUS_BASE); \
+                       if (id < tegra_cluster_switch_time_id_max) \
+                               tegra_cluster_switch_times[id] = readl(timer_us); \
+                               wmb(); \
+               } \
+               barrier(); \
+       } while(0)
+#else
+#define tegra_cluster_switch_time(flags, id) do {} while(0)
+#endif
+
 unsigned long tegra_cpu_power_good_time(void)
 {
        if (WARN_ON_ONCE(!pdata))
@@ -432,6 +458,8 @@ void tegra_idle_lp2_last(unsigned int flags)
        reg &= ~TEGRA_POWER_EFFECT_LP0;
        pmc_32kwritel(reg, PMC_CTRL);
 
+       tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_start);
+
        writel(virt_to_phys(tegra_resume), evp_reset);
 
        /*
@@ -447,6 +475,7 @@ void tegra_idle_lp2_last(unsigned int flags)
        cpu_complex_pm_enter();
 
        suspend_cpu_complex();
+       tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_prolog);
        flush_cache_all();
        outer_flush_all();
        outer_disable();
@@ -454,6 +483,7 @@ void tegra_idle_lp2_last(unsigned int flags)
        tegra_sleep_cpu(PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
        l2x0_enable();
+       tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_switch);
        restore_cpu_complex();
        cpu_complex_pm_exit();
 
@@ -463,6 +493,27 @@ void tegra_idle_lp2_last(unsigned int flags)
        for_each_online_cpu(i)
                if (i != cpu)
                        tegra_wake_reset_cpu(i);
+
+       tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_epilog);
+
+#if INSTRUMENT_CLUSTER_SWITCH
+       if (flags & TEGRA_POWER_CLUSTER_MASK) {
+               printk("cluster switch prolog took %lu us\n",
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_prolog] -
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_start]);
+
+               printk("cluster switch context save/restore took %lu us, cumulative time %lu us\n",
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_switch] -
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_prolog],
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_switch] -
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_start]),
+               printk("cluster switch epilog took %lu us, cumulative time %lu us\n",
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_epilog] -
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_switch],
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_epilog] -
+                       tegra_cluster_switch_times[tegra_cluster_switch_time_id_start]);
+       }
+#endif
 }
 
 void tegra_idle_lp2(void)
index 6be530c..eb4e24e 100644 (file)
@@ -70,6 +70,7 @@ extern void (*tegra_deep_sleep)(int);
 
 void tegra_idle_lp2_last(unsigned int flags);
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
+#define INSTRUMENT_CLUSTER_SWITCH 0 /* Must be zero for ARCH_TEGRA_2x_SOC */
 static inline int tegra_cluster_control(unsigned int us, unsigned int flags)
 { return -EPERM; }
 #define tegra_cluster_switch_prolog(flags) do {} while(0)
@@ -79,6 +80,7 @@ static inline unsigned int is_lp_cluster(void)
 static inline unsigned long tegra_get_lpcpu_max_rate(void)
 { return 0; }
 #else
+#define INSTRUMENT_CLUSTER_SWITCH 1 /* Should be zero for shipping code */
 int tegra_cluster_control(unsigned int us, unsigned int flags);
 void tegra_cluster_switch_prolog(unsigned int flags);
 void tegra_cluster_switch_epilog(unsigned int flags);