ARM: tegra11x: Define ncpu residency for 2 clusters
[linux-3.10.git] / arch / arm / mach-tegra / pm.c
index b10e8e7..a63471d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * CPU complex suspend & resume functions for Tegra SoCs
  *
- * Copyright (c) 2009-2012, NVIDIA Corporation.
+ * Copyright (c) 2009-2013, NVIDIA Corporation.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -47,6 +47,7 @@
 #include <linux/tegra_audio.h>
 
 #include <trace/events/power.h>
+#include <trace/events/nvsecurity.h>
 
 #include <asm/cacheflush.h>
 #include <asm/idmap.h>
@@ -76,6 +77,9 @@
 #include "dvfs.h"
 #include "cpu-tegra.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/nvpower.h>
+
 struct suspend_context {
        /*
         * The next 7 values are referenced by offset in __restart_plls
@@ -97,9 +101,6 @@ struct suspend_context {
        u8 uart[5];
 
        struct tegra_twd_context twd;
-#ifdef CONFIG_ARM_ARCH_TIMER
-       struct arch_timer_context arch_timer;
-#endif
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -136,8 +137,12 @@ struct suspend_context tegra_sctx;
 #define PMC_DPAD_ORIDE         0x1C
 #define PMC_WAKE_DELAY         0xe0
 #define PMC_DPD_SAMPLE         0x20
-#define PMC_IO_DPD_REQ_0       0x1b8
-#define PMC_IO_DPD2_REQ_0      0X1C0
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+#define PMC_DPD_ENABLE         0x24
+#endif
+#define PMC_IO_DPD_REQ          0x1B8
+#define PMC_IO_DPD2_REQ         0x1C0
+
 
 #define PMC_WAKE_STATUS                0x14
 #define PMC_SW_WAKE_STATUS     0x18
@@ -252,11 +257,6 @@ unsigned long tegra_cpu_lp2_min_residency(void)
 }
 
 #ifdef CONFIG_ARCH_TEGRA_HAS_SYMMETRIC_CPU_PWR_GATE
-unsigned long tegra_min_residency_noncpu(void)
-{
-       return pdata->min_residency_noncpu;
-}
-
 unsigned long tegra_min_residency_crail(void)
 {
        return pdata->min_residency_crail;
@@ -350,18 +350,12 @@ static void set_power_timers(unsigned long us_on, unsigned long us_off,
  */
 static void restore_cpu_complex(u32 mode)
 {
-       int cpu = smp_processor_id();
+       int cpu = cpu_logical_map(smp_processor_id());
        unsigned int reg;
 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
        unsigned int policy;
 #endif
 
-       BUG_ON(cpu != 0);
-
-#ifdef CONFIG_SMP
-       cpu = cpu_logical_map(cpu);
-#endif
-
 /*
  * On Tegra11x PLLX and CPU burst policy is either preserved across LP2,
  * or restored by common clock suspend/resume procedures. Hence, we don't
@@ -428,19 +422,11 @@ static void restore_cpu_complex(u32 mode)
           idle or system suspend, the local timer was shut down and
           timekeeping switched over to the global system timer. In this
           case keep local timer disabled, and restore only periodic load. */
+#ifdef CONFIG_HAVE_ARM_TWD
        if (!(mode & (TEGRA_POWER_CLUSTER_MASK |
                      TEGRA_POWER_CLUSTER_IMMEDIATE))) {
-#ifdef CONFIG_ARM_ARCH_TIMER
-               tegra_sctx.arch_timer.cntp_ctl = 0;
-#endif
-#ifdef CONFIG_HAVE_ARM_TWD
                tegra_sctx.twd.twd_ctrl = 0;
-#endif
        }
-#ifdef CONFIG_ARM_ARCH_TIMER
-       arch_timer_resume(&tegra_sctx.arch_timer);
-#endif
-#ifdef CONFIG_HAVE_ARM_TWD
        tegra_twd_resume(&tegra_sctx.twd);
 #endif
 }
@@ -455,15 +441,12 @@ static void restore_cpu_complex(u32 mode)
  */
 static void suspend_cpu_complex(u32 mode)
 {
-       int cpu = smp_processor_id();
+       int cpu = cpu_logical_map(smp_processor_id());
        unsigned int reg;
        int i;
 
        BUG_ON(cpu != 0);
 
-#ifdef CONFIG_SMP
-       cpu = cpu_logical_map(cpu);
-#endif
        /* switch coresite to clk_m, save off original source */
        tegra_sctx.clk_csite_src = readl(clk_rst + CLK_RESET_SOURCE_CSITE);
        writel(3<<30, clk_rst + CLK_RESET_SOURCE_CSITE);
@@ -480,9 +463,6 @@ static void suspend_cpu_complex(u32 mode)
 #ifdef CONFIG_HAVE_ARM_TWD
        tegra_twd_suspend(&tegra_sctx.twd);
 #endif
-#ifdef CONFIG_ARM_ARCH_TIMER
-       arch_timer_suspend(&tegra_sctx.arch_timer);
-#endif
 
        reg = readl(FLOW_CTRL_CPU_CSR(cpu));
        reg &= ~FLOW_CTRL_CSR_WFE_BITMAP;       /* clear wfe bitmap */
@@ -509,7 +489,7 @@ static void suspend_cpu_complex(u32 mode)
        tegra_gic_cpu_disable(true);
 }
 
-void tegra_clear_cpu_in_lp2(int cpu)
+void tegra_clear_cpu_in_pd(int cpu)
 {
        spin_lock(&tegra_lp2_lock);
        BUG_ON(!cpumask_test_cpu(cpu, &tegra_in_lp2));
@@ -525,7 +505,7 @@ void tegra_clear_cpu_in_lp2(int cpu)
        spin_unlock(&tegra_lp2_lock);
 }
 
-bool tegra_set_cpu_in_lp2(int cpu)
+bool tegra_set_cpu_in_pd(int cpu)
 {
        bool last_cpu = false;
 
@@ -555,14 +535,23 @@ static void tegra_sleep_core(enum tegra_suspend_mode mode,
                             unsigned long v2p)
 {
 #ifdef CONFIG_TRUSTED_FOUNDATIONS
+       outer_flush_range(__pa(&tegra_resume_timestamps_start),
+                         __pa(&tegra_resume_timestamps_end));
+
        if (mode == TEGRA_SUSPEND_LP0) {
+               trace_smc_sleep_core(NVSEC_SMC_START);
+
                tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE3,
                                  virt_to_phys(tegra_resume));
        } else {
+               trace_smc_sleep_core(NVSEC_SMC_START);
+
                tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE6,
                                  (TEGRA_RESET_HANDLER_BASE +
                                   tegra_cpu_reset_handler_offset));
        }
+
+       trace_smc_sleep_core(NVSEC_SMC_DONE);
 #endif
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
        cpu_suspend(v2p, tegra2_sleep_core_finish);
@@ -573,19 +562,15 @@ static void tegra_sleep_core(enum tegra_suspend_mode mode,
 
 static inline void tegra_sleep_cpu(unsigned long v2p)
 {
-#ifdef CONFIG_TRUSTED_FOUNDATIONS
-       tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE4,
-                         (TEGRA_RESET_HANDLER_BASE +
-                          tegra_cpu_reset_handler_offset));
-#endif
        cpu_suspend(v2p, tegra_sleep_cpu_finish);
 }
 
-unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
+unsigned int tegra_idle_power_down_last(unsigned int sleep_time,
+                                       unsigned int flags)
 {
        u32 reg;
        unsigned int remain;
-#ifndef CONFIG_ARCH_TEGRA_11x_SOC
+#if defined(CONFIG_CACHE_L2X0) && !defined(CONFIG_ARCH_TEGRA_14x_SOC)
        pgd_t *pgd;
 #endif
 
@@ -607,7 +592,7 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
         * are in LP2 state and irqs are disabled
         */
        if (flags & TEGRA_POWER_CLUSTER_MASK) {
-               trace_cpu_cluster(POWER_CPU_CLUSTER_START);
+               trace_nvcpu_cluster(NVPOWER_CPU_CLUSTER_START);
                set_power_timers(pdata->cpu_timer, 2,
                        clk_get_rate_all_locked(tegra_pclk));
                if (flags & TEGRA_POWER_CLUSTER_G) {
@@ -654,13 +639,16 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
        }
 
        if (sleep_time)
-               tegra_lp2_set_trigger(sleep_time);
+               tegra_pd_set_trigger(sleep_time);
 
        cpu_cluster_pm_enter();
        suspend_cpu_complex(flags);
        tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_prolog);
-#ifndef CONFIG_ARCH_TEGRA_11x_SOC
+#ifdef CONFIG_CACHE_L2X0
        flush_cache_all();
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+       outer_flush_all();
+#else
        /*
         * No need to flush complete L2. Cleaning kernel and IO mappings
         * is enough for the LP code sequence that has L2 disabled but
@@ -669,25 +657,38 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
        pgd = cpu_get_pgd();
        outer_clean_range(__pa(pgd + USER_PTRS_PER_PGD),
                          __pa(pgd + PTRS_PER_PGD));
+#endif
        outer_disable();
 #endif
        tegra_sleep_cpu(PHYS_OFFSET - PAGE_OFFSET);
 
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+       tegra_init_cache(true);
+#else
        tegra_init_cache(false);
+#endif
+
+#ifdef CONFIG_TRUSTED_FOUNDATIONS
+#ifndef CONFIG_ARCH_TEGRA_11x_SOC
+       trace_smc_wake(tegra_resume_smc_entry_time, NVSEC_SMC_START);
+       trace_smc_wake(tegra_resume_smc_exit_time, NVSEC_SMC_DONE);
+#endif
+#endif
+
        tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_switch);
        restore_cpu_complex(flags);
        cpu_cluster_pm_exit();
 
-       remain = tegra_lp2_timer_remain();
+       remain = tegra_pd_timer_remain();
        if (sleep_time)
-               tegra_lp2_set_trigger(0);
+               tegra_pd_set_trigger(0);
 
        if (flags & TEGRA_POWER_CLUSTER_MASK) {
                tegra_cluster_switch_epilog(flags);
                if (is_idle_task(current))
-                       trace_cpu_cluster_rcuidle(POWER_CPU_CLUSTER_DONE);
+                       trace_nvcpu_cluster_rcuidle(NVPOWER_CPU_CLUSTER_DONE);
                else
-                       trace_cpu_cluster(POWER_CPU_CLUSTER_DONE);
+                       trace_nvcpu_cluster(NVPOWER_CPU_CLUSTER_DONE);
        } else {
                resume_cpu_dfll_mode();
        }
@@ -732,8 +733,10 @@ static void tegra_common_resume(void)
        void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE);
 #endif
 
-       /* Clear DPD sample */
-       writel(0x0, pmc + PMC_DPD_SAMPLE);
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+       /* Clear DPD Enable */
+       writel(0x0, pmc + PMC_DPD_ENABLE);
+#endif
 
        writel(tegra_sctx.mc[0], mc + MC_SECURITY_START);
        writel(tegra_sctx.mc[1], mc + MC_SECURITY_SIZE);
@@ -741,9 +744,9 @@ static void tegra_common_resume(void)
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
        /* trigger emc mode write */
        writel(EMC_MRW_DEV_NONE, emc + EMC_MRW_0);
-#endif
        /* clear scratch registers shared by suspend and the reset pen */
        writel(0x0, pmc + PMC_SCRATCH39);
+#endif
        writel(0x0, pmc + PMC_SCRATCH41);
 
        /* restore IRAM */
@@ -788,20 +791,23 @@ static void tegra_pm_set(enum tegra_suspend_mode mode)
                        reg &= ~TEGRA_POWER_CPU_PWRREQ_OE;
                }
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
                /*
                 * LP0 boots through the AVP, which then resumes the AVP to
                 * the address in scratch 39, and the cpu to the address in
                 * scratch 41 to tegra_resume
                 */
                writel(0x0, pmc + PMC_SCRATCH39);
+#endif
 
                /* Enable DPD sample to trigger sampling pads data and direction
                 * in which pad will be driven during lp0 mode*/
                writel(0x1, pmc + PMC_DPD_SAMPLE);
 #if !defined(CONFIG_ARCH_TEGRA_3x_SOC) && !defined(CONFIG_ARCH_TEGRA_2x_SOC)
-               writel(0x800fffff, pmc + PMC_IO_DPD_REQ_0);
-               writel(0x80001fff, pmc + PMC_IO_DPD2_REQ_0);
+               writel(0x800fdfff, pmc + PMC_IO_DPD_REQ);
+               writel(0x80001fff, pmc + PMC_IO_DPD2_REQ);
 #endif
+
 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
                /* this is needed only for T11x, not for other chips */
                reg &= ~TEGRA_POWER_CPUPWRGOOD_EN;
@@ -940,7 +946,7 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags)
 
        local_fiq_disable();
 
