diff options
Diffstat (limited to 'arch/arm/mach-s3c2410')
-rw-r--r-- | arch/arm/mach-s3c2410/Kconfig | 9 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/pm.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/pm.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-pm.c | 111 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-sleep.S | 68 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/sleep.S | 33 |
7 files changed, 209 insertions, 49 deletions
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 61a359c4aa47..e555bc5f3029 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig | |||
@@ -133,6 +133,12 @@ config S3C2410_CLOCK | |||
133 | help | 133 | help |
134 | Clock code for the S3C2410, and similar processors | 134 | Clock code for the S3C2410, and similar processors |
135 | 135 | ||
136 | config S3C2410_PM | ||
137 | bool | ||
138 | depends on CONFIG_PM | ||
139 | help | ||
140 | Power Management code common to S3C2410 and better | ||
141 | |||
136 | config CPU_S3C2410_DMA | 142 | config CPU_S3C2410_DMA |
137 | bool | 143 | bool |
138 | depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442) | 144 | depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442) |
@@ -144,6 +150,7 @@ config CPU_S3C2410 | |||
144 | bool | 150 | bool |
145 | depends on ARCH_S3C2410 | 151 | depends on ARCH_S3C2410 |
146 | select S3C2410_CLOCK | 152 | select S3C2410_CLOCK |
153 | select S3C2410_PM | ||
147 | help | 154 | help |
148 | Support for S3C2410 and S3C2410A family from the S3C24XX line | 155 | Support for S3C2410 and S3C2410A family from the S3C24XX line |
149 | of Samsung Mobile CPUs. | 156 | of Samsung Mobile CPUs. |
@@ -172,6 +179,7 @@ config CPU_S3C2440 | |||
172 | bool | 179 | bool |
173 | depends on ARCH_S3C2410 | 180 | depends on ARCH_S3C2410 |
174 | select S3C2410_CLOCK | 181 | select S3C2410_CLOCK |
182 | select S3C2410_PM | ||
175 | select CPU_S3C244X | 183 | select CPU_S3C244X |
176 | help | 184 | help |
177 | Support for S3C2440 Samsung Mobile CPU based systems. | 185 | Support for S3C2440 Samsung Mobile CPU based systems. |
@@ -180,6 +188,7 @@ config CPU_S3C2442 | |||
180 | bool | 188 | bool |
181 | depends on ARCH_S3C2420 | 189 | depends on ARCH_S3C2420 |
182 | select S3C2410_CLOCK | 190 | select S3C2410_CLOCK |
191 | select S3C2410_PM | ||
183 | select CPU_S3C244X | 192 | select CPU_S3C244X |
184 | help | 193 | help |
185 | Support for S3C2442 Samsung Mobile CPU based systems. | 194 | Support for S3C2442 Samsung Mobile CPU based systems. |
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 0d87a9de0034..758f7e13b488 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile | |||
@@ -23,6 +23,8 @@ obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o | |||
23 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o | 23 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o |
24 | obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o | 24 | obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o |
25 | obj-$(CONFIG_CPU_S3C2410) += s3c2410-irq.o | 25 | obj-$(CONFIG_CPU_S3C2410) += s3c2410-irq.o |
26 | |||
27 | obj-$(CONFIG_S3C2410_PM) += s3c2410-pm.o s3c2410-sleep.o | ||
26 | obj-$(CONFIG_CPU_S3C2410_DMA) += s3c2410-dma.o | 28 | obj-$(CONFIG_CPU_S3C2410_DMA) += s3c2410-dma.o |
27 | 29 | ||
28 | # Power Management support | 30 | # Power Management support |
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index 46dedd37f438..9402583a1294 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c | |||
@@ -142,7 +142,7 @@ static struct sleep_save uart_save[] = { | |||
142 | 142 | ||
143 | extern void printascii(const char *); | 143 | extern void printascii(const char *); |
144 | 144 | ||
145 | static void pm_dbg(const char *fmt, ...) | 145 | void pm_dbg(const char *fmt, ...) |
146 | { | 146 | { |
147 | va_list va; | 147 | va_list va; |
148 | char buff[256]; | 148 | char buff[256]; |
@@ -486,6 +486,9 @@ static void s3c2410_pm_configure_extint(void) | |||
486 | } | 486 | } |
487 | } | 487 | } |
488 | 488 | ||
489 | void (*pm_cpu_prep)(void); | ||
490 | void (*pm_cpu_sleep)(void); | ||
491 | |||
489 | #define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) | 492 | #define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) |
490 | 493 | ||
491 | /* s3c2410_pm_enter | 494 | /* s3c2410_pm_enter |
@@ -496,7 +499,6 @@ static void s3c2410_pm_configure_extint(void) | |||
496 | static int s3c2410_pm_enter(suspend_state_t state) | 499 | static int s3c2410_pm_enter(suspend_state_t state) |
497 | { | 500 | { |
498 | unsigned long regs_save[16]; | 501 | unsigned long regs_save[16]; |
499 | unsigned long tmp; | ||
500 | 502 | ||
501 | /* ensure the debug is initialised (if enabled) */ | 503 | /* ensure the debug is initialised (if enabled) */ |
502 | 504 | ||
@@ -504,6 +506,11 @@ static int s3c2410_pm_enter(suspend_state_t state) | |||
504 | 506 | ||
505 | DBG("s3c2410_pm_enter(%d)\n", state); | 507 | DBG("s3c2410_pm_enter(%d)\n", state); |
506 | 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 | |||
507 | if (state != PM_SUSPEND_MEM) { | 514 | if (state != PM_SUSPEND_MEM) { |
508 | printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n"); | 515 | printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n"); |
509 | return -EINVAL; | 516 | return -EINVAL; |
@@ -531,13 +538,6 @@ static int s3c2410_pm_enter(suspend_state_t state) | |||
531 | 538 | ||
532 | 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); |
533 | 540 | ||
534 | /* ensure at least GESTATUS3 has the resume address */ | ||
535 | |||
536 | __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3); | ||
537 | |||
538 | DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3)); | ||
539 | DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4)); | ||
540 | |||
541 | /* save all necessary core registers not covered by the drivers */ | 541 | /* save all necessary core registers not covered by the drivers */ |
542 | 542 | ||
543 | s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); | 543 | s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); |
@@ -558,6 +558,10 @@ static int s3c2410_pm_enter(suspend_state_t state) | |||
558 | 558 | ||
559 | __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND); | 559 | __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND); |
560 | 560 | ||
561 | /* call cpu specific preperation */ | ||
562 | |||
563 | pm_cpu_prep(); | ||
564 | |||
561 | /* flush cache back to ram */ | 565 | /* flush cache back to ram */ |
562 | 566 | ||
563 | flush_cache_all(); | 567 | flush_cache_all(); |
@@ -574,19 +578,13 @@ static int s3c2410_pm_enter(suspend_state_t state) | |||
574 | 578 | ||
575 | if (s3c2410_cpu_save(regs_save) == 0) { | 579 | if (s3c2410_cpu_save(regs_save) == 0) { |
576 | flush_cache_all(); | 580 | flush_cache_all(); |
577 | s3c2410_cpu_suspend(); | 581 | pm_cpu_sleep(); |
578 | } | 582 | } |
579 | 583 | ||
580 | /* restore the cpu state */ | 584 | /* restore the cpu state */ |
581 | 585 | ||
582 | cpu_init(); | 586 | cpu_init(); |
583 | 587 | ||
584 | /* unset the return-from-sleep flag, to ensure reset */ | ||
585 | |||
586 | tmp = __raw_readl(S3C2410_GSTATUS2); | ||
587 | tmp &= S3C2410_GSTATUS2_OFFRESET; | ||
588 | __raw_writel(tmp, S3C2410_GSTATUS2); | ||
589 | |||
590 | /* restore the system state */ | 588 | /* restore the system state */ |
591 | 589 | ||
592 | s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); | 590 | s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); |
diff --git a/arch/arm/mach-s3c2410/pm.h b/arch/arm/mach-s3c2410/pm.h index fa8e237cfee8..ffe197a119fb 100644 --- a/arch/arm/mach-s3c2410/pm.h +++ b/arch/arm/mach-s3c2410/pm.h | |||
@@ -34,6 +34,11 @@ extern unsigned long s3c_irqwake_eintmask; | |||
34 | extern unsigned long s3c_irqwake_intallow; | 34 | extern unsigned long s3c_irqwake_intallow; |
35 | extern unsigned long s3c_irqwake_eintallow; | 35 | extern unsigned long s3c_irqwake_eintallow; |
36 | 36 | ||
37 | /* per-cpu sleep functions */ | ||
38 | |||
39 | extern void (*pm_cpu_prep)(void); | ||
40 | extern void (*pm_cpu_sleep)(void); | ||
41 | |||
37 | /* Flags for PM Control */ | 42 | /* Flags for PM Control */ |
38 | 43 | ||
39 | extern unsigned long s3c_pm_flags; | 44 | extern unsigned long s3c_pm_flags; |
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c new file mode 100644 index 000000000000..3080d25a12de --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2410-pm.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/s3c2410-pm.c | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <linux/suspend.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/time.h> | ||
27 | #include <linux/sysdev.h> | ||
28 | |||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/io.h> | ||
31 | |||
32 | #include <asm/arch/regs-gpio.h> | ||
33 | |||
34 | #include "cpu.h" | ||
35 | #include "pm.h" | ||
36 | |||
37 | #ifdef CONFIG_S3C2410_PM_DEBUG | ||
38 | extern void pm_dbg(const char *fmt, ...); | ||
39 | #define DBG(fmt...) pm_dbg(fmt) | ||
40 | #else | ||
41 | #define DBG(fmt...) printk(KERN_DEBUG fmt) | ||
42 | #endif | ||
43 | |||
44 | static void s3c2410_pm_prepare(void) | ||
45 | { | ||
46 | /* ensure at least GSTATUS3 has the resume address */ | ||
47 | |||
48 | __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3); | ||
49 | |||
50 | DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3)); | ||
51 | DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4)); | ||
52 | } | ||
53 | |||
54 | int s3c2410_pm_resume(struct sys_device *dev) | ||
55 | { | ||
56 | unsigned long tmp; | ||
57 | |||
58 | /* unset the return-from-sleep flag, to ensure reset */ | ||
59 | |||
60 | tmp = __raw_readl(S3C2410_GSTATUS2); | ||
61 | tmp &= S3C2410_GSTATUS2_OFFRESET; | ||
62 | __raw_writel(tmp, S3C2410_GSTATUS2); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int s3c2410_pm_add(struct sys_device *dev) | ||
68 | { | ||
69 | pm_cpu_prep = s3c2410_pm_prepare; | ||
70 | pm_cpu_sleep = s3c2410_cpu_suspend; | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static struct sysdev_driver s3c2410_pm_driver = { | ||
76 | .add = s3c2410_pm_add, | ||
77 | .resume = s3c2410_pm_resume, | ||
78 | }; | ||
79 | |||
80 | /* register ourselves */ | ||
81 | |||
82 | static int __init s3c2410_pm_drvinit(void) | ||
83 | { | ||
84 | return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver); | ||
85 | } | ||
86 | |||
87 | arch_initcall(s3c2410_pm_drvinit); | ||
88 | |||
89 | static struct sysdev_driver s3c2440_pm_driver = { | ||
90 | .add = s3c2410_pm_add, | ||
91 | .resume = s3c2410_pm_resume, | ||
92 | }; | ||
93 | |||
94 | static int __init s3c2440_pm_drvinit(void) | ||
95 | { | ||
96 | return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver); | ||
97 | } | ||
98 | |||
99 | arch_initcall(s3c2440_pm_drvinit); | ||
100 | |||
101 | static struct sysdev_driver s3c2442_pm_driver = { | ||
102 | .add = s3c2410_pm_add, | ||
103 | .resume = s3c2410_pm_resume, | ||
104 | }; | ||
105 | |||
106 | static int __init s3c2442_pm_drvinit(void) | ||
107 | { | ||
108 | return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver); | ||
109 | } | ||
110 | |||
111 | arch_initcall(s3c2442_pm_drvinit); | ||
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S new file mode 100644 index 000000000000..9179a1024588 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2410-sleep.S | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2410 Power Manager (Suspend-To-RAM) support | ||
7 | * | ||
8 | * Based on PXA/SA1100 sleep code by: | ||
9 | * Nicolas Pitre, (c) 2002 Monta Vista Software Inc | ||
10 | * Cliff Brake, (c) 2001 | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #include <linux/linkage.h> | ||
28 | #include <asm/assembler.h> | ||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/arch/map.h> | ||
31 | |||
32 | #include <asm/arch/regs-gpio.h> | ||
33 | #include <asm/arch/regs-clock.h> | ||
34 | #include <asm/arch/regs-mem.h> | ||
35 | #include <asm/arch/regs-serial.h> | ||
36 | |||
37 | /* s3c2410_cpu_suspend | ||
38 | * | ||
39 | * put the cpu into sleep mode | ||
40 | */ | ||
41 | |||
42 | ENTRY(s3c2410_cpu_suspend) | ||
43 | @@ prepare cpu to sleep | ||
44 | |||
45 | ldr r4, =S3C2410_REFRESH | ||
46 | ldr r5, =S3C24XX_MISCCR | ||
47 | ldr r6, =S3C2410_CLKCON | ||
48 | ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB) | ||
49 | ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB) | ||
50 | ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB) | ||
51 | |||
52 | orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command | ||
53 | orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals | ||
54 | orr r9, r9, #S3C2410_CLKCON_POWER @ power down command | ||
55 | |||
56 | teq pc, #0 @ first as a trial-run to load cache | ||
57 | bl s3c2410_do_sleep | ||
58 | teq r0, r0 @ now do it for real | ||
59 | b s3c2410_do_sleep @ | ||
60 | |||
61 | @@ align next bit of code to cache line | ||
62 | .align 8 | ||
63 | s3c2410_do_sleep: | ||
64 | streq r7, [ r4 ] @ SDRAM sleep command | ||
65 | streq r8, [ r5 ] @ SDRAM power-down config | ||
66 | streq r9, [ r6 ] @ CPU sleep | ||
67 | 1: beq 1b | ||
68 | mov pc, r14 | ||
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S index e977aa1ffe18..2018c2e1dcc5 100644 --- a/arch/arm/mach-s3c2410/sleep.S +++ b/arch/arm/mach-s3c2410/sleep.S | |||
@@ -75,39 +75,6 @@ ENTRY(s3c2410_cpu_save) | |||
75 | mov r0, #0 | 75 | mov r0, #0 |
76 | ldmfd sp, { r4 - r12, pc } | 76 | ldmfd sp, { r4 - r12, pc } |
77 | 77 | ||
78 | /* s3c2410_cpu_suspend | ||
79 | * | ||
80 | * put the cpu into sleep mode | ||
81 | */ | ||
82 | |||
83 | ENTRY(s3c2410_cpu_suspend) | ||
84 | @@ prepare cpu to sleep | ||
85 | |||
86 | ldr r4, =S3C2410_REFRESH | ||
87 | ldr r5, =S3C24XX_MISCCR | ||
88 | ldr r6, =S3C2410_CLKCON | ||
89 | ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB) | ||
90 | ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB) | ||
91 | ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB) | ||
92 | |||
93 | orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command | ||
94 | orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals | ||
95 | orr r9, r9, #S3C2410_CLKCON_POWER @ power down command | ||
96 | |||
97 | teq pc, #0 @ first as a trial-run to load cache | ||
98 | bl s3c2410_do_sleep | ||
99 | teq r0, r0 @ now do it for real | ||
100 | b s3c2410_do_sleep @ | ||
101 | |||
102 | @@ align next bit of code to cache line | ||
103 | .align 8 | ||
104 | s3c2410_do_sleep: | ||
105 | streq r7, [ r4 ] @ SDRAM sleep command | ||
106 | streq r8, [ r5 ] @ SDRAM power-down config | ||
107 | streq r9, [ r6 ] @ CPU sleep | ||
108 | 1: beq 1b | ||
109 | mov pc, r14 | ||
110 | |||
111 | @@ return to the caller, after having the MMU | 78 | @@ return to the caller, after having the MMU |
112 | @@ turned on, this restores the last bits from the | 79 | @@ turned on, this restores the last bits from the |
113 | @@ stack | 80 | @@ stack |