aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/pm.c')
-rw-r--r--arch/arm/mach-tegra/pm.c63
1 files changed, 40 insertions, 23 deletions
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index f55b05a29b55..b0f48a3946fa 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -16,30 +16,32 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18 18
19#include <linux/kernel.h> 19#include <linux/clk/tegra.h>
20#include <linux/spinlock.h>
21#include <linux/io.h>
22#include <linux/cpumask.h> 20#include <linux/cpumask.h>
23#include <linux/delay.h>
24#include <linux/cpu_pm.h> 21#include <linux/cpu_pm.h>
25#include <linux/suspend.h> 22#include <linux/delay.h>
26#include <linux/err.h> 23#include <linux/err.h>
24#include <linux/io.h>
25#include <linux/kernel.h>
27#include <linux/slab.h> 26#include <linux/slab.h>
28#include <linux/clk/tegra.h> 27#include <linux/spinlock.h>
28#include <linux/suspend.h>
29
30#include <soc/tegra/fuse.h>
31#include <soc/tegra/pm.h>
32#include <soc/tegra/pmc.h>
29 33
30#include <asm/smp_plat.h>
31#include <asm/cacheflush.h> 34#include <asm/cacheflush.h>
32#include <asm/suspend.h>
33#include <asm/idmap.h> 35#include <asm/idmap.h>
34#include <asm/proc-fns.h> 36#include <asm/proc-fns.h>
37#include <asm/smp_plat.h>
38#include <asm/suspend.h>
35#include <asm/tlbflush.h> 39#include <asm/tlbflush.h>
36 40
37#include "iomap.h"
38#include "reset.h"
39#include "flowctrl.h" 41#include "flowctrl.h"
40#include "fuse.h" 42#include "iomap.h"
41#include "pm.h" 43#include "pm.h"
42#include "pmc.h" 44#include "reset.h"
43#include "sleep.h" 45#include "sleep.h"
44 46
45#ifdef CONFIG_PM_SLEEP 47#ifdef CONFIG_PM_SLEEP
@@ -53,7 +55,7 @@ static int (*tegra_sleep_func)(unsigned long v2p);
53 55
54static void tegra_tear_down_cpu_init(void) 56static void tegra_tear_down_cpu_init(void)
55{ 57{
56 switch (tegra_chip_id) { 58 switch (tegra_get_chip_id()) {
57 case TEGRA20: 59 case TEGRA20:
58 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) 60 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
59 tegra_tear_down_cpu = tegra20_tear_down_cpu; 61 tegra_tear_down_cpu = tegra20_tear_down_cpu;
@@ -143,7 +145,7 @@ bool tegra_set_cpu_in_lp2(void)
143 145
144 if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask)) 146 if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
145 last_cpu = true; 147 last_cpu = true;
146 else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1) 148 else if (tegra_get_chip_id() == TEGRA20 && phy_cpu_id == 1)
147 tegra20_cpu_set_resettable_soon(); 149 tegra20_cpu_set_resettable_soon();
148 150
149 spin_unlock(&tegra_lp2_lock); 151 spin_unlock(&tegra_lp2_lock);
@@ -166,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
166 return 0; 168 return 0;
167} 169}
168 170
171static void tegra_pm_set(enum tegra_suspend_mode mode)
172{
173 u32 value;
174
175 switch (tegra_get_chip_id()) {
176 case TEGRA20:
177 case TEGRA30:
178 break;
179 default:
180 /* Turn off CRAIL */
181 value = flowctrl_read_cpu_csr(0);
182 value &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
183 value |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
184 flowctrl_write_cpu_csr(0, value);
185 break;
186 }
187
188 tegra_pmc_enter_suspend_mode(mode);
189}
190
169void tegra_idle_lp2_last(void) 191void tegra_idle_lp2_last(void)
170{ 192{
171 tegra_pmc_pm_set(TEGRA_SUSPEND_LP2); 193 tegra_pm_set(TEGRA_SUSPEND_LP2);
172 194
173 cpu_cluster_pm_enter(); 195 cpu_cluster_pm_enter();
174 suspend_cpu_complex(); 196 suspend_cpu_complex();
@@ -212,7 +234,7 @@ static int tegra_sleep_core(unsigned long v2p)
212 */ 234 */
213static bool tegra_lp1_iram_hook(void) 235static bool tegra_lp1_iram_hook(void)
214{ 236{
215 switch (tegra_chip_id) { 237 switch (tegra_get_chip_id()) {
216 case TEGRA20: 238 case TEGRA20:
217 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) 239 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
218 tegra20_lp1_iram_hook(); 240 tegra20_lp1_iram_hook();
@@ -242,7 +264,7 @@ static bool tegra_lp1_iram_hook(void)
242 264
243static bool tegra_sleep_core_init(void) 265static bool tegra_sleep_core_init(void)
244{ 266{
245 switch (tegra_chip_id) { 267 switch (tegra_get_chip_id()) {
246 case TEGRA20: 268 case TEGRA20:
247 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) 269 if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
248 tegra20_sleep_core_init(); 270 tegra20_sleep_core_init();
@@ -267,8 +289,6 @@ static bool tegra_sleep_core_init(void)
267 289
268static void tegra_suspend_enter_lp1(void) 290static void tegra_suspend_enter_lp1(void)
269{ 291{
270 tegra_pmc_suspend();
271
272 /* copy the reset vector & SDRAM shutdown code into IRAM */ 292 /* copy the reset vector & SDRAM shutdown code into IRAM */
273 memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), 293 memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
274 iram_save_size); 294 iram_save_size);
@@ -280,8 +300,6 @@ static void tegra_suspend_enter_lp1(void)
280 300
281static void tegra_suspend_exit_lp1(void) 301static void tegra_suspend_exit_lp1(void)
282{ 302{
283 tegra_pmc_resume();
284
285 /* restore IRAM */ 303 /* restore IRAM */
286 memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr, 304 memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
287 iram_save_size); 305 iram_save_size);
@@ -306,7 +324,7 @@ static int tegra_suspend_enter(suspend_state_t state)
306 324
307 pr_info("Entering suspend state %s\n", lp_state[mode]); 325 pr_info("Entering suspend state %s\n", lp_state[mode]);
308 326
309 tegra_pmc_pm_set(mode); 327 tegra_pm_set(mode);
310 328
311 local_fiq_disable(); 329 local_fiq_disable();
312 330
@@ -354,7 +372,6 @@ void __init tegra_init_suspend(void)
354 return; 372 return;
355 373
356 tegra_tear_down_cpu_init(); 374 tegra_tear_down_cpu_init();
357 tegra_pmc_suspend_init();
358 375
359 if (mode >= TEGRA_SUSPEND_LP1) { 376 if (mode >= TEGRA_SUSPEND_LP1) {
360 if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) { 377 if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {