Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec...
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / arm / mach-shmobile / pm-sh7372.c
blob8e4aadf14c9f45c6d963c93c419ab641a1f03452
1 /*
2 * sh7372 Power management support
4 * Copyright (C) 2011 Magnus Damm
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
11 #include <linux/pm.h>
12 #include <linux/suspend.h>
13 #include <linux/cpuidle.h>
14 #include <linux/module.h>
15 #include <linux/list.h>
16 #include <linux/err.h>
17 #include <linux/slab.h>
18 #include <asm/system.h>
19 #include <asm/io.h>
20 #include <asm/tlbflush.h>
21 #include <mach/common.h>
23 #define SMFRAM 0xe6a70000
24 #define SYSTBCR 0xe6150024
25 #define SBAR 0xe6180020
26 #define APARMBAREA 0xe6f10020
28 static void sh7372_enter_core_standby(void)
30 void __iomem *smfram = (void __iomem *)SMFRAM;
32 __raw_writel(0, APARMBAREA); /* translate 4k */
33 __raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */
34 __raw_writel(0x10, SYSTBCR); /* enable core standby */
36 __raw_writel(0, smfram + 0x3c); /* clear page table address */
38 sh7372_cpu_suspend();
39 cpu_init();
41 /* if page table address is non-NULL then we have been powered down */
42 if (__raw_readl(smfram + 0x3c)) {
43 __raw_writel(__raw_readl(smfram + 0x40),
44 __va(__raw_readl(smfram + 0x3c)));
46 flush_tlb_all();
47 set_cr(__raw_readl(smfram + 0x38));
50 __raw_writel(0, SYSTBCR); /* disable core standby */
51 __raw_writel(0, SBAR); /* disable reset vector translation */
54 #ifdef CONFIG_CPU_IDLE
55 static void sh7372_cpuidle_setup(struct cpuidle_device *dev)
57 struct cpuidle_state *state;
58 int i = dev->state_count;
60 state = &dev->states[i];
61 snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
62 strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
63 state->exit_latency = 10;
64 state->target_residency = 20 + 10;
65 state->power_usage = 1; /* perhaps not */
66 state->flags = 0;
67 state->flags |= CPUIDLE_FLAG_TIME_VALID;
68 shmobile_cpuidle_modes[i] = sh7372_enter_core_standby;
70 dev->state_count = i + 1;
73 static void sh7372_cpuidle_init(void)
75 shmobile_cpuidle_setup = sh7372_cpuidle_setup;
77 #else
78 static void sh7372_cpuidle_init(void) {}
79 #endif
81 #ifdef CONFIG_SUSPEND
82 static int sh7372_enter_suspend(suspend_state_t suspend_state)
84 sh7372_enter_core_standby();
85 return 0;
88 static void sh7372_suspend_init(void)
90 shmobile_suspend_ops.enter = sh7372_enter_suspend;
92 #else
93 static void sh7372_suspend_init(void) {}
94 #endif
96 #define DBGREG1 0xe6100020
97 #define DBGREG9 0xe6100040
99 void __init sh7372_pm_init(void)
101 /* enable DBG hardware block to kick SYSC */
102 __raw_writel(0x0000a500, DBGREG9);
103 __raw_writel(0x0000a501, DBGREG9);
104 __raw_writel(0x00000000, DBGREG1);
106 sh7372_suspend_init();
107 sh7372_cpuidle_init();