diff options
Diffstat (limited to 'arch/arm/mach-s3c2410/pm.c')
-rw-r--r-- | arch/arm/mach-s3c2410/pm.c | 72 |
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 | ||
56 | unsigned long s3c_pm_flags; | 54 | unsigned long s3c_pm_flags; |
57 | 55 | ||
58 | /* cache functions from arch/arm/mm/proc-arm920.S */ | ||
59 | |||
60 | #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH | ||
61 | extern void arm920_flush_kern_cache_all(void); | ||
62 | #else | ||
63 | static void arm920_flush_kern_cache_all(void) { } | ||
64 | #endif | ||
65 | |||
66 | #define PFX "s3c24xx-pm: " | 56 | #define PFX "s3c24xx-pm: " |
67 | 57 | ||
68 | static struct sleep_save core_save[] = { | 58 | static 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 */ | ||
96 | static 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 | |||
108 | static struct sleep_save gpio_save[] = { | 85 | static 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 | ||
166 | extern void printascii(const char *); | 143 | extern void printascii(const char *); |
167 | 144 | ||
168 | static void pm_dbg(const char *fmt, ...) | 145 | void 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 | ||
489 | void (*pm_cpu_prep)(void); | ||
490 | void (*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) | |||
519 | static int s3c2410_pm_enter(suspend_state_t state) | 499 | static 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(); |