# BRCM_VERSION=3
[bcm963xx.git] / kernel / linux / arch / arm / mach-sa1100 / pm.c
1 /*
2  * SA1100 Power Management Routines
3  *
4  * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License.
8  *
9  * History:
10  *
11  * 2001-02-06:  Cliff Brake         Initial code
12  *
13  * 2001-02-25:  Sukjae Cho <sjcho@east.isi.edu> &
14  *              Chester Kuo <chester@linux.org.tw>
15  *                      Save more value for the resume function! Support
16  *                      Bitsy/Assabet/Freebird board
17  *
18  * 2001-08-29:  Nicolas Pitre <nico@cam.org>
19  *                      Cleaned up, pushed platform dependent stuff
20  *                      in the platform specific files.
21  *
22  * 2002-05-27:  Nicolas Pitre   Killed sleep.h and the kmalloced save array.
23  *                              Storage is local on the stack now.
24  */
25 #include <linux/init.h>
26 #include <linux/suspend.h>
27 #include <linux/errno.h>
28 #include <linux/time.h>
29
30 #include <asm/hardware.h>
31 #include <asm/memory.h>
32 #include <asm/system.h>
33
34 extern void sa1100_cpu_suspend(void);
35 extern void sa1100_cpu_resume(void);
36
37 #define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
38 #define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
39
40 /*
41  * List of global SA11x0 peripheral registers to preserve.
42  * More ones like CP and general purpose register values are preserved
43  * on the stack and then the stack pointer is stored last in sleep.S.
44  */
45 enum {  SLEEP_SAVE_SP = 0,
46
47         SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
48         SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
49
50         SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
51         SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
52
53         SLEEP_SAVE_Ser1SDCR0,
54
55         SLEEP_SAVE_SIZE
56 };
57
58
59 static int sa11x0_pm_enter(u32 state)
60 {
61         unsigned long sleep_save[SLEEP_SAVE_SIZE];
62         unsigned long delta, gpio;
63
64         if (state != PM_SUSPEND_MEM)
65                 return -EINVAL;
66
67         /* preserve current time */
68         delta = xtime.tv_sec - RCNR;
69         gpio = GPLR;
70
71         /* save vital registers */
72         SAVE(OSCR);
73         SAVE(OSMR0);
74         SAVE(OSMR1);
75         SAVE(OSMR2);
76         SAVE(OSMR3);
77         SAVE(OIER);
78
79         SAVE(GPDR);
80         SAVE(GAFR);
81
82         SAVE(PPDR);
83         SAVE(PPSR);
84         SAVE(PPAR);
85         SAVE(PSDR);
86
87         SAVE(Ser1SDCR0);
88
89         /* Clear previous reset status */
90         RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
91
92         /* set resume return address */
93         PSPR = virt_to_phys(sa1100_cpu_resume);
94
95         /* go zzz */
96         sa1100_cpu_suspend();
97
98         /*
99          * Ensure not to come back here if it wasn't intended
100          */
101         PSPR = 0;
102
103         /*
104          * Ensure interrupt sources are disabled; we will re-init
105          * the interrupt subsystem via the device manager.
106          */
107         ICLR = 0;
108         ICCR = 1;
109         ICMR = 0;
110
111         /* restore registers */
112         RESTORE(GPDR);
113         RESTORE(GAFR);
114
115         RESTORE(PPDR);
116         RESTORE(PPSR);
117         RESTORE(PPAR);
118         RESTORE(PSDR);
119
120         RESTORE(Ser1SDCR0);
121
122         GPSR = gpio;
123         GPCR = ~gpio;
124
125         /*
126          * Clear the peripheral sleep-hold bit.
127          */
128         PSSR = PSSR_PH;
129
130         RESTORE(OSMR0);
131         RESTORE(OSMR1);
132         RESTORE(OSMR2);
133         RESTORE(OSMR3);
134         RESTORE(OSCR);
135         RESTORE(OIER);
136
137         /* restore current time */
138         xtime.tv_sec = RCNR + delta;
139
140         return 0;
141 }
142
143 unsigned long sleep_phys_sp(void *sp)
144 {
145         return virt_to_phys(sp);
146 }
147
148 /*
149  * Called after processes are frozen, but before we shut down devices.
150  */
151 static int sa11x0_pm_prepare(u32 state)
152 {
153         return 0;
154 }
155
156 /*
157  * Called after devices are re-setup, but before processes are thawed.
158  */
159 static int sa11x0_pm_finish(u32 state)
160 {
161         return 0;
162 }
163
164 /*
165  * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
166  */
167 static struct pm_ops sa11x0_pm_ops = {
168         .pm_disk_mode   = PM_DISK_FIRMWARE,
169         .prepare        = sa11x0_pm_prepare,
170         .enter          = sa11x0_pm_enter,
171         .finish         = sa11x0_pm_finish,
172 };
173
174 static int __init sa11x0_pm_init(void)
175 {
176         pm_set_ops(&sa11x0_pm_ops);
177         return 0;
178 }
179
180 late_initcall(sa11x0_pm_init);