pm.c (0337c3e0c3cbbb3a4f411c292f52fcc314abae67) | pm.c (c8c2e6069065fdecfb195a2c438c7faa964aef22) |
---|---|
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. --- 8 unchanged lines hidden (view full) --- 17 */ 18 19#include <linux/kernel.h> 20#include <linux/spinlock.h> 21#include <linux/io.h> 22#include <linux/cpumask.h> 23#include <linux/delay.h> 24#include <linux/cpu_pm.h> | 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. --- 8 unchanged lines hidden (view full) --- 17 */ 18 19#include <linux/kernel.h> 20#include <linux/spinlock.h> 21#include <linux/io.h> 22#include <linux/cpumask.h> 23#include <linux/delay.h> 24#include <linux/cpu_pm.h> |
25#include <linux/suspend.h> |
|
25#include <linux/err.h> 26#include <linux/clk/tegra.h> 27 28#include <asm/smp_plat.h> 29#include <asm/cacheflush.h> 30#include <asm/suspend.h> 31#include <asm/idmap.h> 32#include <asm/proc-fns.h> 33#include <asm/tlbflush.h> 34 35#include "iomap.h" 36#include "reset.h" 37#include "flowctrl.h" 38#include "fuse.h" 39#include "pmc.h" 40#include "sleep.h" | 26#include <linux/err.h> 27#include <linux/clk/tegra.h> 28 29#include <asm/smp_plat.h> 30#include <asm/cacheflush.h> 31#include <asm/suspend.h> 32#include <asm/idmap.h> 33#include <asm/proc-fns.h> 34#include <asm/tlbflush.h> 35 36#include "iomap.h" 37#include "reset.h" 38#include "flowctrl.h" 39#include "fuse.h" 40#include "pmc.h" 41#include "sleep.h" |
42#include "pmc.h" |
|
41 | 43 |
42#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */ 43 44#define PMC_CTRL 0x0 45 | |
46#ifdef CONFIG_PM_SLEEP 47static DEFINE_SPINLOCK(tegra_lp2_lock); | 44#ifdef CONFIG_PM_SLEEP 45static DEFINE_SPINLOCK(tegra_lp2_lock); |
48static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); | |
49void (*tegra_tear_down_cpu)(void); 50 51/* 52 * restore_cpu_complex 53 * 54 * restores cpu clock setting, clears flow controller 55 * 56 * Always called on CPU 0. --- 83 unchanged lines hidden (view full) --- 140 /* should never here */ 141 BUG(); 142 143 return 0; 144} 145 146void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time) 147{ | 46void (*tegra_tear_down_cpu)(void); 47 48/* 49 * restore_cpu_complex 50 * 51 * restores cpu clock setting, clears flow controller 52 * 53 * Always called on CPU 0. --- 83 unchanged lines hidden (view full) --- 137 /* should never here */ 138 BUG(); 139 140 return 0; 141} 142 143void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time) 144{ |
148 u32 mode; | 145 tegra_pmc_pm_set(TEGRA_SUSPEND_LP2); |
149 | 146 |
150 /* Only the last cpu down does the final suspend steps */ 151 mode = readl(pmc + PMC_CTRL); 152 mode |= TEGRA_POWER_CPU_PWRREQ_OE; 153 writel(mode, pmc + PMC_CTRL); 154 155 set_power_timers(cpu_on_time, cpu_off_time); 156 | |
157 cpu_cluster_pm_enter(); 158 suspend_cpu_complex(); 159 160 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu); 161 162 restore_cpu_complex(); 163 cpu_cluster_pm_exit(); 164} | 147 cpu_cluster_pm_enter(); 148 suspend_cpu_complex(); 149 150 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu); 151 152 restore_cpu_complex(); 153 cpu_cluster_pm_exit(); 154} |
155 156enum tegra_suspend_mode tegra_pm_validate_suspend_mode( 157 enum tegra_suspend_mode mode) 158{ 159 /* Tegra114 didn't support any suspending mode yet. */ 160 if (tegra_chip_id == TEGRA114) 161 return TEGRA_SUSPEND_NONE; 162 163 /* 164 * The Tegra devices only support suspending to LP2 currently. 165 */ 166 if (mode > TEGRA_SUSPEND_LP2) 167 return TEGRA_SUSPEND_LP2; 168 169 return mode; 170} 171 172static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = { 173 [TEGRA_SUSPEND_NONE] = "none", 174 [TEGRA_SUSPEND_LP2] = "LP2", 175 [TEGRA_SUSPEND_LP1] = "LP1", 176 [TEGRA_SUSPEND_LP0] = "LP0", 177}; 178 179static int __cpuinit tegra_suspend_enter(suspend_state_t state) 180{ 181 enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode(); 182 183 if (WARN_ON(mode < TEGRA_SUSPEND_NONE || 184 mode >= TEGRA_MAX_SUSPEND_MODE)) 185 return -EINVAL; 186 187 pr_info("Entering suspend state %s\n", lp_state[mode]); 188 189 tegra_pmc_pm_set(mode); 190 191 local_fiq_disable(); 192 193 suspend_cpu_complex(); 194 switch (mode) { 195 case TEGRA_SUSPEND_LP2: 196 tegra_set_cpu_in_lp2(0); 197 break; 198 default: 199 break; 200 } 201 202 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu); 203 204 switch (mode) { 205 case TEGRA_SUSPEND_LP2: 206 tegra_clear_cpu_in_lp2(0); 207 break; 208 default: 209 break; 210 } 211 restore_cpu_complex(); 212 213 local_fiq_enable(); 214 215 return 0; 216} 217 218static const struct platform_suspend_ops tegra_suspend_ops = { 219 .valid = suspend_valid_only_mem, 220 .enter = tegra_suspend_enter, 221}; 222 223void __init tegra_init_suspend(void) 224{ 225 if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE) 226 return; 227 228 tegra_pmc_suspend_init(); 229 230 suspend_set_ops(&tegra_suspend_ops); 231} |
|
165#endif | 232#endif |