aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/pxa3xx.c
diff options
context:
space:
mode:
authoreric miao <eric.miao@marvell.com>2008-01-28 18:00:02 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-02-04 08:17:33 -0500
commitc4d1fb627ff307256d792280efcb09e1235affea (patch)
tree260ed71dd94883353de1e9256d3d7337d0a7b81a /arch/arm/mach-pxa/pxa3xx.c
parent16dfdbf038706c12c56f327d14c6b901edc376a3 (diff)
[ARM] pxa: add preliminary suspend/resume code for pxa3xx
1. clear RDH bit after resuming back from D3, otherwise, the multi function pins will retain the low power state 2. save/restore essential system registers Signed-off-by: eric miao <eric.miao@marvell.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pxa/pxa3xx.c')
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c73
1 files changed, 59 insertions, 14 deletions
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index d0b2afd4368a..e47e67c11afe 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -40,6 +40,7 @@
40#define RO_CLK 60000000 40#define RO_CLK 60000000
41 41
42#define ACCR_D0CS (1 << 26) 42#define ACCR_D0CS (1 << 26)
43#define ACCR_PCCE (1 << 11)
43 44
44/* crystal frequency to static memory controller multiplier (SMCFS) */ 45/* crystal frequency to static memory controller multiplier (SMCFS) */
45static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, }; 46static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
@@ -204,7 +205,6 @@ static struct clk pxa3xx_clks[] = {
204}; 205};
205 206
206#ifdef CONFIG_PM 207#ifdef CONFIG_PM
207#define SLEEP_SAVE_SIZE 4
208 208
209#define ISRAM_START 0x5c000000 209#define ISRAM_START 0x5c000000
210#define ISRAM_SIZE SZ_256K 210#define ISRAM_SIZE SZ_256K
@@ -212,25 +212,29 @@ static struct clk pxa3xx_clks[] = {
212static void __iomem *sram; 212static void __iomem *sram;
213static unsigned long wakeup_src; 213static unsigned long wakeup_src;
214 214
215static void pxa3xx_cpu_pm_save(unsigned long *sleep_save) 215#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
216{ 216#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
217 pr_debug("PM: CKENA=%08x CKENB=%08x\n", CKENA, CKENB);
218 217
219 if (CKENA & (1 << CKEN_USBH)) { 218enum { SLEEP_SAVE_START = 0,
220 printk(KERN_ERR "PM: USB host clock not stopped?\n"); 219 SLEEP_SAVE_CKENA,
221 CKENA &= ~(1 << CKEN_USBH); 220 SLEEP_SAVE_CKENB,
222 } 221 SLEEP_SAVE_ACCR,
223// CKENA |= 1 << (CKEN_ISC & 31);
224 222
225 /* 223 SLEEP_SAVE_SIZE,
226 * Low power modes require the HSIO2 clock to be enabled. 224};
227 */ 225
228 CKENB |= 1 << (CKEN_HSIO2 & 31); 226static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
227{
228 SAVE(CKENA);
229 SAVE(CKENB);
230 SAVE(ACCR);
229} 231}
230 232
231static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save) 233static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save)
232{ 234{
233 CKENB &= ~(1 << (CKEN_HSIO2 & 31)); 235 RESTORE(ACCR);
236 RESTORE(CKENA);
237 RESTORE(CKENB);
234} 238}
235 239
236/* 240/*
@@ -266,6 +270,46 @@ static void pxa3xx_cpu_standby(unsigned int pwrmode)
266 printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR); 270 printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR);
267} 271}
268 272
273/*
274 * NOTE: currently, the OBM (OEM Boot Module) binary comes along with
275 * PXA3xx development kits assumes that the resuming process continues
276 * with the address stored within the first 4 bytes of SDRAM. The PSPR
277 * register is used privately by BootROM and OBM, and _must_ be set to
278 * 0x5c014000 for the moment.
279 */
280static void pxa3xx_cpu_pm_suspend(void)
281{
282 volatile unsigned long *p = (volatile void *)0xc0000000;
283 unsigned long saved_data = *p;
284
285 extern void pxa3xx_cpu_suspend(void);
286 extern void pxa3xx_cpu_resume(void);
287
288 /* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
289 CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
290 CKENB |= 1 << (CKEN_HSIO2 & 0x1f);
291
292 /* clear and setup wakeup source */
293 AD3SR = ~0;
294 AD3ER = wakeup_src;
295 ASCR = ASCR;
296 ARSR = ARSR;
297
298 PCFR |= (1u << 13); /* L1_DIS */
299 PCFR &= ~((1u << 12) | (1u << 1)); /* L0_EN | SL_ROD */
300
301 PSPR = 0x5c014000;
302
303 /* overwrite with the resume address */
304 *p = virt_to_phys(pxa3xx_cpu_resume);
305
306 pxa3xx_cpu_suspend();
307
308 *p = saved_data;
309
310 AD3ER = 0;
311}
312
269static void pxa3xx_cpu_pm_enter(suspend_state_t state) 313static void pxa3xx_cpu_pm_enter(suspend_state_t state)
270{ 314{
271 /* 315 /*
@@ -280,6 +324,7 @@ static void pxa3xx_cpu_pm_enter(suspend_state_t state)
280 break; 324 break;
281 325
282 case PM_SUSPEND_MEM: 326 case PM_SUSPEND_MEM:
327 pxa3xx_cpu_pm_suspend();
283 break; 328 break;
284 } 329 }
285} 330}