-       trace_cpu_suspend(CPU_SUSPEND_START);
+       trace_cpu_suspend(CPU_SUSPEND_START, tegra_rtc_read_ms());
 
        if (mode == TEGRA_SUSPEND_LP0) {
 #ifdef CONFIG_TEGRA_CLUSTER_CONTROL
@@ -955,7 +961,9 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags)
                tegra_lp0_suspend_mc();
                tegra_cpu_reset_handler_save();
                tegra_tsc_wait_for_suspend();
+#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
                tegra_smp_clear_power_mask();
+#endif
        }
        else if (mode == TEGRA_SUSPEND_LP1)
                *iram_cpu_lp1_mask = 1;
@@ -985,12 +993,29 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags)
 
        tegra_init_cache(true);
 
+#ifdef CONFIG_TRUSTED_FOUNDATIONS
+#ifndef CONFIG_ARCH_TEGRA_11x_SOC
+       trace_smc_wake(tegra_resume_smc_entry_time, NVSEC_SMC_START);
+       trace_smc_wake(tegra_resume_smc_exit_time, NVSEC_SMC_DONE);
+#endif
+
+       if (mode == TEGRA_SUSPEND_LP0) {
+               trace_secureos_init(tegra_resume_entry_time,
+                       NVSEC_SUSPEND_EXIT_DONE);
+       }
+#endif
+
        if (mode == TEGRA_SUSPEND_LP0) {
+
+               /* CPUPWRGOOD_EN is not enabled in HW so disabling this, *
+               * Otherwise it is creating issue in cluster switch after LP0 *
 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
                reg = readl(pmc+PMC_CTRL);
                reg |= TEGRA_POWER_CPUPWRGOOD_EN;
                pmc_32kwritel(reg, PMC_CTRL);
 #endif
+               */
+
                tegra_tsc_resume();
                tegra_cpu_reset_handler_restore();
                tegra_lp0_resume_mc();
@@ -1019,7 +1044,7 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags)
        if (pdata && pdata->board_resume)
                pdata->board_resume(mode, TEGRA_RESUME_AFTER_CPU);
 
