pm.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * CPU complex suspend & resume functions for Tegra SoCs
  3. *
  4. * Copyright (c) 2009-2012, NVIDIA Corporation. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <linux/kernel.h>
  19. #include <linux/spinlock.h>
  20. #include <linux/io.h>
  21. #include <linux/cpumask.h>
  22. #include <linux/delay.h>
  23. #include <linux/cpu_pm.h>
  24. #include <linux/suspend.h>
  25. #include <linux/err.h>
  26. #include <linux/clk/tegra.h>
  27. #include <asm/smp_plat.h>
  28. #include <asm/cacheflush.h>
  29. #include <asm/suspend.h>
  30. #include <asm/idmap.h>
  31. #include <asm/proc-fns.h>
  32. #include <asm/tlbflush.h>
  33. #include "iomap.h"
  34. #include "reset.h"
  35. #include "flowctrl.h"
  36. #include "fuse.h"
  37. #include "pmc.h"
  38. #include "sleep.h"
  39. #ifdef CONFIG_PM_SLEEP
  40. static DEFINE_SPINLOCK(tegra_lp2_lock);
  41. void (*tegra_tear_down_cpu)(void);
  42. static void tegra_tear_down_cpu_init(void)
  43. {
  44. switch (tegra_chip_id) {
  45. case TEGRA20:
  46. if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
  47. tegra_tear_down_cpu = tegra20_tear_down_cpu;
  48. break;
  49. case TEGRA30:
  50. case TEGRA114:
  51. if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) ||
  52. IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
  53. tegra_tear_down_cpu = tegra30_tear_down_cpu;
  54. break;
  55. }
  56. }
  57. /*
  58. * restore_cpu_complex
  59. *
  60. * restores cpu clock setting, clears flow controller
  61. *
  62. * Always called on CPU 0.
  63. */
  64. static void restore_cpu_complex(void)
  65. {
  66. int cpu = smp_processor_id();
  67. BUG_ON(cpu != 0);
  68. #ifdef CONFIG_SMP
  69. cpu = cpu_logical_map(cpu);
  70. #endif
  71. /* Restore the CPU clock settings */
  72. tegra_cpu_clock_resume();
  73. flowctrl_cpu_suspend_exit(cpu);
  74. }
  75. /*
  76. * suspend_cpu_complex
  77. *
  78. * saves pll state for use by restart_plls, prepares flow controller for
  79. * transition to suspend state
  80. *
  81. * Must always be called on cpu 0.
  82. */
  83. static void suspend_cpu_complex(void)
  84. {
  85. int cpu = smp_processor_id();
  86. BUG_ON(cpu != 0);
  87. #ifdef CONFIG_SMP
  88. cpu = cpu_logical_map(cpu);
  89. #endif
  90. /* Save the CPU clock settings */
  91. tegra_cpu_clock_suspend();
  92. flowctrl_cpu_suspend_enter(cpu);
  93. }
  94. void tegra_clear_cpu_in_lp2(void)
  95. {
  96. int phy_cpu_id = cpu_logical_map(smp_processor_id());
  97. u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
  98. spin_lock(&tegra_lp2_lock);
  99. BUG_ON(!(*cpu_in_lp2 & BIT(phy_cpu_id)));
  100. *cpu_in_lp2 &= ~BIT(phy_cpu_id);
  101. spin_unlock(&tegra_lp2_lock);
  102. }
  103. bool tegra_set_cpu_in_lp2(void)
  104. {
  105. int phy_cpu_id = cpu_logical_map(smp_processor_id());
  106. bool last_cpu = false;
  107. cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
  108. u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
  109. spin_lock(&tegra_lp2_lock);
  110. BUG_ON((*cpu_in_lp2 & BIT(phy_cpu_id)));
  111. *cpu_in_lp2 |= BIT(phy_cpu_id);
  112. if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
  113. last_cpu = true;
  114. else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1)
  115. tegra20_cpu_set_resettable_soon();
  116. spin_unlock(&tegra_lp2_lock);
  117. return last_cpu;
  118. }
  119. int tegra_cpu_do_idle(void)
  120. {
  121. return cpu_do_idle();
  122. }
  123. static int tegra_sleep_cpu(unsigned long v2p)
  124. {
  125. setup_mm_for_reboot();
  126. tegra_sleep_cpu_finish(v2p);
  127. /* should never here */
  128. BUG();
  129. return 0;
  130. }
  131. void tegra_idle_lp2_last(void)
  132. {
  133. tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
  134. cpu_cluster_pm_enter();
  135. suspend_cpu_complex();
  136. cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
  137. restore_cpu_complex();
  138. cpu_cluster_pm_exit();
  139. }
  140. enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
  141. enum tegra_suspend_mode mode)
  142. {
  143. /* Tegra114 didn't support any suspending mode yet. */
  144. if (tegra_chip_id == TEGRA114)
  145. return TEGRA_SUSPEND_NONE;
  146. /*
  147. * The Tegra devices only support suspending to LP2 currently.
  148. */
  149. if (mode > TEGRA_SUSPEND_LP2)
  150. return TEGRA_SUSPEND_LP2;
  151. return mode;
  152. }
  153. static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {
  154. [TEGRA_SUSPEND_NONE] = "none",
  155. [TEGRA_SUSPEND_LP2] = "LP2",
  156. [TEGRA_SUSPEND_LP1] = "LP1",
  157. [TEGRA_SUSPEND_LP0] = "LP0",
  158. };
  159. static int __cpuinit tegra_suspend_enter(suspend_state_t state)
  160. {
  161. enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
  162. if (WARN_ON(mode < TEGRA_SUSPEND_NONE ||
  163. mode >= TEGRA_MAX_SUSPEND_MODE))
  164. return -EINVAL;
  165. pr_info("Entering suspend state %s\n", lp_state[mode]);
  166. tegra_pmc_pm_set(mode);
  167. local_fiq_disable();
  168. suspend_cpu_complex();
  169. switch (mode) {
  170. case TEGRA_SUSPEND_LP2:
  171. tegra_set_cpu_in_lp2();
  172. break;
  173. default:
  174. break;
  175. }
  176. cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
  177. switch (mode) {
  178. case TEGRA_SUSPEND_LP2:
  179. tegra_clear_cpu_in_lp2();
  180. break;
  181. default:
  182. break;
  183. }
  184. restore_cpu_complex();
  185. local_fiq_enable();
  186. return 0;
  187. }
  188. static const struct platform_suspend_ops tegra_suspend_ops = {
  189. .valid = suspend_valid_only_mem,
  190. .enter = tegra_suspend_enter,
  191. };
  192. void __init tegra_init_suspend(void)
  193. {
  194. if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)
  195. return;
  196. tegra_tear_down_cpu_init();
  197. tegra_pmc_suspend_init();
  198. suspend_set_ops(&tegra_suspend_ops);
  199. }
  200. #endif