root/arch/arm/mach-tegra/cpuidle-tegra30.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tegra30_cpu_cluster_power_down
  2. tegra30_cpu_core_power_down
  3. tegra30_cpu_core_power_down
  4. tegra30_idle_lp2
  5. tegra30_cpuidle_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * CPU idle driver for Tegra CPUs
   4  *
   5  * Copyright (c) 2010-2012, NVIDIA Corporation.
   6  * Copyright (c) 2011 Google, Inc.
   7  * Author: Colin Cross <ccross@android.com>
   8  *         Gary King <gking@nvidia.com>
   9  *
  10  * Rework for 3.3 by Peter De Schrijver <pdeschrijver@nvidia.com>
  11  */
  12 
  13 #include <linux/clk/tegra.h>
  14 #include <linux/tick.h>
  15 #include <linux/cpuidle.h>
  16 #include <linux/cpu_pm.h>
  17 #include <linux/kernel.h>
  18 #include <linux/module.h>
  19 
  20 #include <asm/cpuidle.h>
  21 #include <asm/smp_plat.h>
  22 #include <asm/suspend.h>
  23 
  24 #include "cpuidle.h"
  25 #include "pm.h"
  26 #include "sleep.h"
  27 
  28 #ifdef CONFIG_PM_SLEEP
  29 static int tegra30_idle_lp2(struct cpuidle_device *dev,
  30                             struct cpuidle_driver *drv,
  31                             int index);
  32 #endif
  33 
  34 static struct cpuidle_driver tegra_idle_driver = {
  35         .name = "tegra_idle",
  36         .owner = THIS_MODULE,
  37 #ifdef CONFIG_PM_SLEEP
  38         .state_count = 2,
  39 #else
  40         .state_count = 1,
  41 #endif
  42         .states = {
  43                 [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
  44 #ifdef CONFIG_PM_SLEEP
  45                 [1] = {
  46                         .enter                  = tegra30_idle_lp2,
  47                         .exit_latency           = 2000,
  48                         .target_residency       = 2200,
  49                         .power_usage            = 0,
  50                         .flags                  = CPUIDLE_FLAG_TIMER_STOP,
  51                         .name                   = "powered-down",
  52                         .desc                   = "CPU power gated",
  53                 },
  54 #endif
  55         },
  56 };
  57 
  58 #ifdef CONFIG_PM_SLEEP
  59 static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
  60                                            struct cpuidle_driver *drv,
  61                                            int index)
  62 {
  63         /* All CPUs entering LP2 is not working.
  64          * Don't let CPU0 enter LP2 when any secondary CPU is online.
  65          */
  66         if (num_online_cpus() > 1 || !tegra_cpu_rail_off_ready()) {
  67                 cpu_do_idle();
  68                 return false;
  69         }
  70 
  71         tegra_idle_lp2_last();
  72 
  73         return true;
  74 }
  75 
  76 #ifdef CONFIG_SMP
  77 static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
  78                                         struct cpuidle_driver *drv,
  79                                         int index)
  80 {
  81         smp_wmb();
  82 
  83         cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
  84 
  85         return true;
  86 }
  87 #else
  88 static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
  89                                                struct cpuidle_driver *drv,
  90                                                int index)
  91 {
  92         return true;
  93 }
  94 #endif
  95 
  96 static int tegra30_idle_lp2(struct cpuidle_device *dev,
  97                             struct cpuidle_driver *drv,
  98                             int index)
  99 {
 100         bool entered_lp2 = false;
 101         bool last_cpu;
 102 
 103         local_fiq_disable();
 104 
 105         last_cpu = tegra_set_cpu_in_lp2();
 106         cpu_pm_enter();
 107 
 108         if (dev->cpu == 0) {
 109                 if (last_cpu)
 110                         entered_lp2 = tegra30_cpu_cluster_power_down(dev, drv,
 111                                                                      index);
 112                 else
 113                         cpu_do_idle();
 114         } else {
 115                 entered_lp2 = tegra30_cpu_core_power_down(dev, drv, index);
 116         }
 117 
 118         cpu_pm_exit();
 119         tegra_clear_cpu_in_lp2();
 120 
 121         local_fiq_enable();
 122 
 123         smp_rmb();
 124 
 125         return (entered_lp2) ? index : 0;
 126 }
 127 #endif
 128 
 129 int __init tegra30_cpuidle_init(void)
 130 {
 131         return cpuidle_register(&tegra_idle_driver, NULL);
 132 }

/* [<][>][^][v][top][bottom][index][help] */