aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2410/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-s3c2410/pm.c')
-rw-r--r--arch/arm/mach-s3c2410/pm.c72
1 files changed, 27 insertions, 45 deletions
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index a589fe76d915..b49a0b3b72b3 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -1,9 +1,9 @@
1/* linux/arch/arm/mach-s3c2410/pm.c 1/* linux/arch/arm/mach-s3c2410/pm.c
2 * 2 *
3 * Copyright (c) 2004 Simtec Electronics 3 * Copyright (c) 2004,2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * S3C2410 Power Manager (Suspend-To-RAM) support 6 * S3C24XX Power Manager (Suspend-To-RAM) support
7 * 7 *
8 * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information 8 * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
9 * 9 *
@@ -24,9 +24,6 @@
24 * Parts based on arch/arm/mach-pxa/pm.c 24 * Parts based on arch/arm/mach-pxa/pm.c
25 * 25 *
26 * Thanks to Dimitry Andric for debugging 26 * Thanks to Dimitry Andric for debugging
27 *
28 * Modifications:
29 * 10-Mar-2005 LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART
30*/ 27*/
31 28
32#include <linux/init.h> 29#include <linux/init.h>
@@ -38,6 +35,7 @@
38#include <linux/ioport.h> 35#include <linux/ioport.h>
39#include <linux/delay.h> 36#include <linux/delay.h>
40 37
38#include <asm/cacheflush.h>
41#include <asm/hardware.h> 39#include <asm/hardware.h>
42#include <asm/io.h> 40#include <asm/io.h>
43 41
@@ -55,14 +53,6 @@
55 53
56unsigned long s3c_pm_flags; 54unsigned long s3c_pm_flags;
57 55
58/* cache functions from arch/arm/mm/proc-arm920.S */
59
60#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
61extern void arm920_flush_kern_cache_all(void);
62#else
63static void arm920_flush_kern_cache_all(void) { }
64#endif
65
66#define PFX "s3c24xx-pm: " 56#define PFX "s3c24xx-pm: "
67 57
68static struct sleep_save core_save[] = { 58static struct sleep_save core_save[] = {
@@ -92,19 +82,6 @@ static struct sleep_save core_save[] = {
92 SAVE_ITEM(S3C2410_REFRESH), 82 SAVE_ITEM(S3C2410_REFRESH),
93}; 83};
94 84
95/* this lot should be really saved by the IRQ code */
96static struct sleep_save irq_save[] = {
97 SAVE_ITEM(S3C2410_EXTINT0),
98 SAVE_ITEM(S3C2410_EXTINT1),
99 SAVE_ITEM(S3C2410_EXTINT2),
100 SAVE_ITEM(S3C2410_EINFLT0),
101 SAVE_ITEM(S3C2410_EINFLT1),
102 SAVE_ITEM(S3C2410_EINFLT2),
103 SAVE_ITEM(S3C2410_EINFLT3),
104 SAVE_ITEM(S3C2410_EINTMASK),
105 SAVE_ITEM(S3C2410_INTMSK)
106};
107
108static struct sleep_save gpio_save[] = { 85static struct sleep_save gpio_save[] = {
109 SAVE_ITEM(S3C2410_GPACON), 86 SAVE_ITEM(S3C2410_GPACON),
110 SAVE_ITEM(S3C2410_GPADAT), 87 SAVE_ITEM(S3C2410_GPADAT),
@@ -165,7 +142,7 @@ static struct sleep_save uart_save[] = {
165 142
166extern void printascii(const char *); 143extern void printascii(const char *);
167 144
168static void pm_dbg(const char *fmt, ...) 145void pm_dbg(const char *fmt, ...)
169{ 146{
170 va_list va; 147 va_list va;
171 char buff[256]; 148 char buff[256];
@@ -509,6 +486,9 @@ static void s3c2410_pm_configure_extint(void)
509 } 486 }
510} 487}
511 488
489void (*pm_cpu_prep)(void);
490void (*pm_cpu_sleep)(void);
491
512#define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) 492#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
513 493
514/* s3c2410_pm_enter 494/* s3c2410_pm_enter
@@ -519,7 +499,6 @@ static void s3c2410_pm_configure_extint(void)
519static int s3c2410_pm_enter(suspend_state_t state) 499static int s3c2410_pm_enter(suspend_state_t state)
520{ 500{
521 unsigned long regs_save[16]; 501 unsigned long regs_save[16];
522 unsigned long tmp;
523 502
524 /* ensure the debug is initialised (if enabled) */ 503 /* ensure the debug is initialised (if enabled) */
525 504
@@ -527,6 +506,11 @@ static int s3c2410_pm_enter(suspend_state_t state)
527 506
528 DBG("s3c2410_pm_enter(%d)\n", state); 507 DBG("s3c2410_pm_enter(%d)\n", state);
529 508
509 if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
510 printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
511 return -EINVAL;
512 }
513
530 if (state != PM_SUSPEND_MEM) { 514 if (state != PM_SUSPEND_MEM) {
531 printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n"); 515 printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
532 return -EINVAL; 516 return -EINVAL;
@@ -554,17 +538,9 @@ static int s3c2410_pm_enter(suspend_state_t state)
554 538
555 DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys); 539 DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
556 540
557 /* ensure at least GESTATUS3 has the resume address */
558
559 __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
560
561 DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
562 DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
563
564 /* save all necessary core registers not covered by the drivers */ 541 /* save all necessary core registers not covered by the drivers */
565 542
566 s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); 543 s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
567 s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
568 s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save)); 544 s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
569 s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); 545 s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
570 546
@@ -581,10 +557,16 @@ static int s3c2410_pm_enter(suspend_state_t state)
581 /* ack any outstanding external interrupts before we go to sleep */ 557 /* ack any outstanding external interrupts before we go to sleep */
582 558
583 __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND); 559 __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
560 __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
561 __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
562
563 /* call cpu specific preperation */
564
565 pm_cpu_prep();
584 566
585 /* flush cache back to ram */ 567 /* flush cache back to ram */
586 568
587 arm920_flush_kern_cache_all(); 569 flush_cache_all();
588 570
589 s3c2410_pm_check_store(); 571 s3c2410_pm_check_store();
590 572
@@ -592,23 +574,23 @@ static int s3c2410_pm_enter(suspend_state_t state)
592 574
593 __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */ 575 __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
594 576
595 s3c2410_cpu_suspend(regs_save); 577 /* s3c2410_cpu_save will also act as our return point from when
578 * we resume as it saves its own register state, so use the return
579 * code to differentiate return from save and return from sleep */
580
581 if (s3c2410_cpu_save(regs_save) == 0) {
582 flush_cache_all();
583 pm_cpu_sleep();
584 }
596 585
597 /* restore the cpu state */ 586 /* restore the cpu state */
598 587
599 cpu_init(); 588 cpu_init();
600 589
601 /* unset the return-from-sleep flag, to ensure reset */
602
603 tmp = __raw_readl(S3C2410_GSTATUS2);
604 tmp &= S3C2410_GSTATUS2_OFFRESET;
605 __raw_writel(tmp, S3C2410_GSTATUS2);
606
607 /* restore the system state */ 590 /* restore the system state */
608 591
609 s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); 592 s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
610 s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); 593 s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
611 s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
612 s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); 594 s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
613 595
614 s3c2410_pm_debug_init(); 596 s3c2410_pm_debug_init();