blob: 77d9669810eda5a9736acc5ac08d3acc22ee9216 [file] [log] [blame]
Andrew Victor907d6de2006-06-20 19:30:19 +01001/*
Andrew Victor9d041262007-02-05 11:42:07 +01002 * arch/arm/mach-at91/pm.c
Andrew Victor907d6de2006-06-20 19:30:19 +01003 * AT91 Power Management
4 *
5 * Copyright (C) 2005 David Brownell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
Rafael J. Wysocki95d9ffb2007-10-18 03:04:39 -070013#include <linux/suspend.h>
Andrew Victor907d6de2006-06-20 19:30:19 +010014#include <linux/sched.h>
15#include <linux/proc_fs.h>
Andrew Victor907d6de2006-06-20 19:30:19 +010016#include <linux/interrupt.h>
17#include <linux/sysfs.h>
18#include <linux/module.h>
19#include <linux/platform_device.h>
20
21#include <asm/io.h>
22#include <asm/irq.h>
23#include <asm/atomic.h>
24#include <asm/mach/time.h>
25#include <asm/mach/irq.h>
26#include <asm/mach-types.h>
27
Andrew Victor55d8bae2006-11-30 17:16:43 +010028#include <asm/arch/at91_pmc.h>
Andrew Victor907d6de2006-06-20 19:30:19 +010029#include <asm/arch/gpio.h>
Andrew Victord481f862006-12-01 11:27:31 +010030#include <asm/arch/cpu.h>
Andrew Victor907d6de2006-06-20 19:30:19 +010031
32#include "generic.h"
33
Andrew Victorf5d0f452008-04-02 21:50:16 +010034#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
Andrew Victor907d6de2006-06-20 19:30:19 +010085
86static int at91_pm_valid_state(suspend_state_t state)
87{
88 switch (state) {
89 case PM_SUSPEND_ON:
90 case PM_SUSPEND_STANDBY:
91 case PM_SUSPEND_MEM:
92 return 1;
93
94 default:
95 return 0;
96 }
97}
98
99
100static suspend_state_t target_state;
101
102/*
103 * Called after processes are frozen, but before we shutdown devices.
104 */
Rafael J. Wysockic697eec2008-01-08 00:04:17 +0100105static int at91_pm_begin(suspend_state_t state)
Andrew Victor907d6de2006-06-20 19:30:19 +0100106{
107 target_state = state;
108 return 0;
109}
110
111/*
112 * Verify that all the clocks are correct before entering
113 * slow-clock mode.
114 */
115static int at91_pm_verify_clocks(void)
116{
117 unsigned long scsr;
118 int i;
119
120 scsr = at91_sys_read(AT91_PMC_SCSR);
121
122 /* USB must not be using PLLB */
Andrew Victord481f862006-12-01 11:27:31 +0100123 if (cpu_is_at91rm9200()) {
124 if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
125 pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
126 return 0;
127 }
Andrew Victorb6b27ae2007-05-31 09:34:53 +0100128 } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
129 if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) {
130 pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
131 return 0;
132 }
Andrew Victor2b3b3512008-01-24 15:10:39 +0100133 } else if (cpu_is_at91cap9()) {
134 if ((scsr & AT91CAP9_PMC_UHP) != 0) {
135 pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
136 return 0;
137 }
Andrew Victor907d6de2006-06-20 19:30:19 +0100138 }
139
140#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
141 /* PCK0..PCK3 must be disabled, or configured to use clk32k */
142 for (i = 0; i < 4; i++) {
143 u32 css;
144
145 if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
146 continue;
147
148 css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
149 if (css != AT91_PMC_CSS_SLOW) {
150 pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
151 return 0;
152 }
153 }
154#endif
155
156 return 1;
157}
158
159/*
160 * Call this from platform driver suspend() to see how deeply to suspend.
161 * For example, some controllers (like OHCI) need one of the PLL clocks
162 * in order to act as a wakeup source, and those are not available when
163 * going into slow clock mode.
164 *
165 * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have
166 * the very same problem (but not using at91 main_clk), and it'd be better
167 * to add one generic API rather than lots of platform-specific ones.
168 */
169int at91_suspend_entering_slow_clock(void)
170{
171 return (target_state == PM_SUSPEND_MEM);
172}
173EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
174
175
176static void (*slow_clock)(void);
177
Andrew Victorf5d0f452008-04-02 21:50:16 +0100178#ifdef CONFIG_AT91_SLOW_CLOCK
179extern void at91_slow_clock(void);
180extern u32 at91_slow_clock_sz;
181#endif
182
Andrew Victor907d6de2006-06-20 19:30:19 +0100183
Andrew Victor907d6de2006-06-20 19:30:19 +0100184static int at91_pm_enter(suspend_state_t state)
185{
186 at91_gpio_suspend();
187 at91_irq_suspend();
188
189 pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
190 /* remember all the always-wake irqs */
191 (at91_sys_read(AT91_PMC_PCSR)
192 | (1 << AT91_ID_FIQ)
193 | (1 << AT91_ID_SYS)
Andrew Victor1f4fd0a2006-11-30 10:01:47 +0100194 | (at91_extern_irq))
Andrew Victor907d6de2006-06-20 19:30:19 +0100195 & at91_sys_read(AT91_AIC_IMR),
196 state);
197
198 switch (state) {
199 /*
200 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
201 * drivers must suspend more deeply: only the master clock
202 * controller may be using the main oscillator.
203 */
204 case PM_SUSPEND_MEM:
205 /*
206 * Ensure that clocks are in a valid state.
207 */
208 if (!at91_pm_verify_clocks())
209 goto error;
210
211 /*
212 * Enter slow clock mode by switching over to clk32k and
213 * turning off the main oscillator; reverse on wakeup.
214 */
215 if (slow_clock) {
Andrew Victorf5d0f452008-04-02 21:50:16 +0100216#ifdef CONFIG_AT91_SLOW_CLOCK
217 /* copy slow_clock handler to SRAM, and call it */
218 memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
219#endif
Andrew Victor907d6de2006-06-20 19:30:19 +0100220 slow_clock();
221 break;
222 } else {
Andrew Victorf5d0f452008-04-02 21:50:16 +0100223 pr_info("AT91: PM - no slow clock mode enabled ...\n");
Andrew Victor907d6de2006-06-20 19:30:19 +0100224 /* FALLTHROUGH leaving master clock alone */
225 }
226
227 /*
228 * STANDBY mode has *all* drivers suspended; ignores irqs not
229 * marked as 'wakeup' event sources; and reduces DRAM power.
230 * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and
231 * nothing fancy done with main or cpu clocks.
232 */
233 case PM_SUSPEND_STANDBY:
234 /*
235 * NOTE: the Wait-for-Interrupt instruction needs to be
Andrew Victorf5d0f452008-04-02 21:50:16 +0100236 * in icache so no SDRAM accesses are needed until the
237 * wakeup IRQ occurs and self-refresh is terminated.
Andrew Victor907d6de2006-06-20 19:30:19 +0100238 */
239 asm("b 1f; .align 5; 1:");
240 asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
Andrew Victorf5d0f452008-04-02 21:50:16 +0100241 sdram_selfrefresh_enable();
242 asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
243 sdram_selfrefresh_disable();
244 break;
Andrew Victor907d6de2006-06-20 19:30:19 +0100245
246 case PM_SUSPEND_ON:
247 asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
248 break;
249
250 default:
251 pr_debug("AT91: PM - bogus suspend state %d\n", state);
252 goto error;
253 }
254
255 pr_debug("AT91: PM - wakeup %08x\n",
256 at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
257
258error:
Andrew Victorf5d0f452008-04-02 21:50:16 +0100259 sdram_selfrefresh_disable();
Andrew Victor907d6de2006-06-20 19:30:19 +0100260 target_state = PM_SUSPEND_ON;
261 at91_irq_resume();
262 at91_gpio_resume();
263 return 0;
264}
265
Rafael J. Wysockic697eec2008-01-08 00:04:17 +0100266/*
267 * Called right prior to thawing processes.
268 */
269static void at91_pm_end(void)
270{
271 target_state = PM_SUSPEND_ON;
272}
273
Andrew Victor907d6de2006-06-20 19:30:19 +0100274
Rafael J. Wysocki26398a72007-10-18 03:04:40 -0700275static struct platform_suspend_ops at91_pm_ops ={
Rafael J. Wysockic697eec2008-01-08 00:04:17 +0100276 .valid = at91_pm_valid_state,
277 .begin = at91_pm_begin,
278 .enter = at91_pm_enter,
279 .end = at91_pm_end,
Andrew Victor907d6de2006-06-20 19:30:19 +0100280};
281
282static int __init at91_pm_init(void)
283{
Andrew Victorf5d0f452008-04-02 21:50:16 +0100284#ifdef CONFIG_AT91_SLOW_CLOCK
285 slow_clock = (void *) (AT91_IO_VIRT_BASE - at91_slow_clock_sz);
Andrew Victor907d6de2006-06-20 19:30:19 +0100286#endif
287
Andrew Victorf5d0f452008-04-02 21:50:16 +0100288 pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
289
290#ifdef CONFIG_ARCH_AT91RM9200
291 /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
Andrew Victor907d6de2006-06-20 19:30:19 +0100292 at91_sys_write(AT91_SDRAMC_LPR, 0);
Andrew Victorf5d0f452008-04-02 21:50:16 +0100293#endif
Andrew Victor907d6de2006-06-20 19:30:19 +0100294
Rafael J. Wysocki26398a72007-10-18 03:04:40 -0700295 suspend_set_ops(&at91_pm_ops);
Andrew Victor907d6de2006-06-20 19:30:19 +0100296
297 return 0;
298}
299arch_initcall(at91_pm_init);