aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-at91/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-at91/pm.c')
-rw-r--r--arch/arm/mach-at91/pm.c165
1 files changed, 149 insertions, 16 deletions
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index a67defd50438..39733b6992aa 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -26,12 +26,135 @@
26#include <asm/mach-types.h> 26#include <asm/mach-types.h>
27 27
28#include <asm/arch/at91_pmc.h> 28#include <asm/arch/at91_pmc.h>
29#include <asm/arch/at91rm9200_mc.h>
30#include <asm/arch/gpio.h> 29#include <asm/arch/gpio.h>
31#include <asm/arch/cpu.h> 30#include <asm/arch/cpu.h>
32 31
33#include "generic.h" 32#include "generic.h"
34 33
34#ifdef CONFIG_ARCH_AT91RM9200
35#include <asm/arch/at91rm9200_mc.h>
36
37/*
38 * The AT91RM9200 goes into self-refresh mode with this command, and will
39 * terminate self-refresh automatically on the next SDRAM access.
40 */
41#define sdram_selfrefresh_enable() at91_sys_write(AT91_SDRAMC_SRR, 1)
42#define sdram_selfrefresh_disable() do {} while (0)
43
44#elif defined(CONFIG_ARCH_AT91CAP9)
45#include <asm/arch/at91cap9_ddrsdr.h>
46
47static u32 saved_lpr;
48
49static inline void sdram_selfrefresh_enable(void)
50{
51 u32 lpr;
52
53 saved_lpr = at91_sys_read(AT91_DDRSDRC_LPR);
54
55 lpr = saved_lpr & ~AT91_DDRSDRC_LPCB;
56 at91_sys_write(AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
57}
58
59#define sdram_selfrefresh_disable() at91_sys_write(AT91_DDRSDRC_LPR, saved_lpr)
60
61#else
62#include <asm/arch/at91sam9_sdramc.h>
63
64static u32 saved_lpr;
65
66static inline void sdram_selfrefresh_enable(void)
67{
68 u32 lpr;
69
70 saved_lpr = at91_sys_read(AT91_SDRAMC_LPR);
71
72 lpr = saved_lpr & ~AT91_SDRAMC_LPCB;
73 at91_sys_write(AT91_SDRAMC_LPR, lpr | AT91_SDRAMC_LPCB_SELF_REFRESH);
74}
75
76#define sdram_selfrefresh_disable() at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
77
78/*
79 * FIXME: The AT91SAM9263 has a second EBI controller which may have
80 * additional SDRAM. pm_slowclock.S will require a similar fix.
81 */
82
83#endif
84
85
86/*
87 * Show the reason for the previous system reset.
88 */
89#if defined(AT91_SHDWC)
90
91#include <asm/arch/at91_rstc.h>
92#include <asm/arch/at91_shdwc.h>
93
94static void __init show_reset_status(void)
95{
96 static char reset[] __initdata = "reset";
97
98 static char general[] __initdata = "general";
99 static char wakeup[] __initdata = "wakeup";
100 static char watchdog[] __initdata = "watchdog";
101 static char software[] __initdata = "software";
102 static char user[] __initdata = "user";
103 static char unknown[] __initdata = "unknown";
104
105 static char signal[] __initdata = "signal";
106 static char rtc[] __initdata = "rtc";
107 static char rtt[] __initdata = "rtt";
108 static char restore[] __initdata = "power-restored";
109
110 char *reason, *r2 = reset;
111 u32 reset_type, wake_type;
112
113 reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
114 wake_type = at91_sys_read(AT91_SHDW_SR);
115
116 switch (reset_type) {
117 case AT91_RSTC_RSTTYP_GENERAL:
118 reason = general;
119 break;
120 case AT91_RSTC_RSTTYP_WAKEUP:
121 /* board-specific code enabled the wakeup sources */
122 reason = wakeup;
123
124 /* "wakeup signal" */
125 if (wake_type & AT91_SHDW_WAKEUP0)
126 r2 = signal;
127 else {
128 r2 = reason;
129 if (wake_type & AT91_SHDW_RTTWK) /* rtt wakeup */
130 reason = rtt;
131 else if (wake_type & AT91_SHDW_RTCWK) /* rtc wakeup */
132 reason = rtc;
133 else if (wake_type == 0) /* power-restored wakeup */
134 reason = restore;
135 else /* unknown wakeup */
136 reason = unknown;
137 }
138 break;
139 case AT91_RSTC_RSTTYP_WATCHDOG:
140 reason = watchdog;
141 break;
142 case AT91_RSTC_RSTTYP_SOFTWARE:
143 reason = software;
144 break;
145 case AT91_RSTC_RSTTYP_USER:
146 reason = user;
147 break;
148 default:
149 reason = unknown;
150 break;
151 }
152 pr_info("AT91: Starting after %s %s\n", reason, r2);
153}
154#else
155static void __init show_reset_status(void) {}
156#endif
157
35 158
36static int at91_pm_valid_state(suspend_state_t state) 159static int at91_pm_valid_state(suspend_state_t state)
37{ 160{
@@ -125,6 +248,11 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
125 248
126static void (*slow_clock)(void); 249static void (*slow_clock)(void);
127 250
251#ifdef CONFIG_AT91_SLOW_CLOCK
252extern void at91_slow_clock(void);
253extern u32 at91_slow_clock_sz;
254#endif
255
128 256
129static int at91_pm_enter(suspend_state_t state) 257static int at91_pm_enter(suspend_state_t state)
130{ 258{
@@ -158,11 +286,14 @@ static int at91_pm_enter(suspend_state_t state)
158 * turning off the main oscillator; reverse on wakeup. 286 * turning off the main oscillator; reverse on wakeup.
159 */ 287 */
160 if (slow_clock) { 288 if (slow_clock) {
289#ifdef CONFIG_AT91_SLOW_CLOCK
290 /* copy slow_clock handler to SRAM, and call it */
291 memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
292#endif
161 slow_clock(); 293 slow_clock();
162 break; 294 break;
163 } else { 295 } else {
164 /* DEVELOPMENT ONLY */ 296 pr_info("AT91: PM - no slow clock mode enabled ...\n");
165 pr_info("AT91: PM - no slow clock mode yet ...\n");
166 /* FALLTHROUGH leaving master clock alone */ 297 /* FALLTHROUGH leaving master clock alone */
167 } 298 }
168 299
@@ -175,13 +306,15 @@ static int at91_pm_enter(suspend_state_t state)
175 case PM_SUSPEND_STANDBY: 306 case PM_SUSPEND_STANDBY:
176 /* 307 /*
177 * NOTE: the Wait-for-Interrupt instruction needs to be 308 * NOTE: the Wait-for-Interrupt instruction needs to be
178 * in icache so the SDRAM stays in self-refresh mode until 309 * in icache so no SDRAM accesses are needed until the
179 * the wakeup IRQ occurs. 310 * wakeup IRQ occurs and self-refresh is terminated.
180 */ 311 */
181 asm("b 1f; .align 5; 1:"); 312 asm("b 1f; .align 5; 1:");
182 asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ 313 asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
183 at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */ 314 sdram_selfrefresh_enable();
184 /* fall though to next state */ 315 asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
316 sdram_selfrefresh_disable();
317 break;
185 318
186 case PM_SUSPEND_ON: 319 case PM_SUSPEND_ON:
187 asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */ 320 asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
@@ -196,6 +329,7 @@ static int at91_pm_enter(suspend_state_t state)
196 at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); 329 at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
197 330
198error: 331error:
332 sdram_selfrefresh_disable();
199 target_state = PM_SUSPEND_ON; 333 target_state = PM_SUSPEND_ON;
200 at91_irq_resume(); 334 at91_irq_resume();
201 at91_gpio_resume(); 335 at91_gpio_resume();
@@ -220,21 +354,20 @@ static struct platform_suspend_ops at91_pm_ops ={
220 354
221static int __init at91_pm_init(void) 355static int __init at91_pm_init(void)
222{ 356{
223 printk("AT91: Power Management\n"); 357#ifdef CONFIG_AT91_SLOW_CLOCK
224 358 slow_clock = (void *) (AT91_IO_VIRT_BASE - at91_slow_clock_sz);
225#ifdef CONFIG_AT91_PM_SLOW_CLOCK
226 /* REVISIT allocations of SRAM should be dynamically managed.
227 * FIQ handlers and other components will want SRAM/TCM too...
228 */
229 slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
230 memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
231#endif 359#endif
232 360
233 /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */ 361 pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
362
363#ifdef CONFIG_ARCH_AT91RM9200
364 /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
234 at91_sys_write(AT91_SDRAMC_LPR, 0); 365 at91_sys_write(AT91_SDRAMC_LPR, 0);
366#endif
235 367
236 suspend_set_ops(&at91_pm_ops); 368 suspend_set_ops(&at91_pm_ops);
237 369
370 show_reset_status();
238 return 0; 371 return 0;
239} 372}
240arch_initcall(at91_pm_init); 373arch_initcall(at91_pm_init);