summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/cpuidle-t14x.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/cpuidle-t14x.c')
-rw-r--r--arch/arm/mach-tegra/cpuidle-t14x.c792
1 files changed, 0 insertions, 792 deletions
diff --git a/arch/arm/mach-tegra/cpuidle-t14x.c b/arch/arm/mach-tegra/cpuidle-t14x.c
deleted file mode 100644
index 3af1eece7441..000000000000
--- a/arch/arm/mach-tegra/cpuidle-t14x.c
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * arch/arm/mach-tegra/cpuidle-t14x.c
- *
- * Copyright (c) 2012-2013 NVIDIA Corporation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/cpu.h>
-#include <linux/cpuidle.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/hrtimer.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/ratelimit.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
-#include <linux/suspend.h>
-#include <linux/tick.h>
-#include <linux/clk.h>
-#include <linux/cpu_pm.h>
-#include <linux/module.h>
-#include <linux/tegra-soc.h>
-#include <linux/irqchip/tegra.h>
-
-#include <asm/cacheflush.h>
-#include <asm/localtimer.h>
-#include <asm/suspend.h>
-#include <asm/smp_twd.h>
-#include <asm/cputype.h>
-
-#include <mach/irqs.h>
-
-#include <trace/events/nvpower.h>
-
-#include "clock.h"
-#include "cpuidle.h"
-#include "dvfs.h"
-#include "iomap.h"
-#include "pm.h"
-#include "reset.h"
-#include "sleep.h"
-#include "timer.h"
-
-#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS \
- (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x470)
-#define PMC_POWERGATE_STATUS \
- (IO_ADDRESS(TEGRA_PMC_BASE) + 0x038)
-
-#ifdef CONFIG_SMP
-static s64 tegra_cpu_wake_by_time[4] = {
- LLONG_MAX, LLONG_MAX, LLONG_MAX, LLONG_MAX };
-#endif
-
-static ulong cpu_power_gating_in_idle __read_mostly = 0x1f;
-module_param(cpu_power_gating_in_idle, ulong, 0644);
-
-static bool slow_cluster_power_gating_noncpu __read_mostly;
-module_param(slow_cluster_power_gating_noncpu, bool, 0644);
-
-static uint fast_cluster_power_down_mode __read_mostly;
-module_param(fast_cluster_power_down_mode, uint, 0644);
-
-static bool stop_mc_clk_in_idle __read_mostly;
-module_param(stop_mc_clk_in_idle, bool, 0644);
-
-static struct clk *cpu_clk_for_dvfs;
-#ifdef CONFIG_HAVE_ARM_TWD
-static struct clk *twd_clk;
-#endif
-
-static int pd_exit_latencies[5];
-
-static struct {
- unsigned int cpu_ready_count[5];
- unsigned int tear_down_count[5];
- unsigned long long cpu_wants_pd_time[5];
- unsigned long long cpu_pg_time[5];
- unsigned long long rail_pd_time;
- unsigned long long c0nc_pg_time;
- unsigned long long c1nc_pg_time;
- unsigned long long mc_clk_stop_time;
- unsigned int rail_gating_count;
- unsigned int rail_gating_bin[32];
- unsigned int rail_gating_done_count;
- unsigned int rail_gating_done_count_bin[32];
- unsigned int c0nc_gating_count;
- unsigned int c0nc_gating_bin[32];
- unsigned int c0nc_gating_done_count;
- unsigned int c0nc_gating_done_count_bin[32];
- unsigned int c1nc_gating_count;
- unsigned int c1nc_gating_bin[32];
- unsigned int c1nc_gating_done_count;
- unsigned int c1nc_gating_done_count_bin[32];
- unsigned int mc_clk_stop_count;
- unsigned int mc_clk_stop_bin[32];
- unsigned int mc_clk_stop_done_count;
- unsigned int mc_clk_stop_done_count_bin[32];
- unsigned int pd_int_count[NR_IRQS];
- unsigned int last_pd_int_count[NR_IRQS];
- unsigned int clk_gating_vmin;
-} idle_stats;
-
-static inline unsigned int time_to_bin(unsigned int time)
-{
- return fls(time);
-}
-
-static inline void tegra_irq_unmask(int irq)
-{
- struct irq_data *data = irq_get_irq_data(irq);
- data->chip->irq_unmask(data);
-}
-
-static inline unsigned int cpu_number(unsigned int n)
-{
- return is_lp_cluster() ? 4 : n;
-}
-
-void tegra14x_cpu_idle_stats_pd_ready(unsigned int cpu)
-{
- idle_stats.cpu_ready_count[cpu_number(cpu)]++;
-}
-
-void tegra14x_cpu_idle_stats_pd_time(unsigned int cpu, s64 us)
-{
- idle_stats.cpu_wants_pd_time[cpu_number(cpu)] += us;
-}
-
-/* Allow rail off only if all secondary CPUs are power gated, and no
- rail update is in progress */
-static bool tegra_rail_off_is_allowed(void)
-{
- u32 rst = readl(CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
- u32 pg = readl(PMC_POWERGATE_STATUS) >> 8;
-
- if (((rst & 0xE) != 0xE) || ((pg & 0xE) != 0))
- return false;
-
- if (tegra_dvfs_rail_updating(cpu_clk_for_dvfs))
- return false;
-
- return true;
-}
-
-bool tegra14x_pd_is_allowed(struct cpuidle_device *dev,
- struct cpuidle_state *state)
-{
- s64 request;
-
- if (!cpumask_test_cpu(cpu_number(dev->cpu),
- to_cpumask(&cpu_power_gating_in_idle)))
- return false;
-
- request = ktime_to_us(tick_nohz_get_sleep_length());
- if (state->exit_latency != pd_exit_latencies[cpu_number(dev->cpu)]) {
- /* possible on the 1st entry after cluster switch*/
- state->exit_latency = pd_exit_latencies[cpu_number(dev->cpu)];
- tegra_pd_update_target_residency(state);
- }
- if (request < state->target_residency) {
- /* Not enough time left to enter LP2 */
- return false;
- }
-
- return true;
-}
-
-static inline void tegra14_irq_restore_affinity(void)
-{
-#ifdef CONFIG_SMP
- /* Disable the distributor. */
- tegra_gic_dist_disable();
-
- /* Restore the other CPU's interrupt affinity. */
- tegra_gic_restore_affinity();
-
- /* Re-enable the distributor. */
- tegra_gic_dist_enable();
-#endif
-}
-
-static bool tegra_cpu_cluster_power_down(struct cpuidle_device *dev,
- struct cpuidle_state *state, s64 request)
-{
- ktime_t entry_time;
- ktime_t exit_time;
- bool sleep_completed = false;
- bool multi_cpu_entry = false;
- int bin;
- unsigned int flag = 0;
- s64 sleep_time;
-
- /* LP2 entry time */
- entry_time = ktime_get();
-
- if (request < state->target_residency) {
- /* Not enough time left to enter LP2 */
- cpu_do_idle();
- return false;
- }
-
-#ifdef CONFIG_SMP
- multi_cpu_entry = !is_lp_cluster() && (num_online_cpus() > 1);
- if (multi_cpu_entry) {
- s64 wake_time;
- unsigned int i;
-
- /* Disable the distributor -- this is the only way to
- prevent the other CPUs from responding to interrupts
- and potentially fiddling with the distributor
- registers while we're fiddling with them. */
- tegra_gic_dist_disable();
-
- /* Did an interrupt come in for another CPU before we
- could disable the distributor? */
- if (!tegra_rail_off_is_allowed()) {
- /* Yes, re-enable the distributor and clock gating. */
- tegra_gic_dist_enable();
- cpu_do_idle();
- return false;
- }
-
- /* LP2 initial targeted wake time */
- wake_time = ktime_to_us(entry_time) + request;
-
- /* CPU0 must wake up before any of the other CPUs. */
- smp_rmb();
- for (i = 1; i < CONFIG_NR_CPUS; i++)
- wake_time = min_t(s64, wake_time,
- tegra_cpu_wake_by_time[i]);
-
- /* LP2 actual targeted wake time */
- request = wake_time - ktime_to_us(entry_time);
- BUG_ON(wake_time < 0LL);
-
- if (request < state->target_residency) {
- /* Not enough time left to enter LP2 */
- tegra_gic_dist_enable();
- cpu_do_idle();
- return false;
- }
-
- /* Cancel power gating wake timers for all secondary CPUs */
- tegra_pd_timer_cancel_secondary();
-
- /* Save and disable the affinity setting for the other
- CPUs and route all interrupts to CPU0. */
- tegra_gic_disable_affinity();
-
- /* Re-enable the distributor. */
- tegra_gic_dist_enable();
- }
-#endif
- cpu_pm_enter();
-
- sleep_time = request -
- pd_exit_latencies[cpu_number(dev->cpu)];
-
- bin = time_to_bin((u32)request / 1000);
- idle_stats.tear_down_count[cpu_number(dev->cpu)]++;
-
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
- if (is_lp_cluster()) {
- /* here we are not supporting emulation mode, for now */
- flag = TEGRA_POWER_CLUSTER_PART_NONCPU;
- idle_stats.c1nc_gating_count++;
- idle_stats.c1nc_gating_bin[bin]++;
- } else {
- tegra_dvfs_rail_off(tegra_cpu_rail, entry_time);
- flag = (fast_cluster_power_down_mode
- << TEGRA_POWER_CLUSTER_PART_SHIFT)
- & TEGRA_POWER_CLUSTER_PART_MASK;
- if ((request < tegra_min_residency_crail()) &&
- (flag != TEGRA_POWER_CLUSTER_PART_MASK))
- flag = TEGRA_POWER_CLUSTER_PART_NONCPU;
-
- if (flag == TEGRA_POWER_CLUSTER_PART_CRAIL) {
- idle_stats.rail_gating_count++;
- idle_stats.rail_gating_bin[bin]++;
- } else if (flag == TEGRA_POWER_CLUSTER_PART_NONCPU) {
- idle_stats.c0nc_gating_count++;
- idle_stats.c0nc_gating_bin[bin]++;
- }
- }
-
- if (stop_mc_clk_in_idle && (state->power_usage == 0) &&
- (request > tegra_mc_clk_stop_min_residency())) {
- flag |= TEGRA_POWER_STOP_MC_CLK;
-
- trace_nvmc_clk_stop_rcuidle(NVPOWER_MC_CLK_STOP_ENTRY,
- sleep_time);
- idle_stats.mc_clk_stop_count++;
- idle_stats.mc_clk_stop_bin[bin]++;
-
- tegra_mc_clk_prepare();
- }
-
- if (tegra_idle_power_down_last(sleep_time, flag) == 0)
- sleep_completed = true;
- else {
- int irq = tegra_gic_pending_interrupt();
- idle_stats.pd_int_count[irq]++;
- }
-
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
- exit_time = ktime_get();
-
- if (flag & TEGRA_POWER_STOP_MC_CLK)
- tegra_mc_clk_finish();
-
- if (!is_lp_cluster())
- tegra_dvfs_rail_on(tegra_cpu_rail, exit_time);
-
- if (flag & TEGRA_POWER_STOP_MC_CLK)
- idle_stats.mc_clk_stop_time +=
- ktime_to_us(ktime_sub(exit_time, entry_time));
- else if (flag & TEGRA_POWER_CLUSTER_PART_CRAIL)
- idle_stats.rail_pd_time +=
- ktime_to_us(ktime_sub(exit_time, entry_time));
- else if (flag & TEGRA_POWER_CLUSTER_PART_NONCPU) {
- if (is_lp_cluster())
- idle_stats.c1nc_pg_time +=
- ktime_to_us(ktime_sub(exit_time, entry_time));
- else
- idle_stats.c0nc_pg_time +=
- ktime_to_us(ktime_sub(exit_time, entry_time));
- }
-
- if (multi_cpu_entry)
- tegra14_irq_restore_affinity();
-
- if (sleep_completed) {
- /*
- * Stayed in LP2 for the full time until the next tick,
- * adjust the exit latency based on measurement
- */
- int offset = ktime_to_us(ktime_sub(exit_time, entry_time))
- - request;
- int latency = pd_exit_latencies[cpu_number(dev->cpu)] +
- offset / 16;
- latency = clamp(latency, 0, 10000);
- pd_exit_latencies[cpu_number(dev->cpu)] = latency;
- state->exit_latency = latency; /* for idle governor */
- smp_wmb();
-
- if (flag & TEGRA_POWER_STOP_MC_CLK) {
- trace_nvmc_clk_stop_rcuidle(NVPOWER_MC_CLK_STOP_EXIT,
- sleep_time);
- idle_stats.mc_clk_stop_done_count++;
- idle_stats.mc_clk_stop_done_count_bin[bin]++;
- } else if (flag & TEGRA_POWER_CLUSTER_PART_CRAIL) {
- idle_stats.rail_gating_done_count++;
- idle_stats.rail_gating_done_count_bin[bin]++;
- } else if (flag & TEGRA_POWER_CLUSTER_PART_NONCPU) {
- if (is_lp_cluster()) {
- idle_stats.c1nc_gating_done_count++;
- idle_stats.c1nc_gating_done_count_bin[bin]++;
- } else {
- idle_stats.c0nc_gating_done_count++;
- idle_stats.c0nc_gating_done_count_bin[bin]++;
- }
- }
-
- pr_debug("%lld %lld %d %d\n", request,
- ktime_to_us(ktime_sub(exit_time, entry_time)),
- offset, bin);
- }
-
- cpu_pm_exit();
-
- return true;
-}
-
-static bool tegra_cpu_core_power_down(struct cpuidle_device *dev,
- struct cpuidle_state *state, s64 request)
-{
-#ifdef CONFIG_SMP
- s64 sleep_time;
- ktime_t entry_time;
-#ifdef CONFIG_HAVE_ARM_TWD
- struct tegra_twd_context twd_context;
-#endif
- bool sleep_completed = false;
- struct tick_sched *ts = tick_get_tick_sched(dev->cpu);
-#ifdef CONFIG_HAVE_ARM_TWD
-#if defined(CONFIG_TEGRA_LP2_CPU_TIMER)
- void __iomem *twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
-#endif
-
- if (!tegra_twd_get_state(&twd_context)) {
- unsigned long twd_rate = clk_get_rate(twd_clk);
-
- if ((twd_context.twd_ctrl & TWD_TIMER_CONTROL_ENABLE) &&
- (twd_context.twd_ctrl & TWD_TIMER_CONTROL_IT_ENABLE)) {
- request = div_u64((u64)twd_context.twd_cnt * 1000000,
- twd_rate);
-#ifdef CONFIG_TEGRA_LP2_CPU_TIMER
- if (request >= state->target_residency) {
- twd_context.twd_cnt -= state->exit_latency *
- (twd_rate / 1000000);
- writel(twd_context.twd_cnt,
- twd_base + TWD_TIMER_COUNTER);
- }
-#endif
- }
- }
-#endif
-
- if (!tegra_is_cpu_wake_timer_ready(dev->cpu) ||
- (request < state->target_residency) ||
- (!ts) || (ts->nohz_mode == NOHZ_MODE_INACTIVE)) {
- /*
- * Not enough time left to enter LP2, or wake timer not ready
- */
- cpu_do_idle();
- return false;
- }
-
- cpu_pm_enter();
-
-#if !defined(CONFIG_TEGRA_LP2_CPU_TIMER)
- sleep_time = request - state->exit_latency;
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
-#ifdef CONFIG_HAVE_ARM_TWD
- tegra_twd_suspend(&twd_context);
-#endif
- tegra_pd_set_trigger(sleep_time);
-#endif
- idle_stats.tear_down_count[cpu_number(dev->cpu)]++;
-
- entry_time = ktime_get();
-
- /* Save time this CPU must be awakened by. */
- tegra_cpu_wake_by_time[dev->cpu] = ktime_to_us(entry_time) + request;
- smp_wmb();
-
-#ifdef CONFIG_TRUSTED_LITTLE_KERNEL
- if (dev->cpu == 0) {
- tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE4,
- (TEGRA_RESET_HANDLER_BASE +
- tegra_cpu_reset_handler_offset));
- }
-#endif
- cpu_suspend(0, tegra3_sleep_cpu_secondary_finish);
-
- tegra_cpu_wake_by_time[dev->cpu] = LLONG_MAX;
-
-#ifdef CONFIG_TEGRA_LP2_CPU_TIMER
-#ifdef CONFIG_HAVE_ARM_TWD
- if (!tegra_twd_get_state(&twd_context))
- sleep_completed = (twd_context.twd_cnt == 0);
-#endif
-#else
- sleep_completed = !tegra_pd_timer_remain();
- tegra_pd_set_trigger(0);
-#ifdef CONFIG_HAVE_ARM_TWD
- tegra_twd_resume(&twd_context);
-#endif
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
-#endif
- sleep_time = ktime_to_us(ktime_sub(ktime_get(), entry_time));
- idle_stats.cpu_pg_time[cpu_number(dev->cpu)] += sleep_time;
- if (sleep_completed) {
- /*
- * Stayed in LP2 for the full time until timer expires,
- * adjust the exit latency based on measurement
- */
- int offset = sleep_time - request;
- int latency = pd_exit_latencies[cpu_number(dev->cpu)] +
- offset / 16;
- latency = clamp(latency, 0, 10000);
- pd_exit_latencies[cpu_number(dev->cpu)] = latency;
- state->exit_latency = latency; /* for idle governor */
- smp_wmb();
- }
-#endif
- cpu_pm_exit();
-
- return true;
-}
-
-bool tegra14x_idle_power_down(struct cpuidle_device *dev,
- struct cpuidle_state *state)
-{
- bool power_down;
- bool cpu_gating_only = false;
- bool clkgt_at_vmin = false;
- bool power_gating_cpu_only = true;
- unsigned long rate;
- int status = -1;
- s64 request = ktime_to_us(tick_nohz_get_sleep_length());
-
- tegra_set_cpu_in_pd(dev->cpu);
- cpu_gating_only = (((fast_cluster_power_down_mode
- << TEGRA_POWER_CLUSTER_PART_SHIFT)
- & TEGRA_POWER_CLUSTER_PART_MASK) == 0);
-
- if (is_lp_cluster()) {
- if (slow_cluster_power_gating_noncpu &&
- (request > tegra_min_residency_ncpu()))
- power_gating_cpu_only = false;
- else
- power_gating_cpu_only = true;
- } else {
- if (num_online_cpus() > 1)
- power_gating_cpu_only = true;
- else {
- if (tegra_dvfs_rail_updating(cpu_clk_for_dvfs))
- clkgt_at_vmin = false;
- else if (tegra_force_clkgt_at_vmin ==
- TEGRA_CPUIDLE_FORCE_DO_CLKGT_VMIN)
- clkgt_at_vmin = true;
- else if (tegra_force_clkgt_at_vmin ==
- TEGRA_CPUIDLE_FORCE_NO_CLKGT_VMIN)
- clkgt_at_vmin = false;
- else if ((request >= tegra_min_residency_vmin_fmin()) &&
- ((request < tegra_min_residency_ncpu()) ||
- cpu_gating_only))
- clkgt_at_vmin = true;
-
- if (!cpu_gating_only && tegra_rail_off_is_allowed()) {
- if (fast_cluster_power_down_mode &
- TEGRA_POWER_CLUSTER_FORCE_MASK)
- power_gating_cpu_only = false;
- else if (request >
- tegra_min_residency_ncpu())
- power_gating_cpu_only = false;
- else
- power_gating_cpu_only = true;
- } else
- power_gating_cpu_only = true;
- }
- }
-
- if (clkgt_at_vmin) {
- rate = 0;
- status = tegra_cpu_g_idle_rate_exchange(&rate);
- if (!status) {
- idle_stats.clk_gating_vmin++;
- cpu_do_idle();
- tegra_cpu_g_idle_rate_exchange(&rate);
- power_down = true;
- } else {
- power_down = tegra_cpu_core_power_down(dev, state,
- request);
- }
- } else if (power_gating_cpu_only)
- power_down = tegra_cpu_core_power_down(dev, state, request);
- else {
- if (is_lp_cluster()) {
- rate = ULONG_MAX;
- status = tegra_cpu_lp_idle_rate_exchange(&rate);
- }
-
- power_down = tegra_cpu_cluster_power_down(dev, state, request);
-
- /* restore cpu clock after cluster power ungating */
- if (status == 0)
- tegra_cpu_lp_idle_rate_exchange(&rate);
- }
-
- tegra_clear_cpu_in_pd(dev->cpu);
-
- return power_down;
-}
-
-#ifdef CONFIG_DEBUG_FS
-int tegra14x_pd_debug_show(struct seq_file *s, void *data)
-{
- int bin;
- int i;
- unsigned long long total_c0cpu0_pg_time = 0;
- unsigned long long total_c1cpu0_pg_time = 0;
-
- seq_printf(s, " cpu0 cpu1 cpu2 cpu3 cpulp\n");
- seq_printf(s, "-----------------------------------------------------------------------------\n");
- seq_printf(s, "cpu ready: %8u %8u %8u %8u %8u\n",
- idle_stats.cpu_ready_count[0],
- idle_stats.cpu_ready_count[1],
- idle_stats.cpu_ready_count[2],
- idle_stats.cpu_ready_count[3],
- idle_stats.cpu_ready_count[4]);
- seq_printf(s, "tear down: %8u %8u %8u %8u %8u\n",
- idle_stats.tear_down_count[0],
- idle_stats.tear_down_count[1],
- idle_stats.tear_down_count[2],
- idle_stats.tear_down_count[3],
- idle_stats.tear_down_count[4]);
- seq_printf(s, "clk gating @ Vmin count: %8u\n",
- idle_stats.clk_gating_vmin);
- seq_printf(s, "rail gating count: %8u\n",
- idle_stats.rail_gating_count);
- seq_printf(s, "rail gating completed: %8u %7u%%\n",
- idle_stats.rail_gating_done_count,
- idle_stats.rail_gating_done_count * 100 /
- (idle_stats.rail_gating_count ?: 1));
-
- seq_printf(s, "c0nc gating count: %8u\n",
- idle_stats.c0nc_gating_count);
- seq_printf(s, "c0nc gating completed: %8u %7u%%\n",
- idle_stats.c0nc_gating_done_count,
- idle_stats.c0nc_gating_done_count * 100 /
- (idle_stats.c0nc_gating_count ?: 1));
-
- seq_printf(s, "c1nc gating count: %8u\n",
- idle_stats.c1nc_gating_count);
- seq_printf(s, "c1nc gating completed: %8u %7u%%\n",
- idle_stats.c1nc_gating_done_count,
- idle_stats.c1nc_gating_done_count * 100 /
- (idle_stats.c1nc_gating_count ?: 1));
-
- seq_printf(s, "mc clk stop count: %8u\n",
- idle_stats.mc_clk_stop_count);
- seq_printf(s, "mc_clk_stop completed: %8u %7u%%\n",
- idle_stats.mc_clk_stop_done_count,
- idle_stats.mc_clk_stop_done_count * 100 /
- (idle_stats.mc_clk_stop_count ?: 1));
-
- seq_printf(s, "\n");
- seq_printf(s, "cpu ready time: " \
- "%8llu %8llu %8llu %8llu %8llu ms\n",
- div64_u64(idle_stats.cpu_wants_pd_time[0], 1000),
- div64_u64(idle_stats.cpu_wants_pd_time[1], 1000),
- div64_u64(idle_stats.cpu_wants_pd_time[2], 1000),
- div64_u64(idle_stats.cpu_wants_pd_time[3], 1000),
- div64_u64(idle_stats.cpu_wants_pd_time[4], 1000));
-
- total_c0cpu0_pg_time = idle_stats.cpu_pg_time[0] + \
- idle_stats.c0nc_pg_time + \
- idle_stats.rail_pd_time;
- total_c1cpu0_pg_time = idle_stats.cpu_pg_time[4] + \
- idle_stats.c1nc_pg_time;
-
- seq_printf(s, "cpu power gating time: " \
- "%8llu %8llu %8llu %8llu %8llu ms\n",
- div64_u64(total_c0cpu0_pg_time, 1000),
- div64_u64(idle_stats.cpu_pg_time[1], 1000),
- div64_u64(idle_stats.cpu_pg_time[2], 1000),
- div64_u64(idle_stats.cpu_pg_time[3], 1000),
- div64_u64(total_c1cpu0_pg_time, 1000));
-
- seq_printf(s, "power gated %%: " \
- "%7d%% %7d%% %7d%% %7d%% %7d%%\n",
- (int)(idle_stats.cpu_wants_pd_time[0] ?
- div64_u64(total_c0cpu0_pg_time * 100,
- idle_stats.cpu_wants_pd_time[0]) : 0),
- (int)(idle_stats.cpu_wants_pd_time[1] ?
- div64_u64(idle_stats.cpu_pg_time[1] * 100,
- idle_stats.cpu_wants_pd_time[1]) : 0),
- (int)(idle_stats.cpu_wants_pd_time[2] ?
- div64_u64(idle_stats.cpu_pg_time[2] * 100,
- idle_stats.cpu_wants_pd_time[2]) : 0),
- (int)(idle_stats.cpu_wants_pd_time[3] ?
- div64_u64(idle_stats.cpu_pg_time[3] * 100,
- idle_stats.cpu_wants_pd_time[3]) : 0),
- (int)(idle_stats.cpu_wants_pd_time[4] ?
- div64_u64(total_c1cpu0_pg_time * 100,
- idle_stats.cpu_wants_pd_time[4]) : 0));
-
- seq_printf(s, "\n");
- seq_printf(s, "rail gating time c0nc gating time c1nc gating time\n");
- seq_printf(s, "%8llu ms %8llu ms %8llu ms\n",
- div64_u64(idle_stats.rail_pd_time, 1000),
- div64_u64(idle_stats.c0nc_pg_time, 1000),
- div64_u64(idle_stats.c1nc_pg_time, 1000));
- seq_printf(s, "%8d%% %8d%% %8d%%\n",
- (int)(idle_stats.cpu_wants_pd_time[0] ?
- div64_u64(idle_stats.rail_pd_time * 100,
- idle_stats.cpu_wants_pd_time[0]) : 0),
- (int)(idle_stats.cpu_wants_pd_time[0] ?
- div64_u64(idle_stats.c0nc_pg_time * 100,
- idle_stats.cpu_wants_pd_time[0]) : 0),
- (int)(idle_stats.cpu_wants_pd_time[4] ?
- div64_u64(idle_stats.c1nc_pg_time * 100,
- idle_stats.cpu_wants_pd_time[4]) : 0));
-
- seq_printf(s, "\n");
-
- seq_printf(s, "%19s %8s %8s %8s\n", "", "rail gating", "comp", "%");
- seq_printf(s, "-------------------------------------------------\n");
- for (bin = 0; bin < 32; bin++) {
- if (idle_stats.rail_gating_bin[bin] == 0)
- continue;
- seq_printf(s, "%6u - %6u ms: %8u %8u %7u%%\n",
- 1 << (bin - 1), 1 << bin,
- idle_stats.rail_gating_bin[bin],
- idle_stats.rail_gating_done_count_bin[bin],
- idle_stats.rail_gating_done_count_bin[bin] * 100 /
- idle_stats.rail_gating_bin[bin]);
- }
- seq_printf(s, "\n");
-
- seq_printf(s, "%19s %8s %8s %8s\n", "", "c0nc gating", "comp", "%");
- seq_printf(s, "-------------------------------------------------\n");
- for (bin = 0; bin < 32; bin++) {
- if (idle_stats.c0nc_gating_bin[bin] == 0)
- continue;
- seq_printf(s, "%6u - %6u ms: %8u %8u %7u%%\n",
- 1 << (bin - 1), 1 << bin,
- idle_stats.c0nc_gating_bin[bin],
- idle_stats.c0nc_gating_done_count_bin[bin],
- idle_stats.c0nc_gating_done_count_bin[bin] * 100 /
- idle_stats.c0nc_gating_bin[bin]);
- }
- seq_printf(s, "\n");
-
- seq_printf(s, "%19s %8s %8s %8s\n", "", "c1nc gating", "comp", "%");
- seq_printf(s, "-------------------------------------------------\n");
- for (bin = 0; bin < 32; bin++) {
- if (idle_stats.c1nc_gating_bin[bin] == 0)
- continue;
- seq_printf(s, "%6u - %6u ms: %8u %8u %7u%%\n",
- 1 << (bin - 1), 1 << bin,
- idle_stats.c1nc_gating_bin[bin],
- idle_stats.c1nc_gating_done_count_bin[bin],
- idle_stats.c1nc_gating_done_count_bin[bin] * 100 /
- idle_stats.c1nc_gating_bin[bin]);
- }
- seq_printf(s, "\n");
-
- seq_printf(s, "%19s %8s %8s %8s\n", "", "mc clk stop", "comp", "%");
- seq_printf(s, "-------------------------------------------------\n");
- for (bin = 0; bin < 32; bin++) {
- if (idle_stats.mc_clk_stop_bin[bin] == 0)
- continue;
- seq_printf(s, "%6u - %6u ms: %8u %8u %7u%%\n",
- 1 << (bin - 1), 1 << bin,
- idle_stats.mc_clk_stop_bin[bin],
- idle_stats.mc_clk_stop_done_count_bin[bin],
- idle_stats.mc_clk_stop_done_count_bin[bin] * 100 /
- idle_stats.mc_clk_stop_bin[bin]);
- }
-
- seq_printf(s, "\n");
- seq_printf(s, "%3s %20s %6s %10s\n",
- "int", "name", "count", "last count");
- seq_printf(s, "--------------------------------------------\n");
- for (i = 0; i < NR_IRQS; i++) {
- if (idle_stats.pd_int_count[i] == 0)
- continue;
- seq_printf(s, "%3d %20s %6d %10d\n",
- i, irq_to_desc(i)->action ?
- irq_to_desc(i)->action->name ?: "???" : "???",
- idle_stats.pd_int_count[i],
- idle_stats.pd_int_count[i] -
- idle_stats.last_pd_int_count[i]);
- idle_stats.last_pd_int_count[i] = idle_stats.pd_int_count[i];
- };
- return 0;
-}
-#endif
-
-int __init tegra14x_cpuidle_init_soc(struct tegra_cpuidle_ops *idle_ops)
-{
- int i;
- struct tegra_cpuidle_ops ops = {
- tegra14x_idle_power_down,
- tegra14x_cpu_idle_stats_pd_ready,
- tegra14x_cpu_idle_stats_pd_time,
- tegra14x_pd_is_allowed,
-#ifdef CONFIG_DEBUG_FS
- tegra14x_pd_debug_show
-#endif
- };
-
- cpu_clk_for_dvfs = tegra_get_clock_by_name("cpu_g");
-#ifdef CONFIG_HAVE_ARM_TWD
- twd_clk = tegra_get_clock_by_name("twd");
-#endif
-
- for (i = 0; i < ARRAY_SIZE(pd_exit_latencies); i++)
- pd_exit_latencies[i] = tegra_pg_exit_latency;
-
- *idle_ops = ops;
-
- return 0;
-}