-       trace_cpu_suspend(CPU_SUSPEND_DONE);
+       trace_cpu_suspend(CPU_SUSPEND_DONE, tegra_rtc_read_ms());
 
        local_fiq_enable();
 
@@ -1117,7 +1142,6 @@ static struct kobject *suspend_kobj;
 static int tegra_pm_enter_suspend(void)
 {
        pr_info("Entering suspend state %s\n", lp_state[current_suspend_mode]);
-       suspend_cpu_dfll_mode();
        if (current_suspend_mode == TEGRA_SUSPEND_LP0)
                tegra_lp0_cpu_mode(true);
        return 0;
@@ -1127,7 +1151,6 @@ static void tegra_pm_enter_resume(void)
 {
        if (current_suspend_mode == TEGRA_SUSPEND_LP0)
                tegra_lp0_cpu_mode(false);
-       resume_cpu_dfll_mode();
        pr_info("Exited suspend state %s\n", lp_state[current_suspend_mode]);
 }
 
@@ -1251,7 +1274,9 @@ out:
        /* Initialize scratch registers used for CPU LP2 synchronization */
        writel(0, pmc + PMC_SCRATCH37);
        writel(0, pmc + PMC_SCRATCH38);
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
        writel(0, pmc + PMC_SCRATCH39);
+#endif
        writel(0, pmc + PMC_SCRATCH41);
 
        /* Always enable CPU power request; just normal polarity is supported */
@@ -1309,7 +1334,7 @@ out:
 fail:
 #endif
        if (plat->suspend_mode == TEGRA_SUSPEND_NONE)
-               tegra_lp2_in_idle(false);
+               tegra_pd_in_idle(false);
 
        current_suspend_mode = plat->suspend_mode;
 }
@@ -1390,13 +1415,13 @@ EXPORT_SYMBOL(debug_uart_clk);
 void tegra_console_uart_suspend(void)
 {
        if (console_suspend_enabled && debug_uart_clk)
-               clk_disable(debug_uart_clk);
+               tegra_clk_disable_unprepare(debug_uart_clk);
 }
 
 void tegra_console_uart_resume(void)
 {
        if (console_suspend_enabled && debug_uart_clk)
-               clk_enable(debug_uart_clk);
+               tegra_clk_prepare_enable(debug_uart_clk);
 }
 
 static int tegra_debug_uart_syscore_init(void)