diff options
author | eric miao <eric.miao@marvell.com> | 2008-01-28 18:00:02 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-02-04 08:17:33 -0500 |
commit | 16dfdbf038706c12c56f327d14c6b901edc376a3 (patch) | |
tree | 1f761ae7ff1c4ba837d24c69521d5cbe0b2d7e72 | |
parent | c016550490687c6bdbcdf06c7b4d874b6c7c6e4e (diff) |
[ARM] pxa: introduce sysdev for GPIO register saving/restoring
Signed-off-by: eric miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/mach-pxa/generic.c | 57 | ||||
-rw-r--r-- | arch/arm/mach-pxa/generic.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 19 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa3xx.c | 2 |
5 files changed, 64 insertions, 38 deletions
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 698aeec52961..76970598f550 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/ioport.h> | 23 | #include <linux/ioport.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/sysdev.h> | ||
26 | 27 | ||
27 | #include <asm/hardware.h> | 28 | #include <asm/hardware.h> |
28 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
@@ -226,3 +227,59 @@ void __init pxa_map_io(void) | |||
226 | iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); | 227 | iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); |
227 | get_clk_frequency_khz(1); | 228 | get_clk_frequency_khz(1); |
228 | } | 229 | } |
230 | |||
231 | #ifdef CONFIG_PM | ||
232 | |||
233 | static unsigned long saved_gplr[4]; | ||
234 | static unsigned long saved_gpdr[4]; | ||
235 | static unsigned long saved_grer[4]; | ||
236 | static unsigned long saved_gfer[4]; | ||
237 | |||
238 | static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state) | ||
239 | { | ||
240 | int i, gpio; | ||
241 | |||
242 | for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) { | ||
243 | saved_gplr[i] = GPLR(gpio); | ||
244 | saved_gpdr[i] = GPDR(gpio); | ||
245 | saved_grer[i] = GRER(gpio); | ||
246 | saved_gfer[i] = GFER(gpio); | ||
247 | |||
248 | /* Clear GPIO transition detect bits */ | ||
249 | GEDR(gpio) = GEDR(gpio); | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int pxa_gpio_resume(struct sys_device *dev) | ||
255 | { | ||
256 | int i, gpio; | ||
257 | |||
258 | for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) { | ||
259 | /* restore level with set/clear */ | ||
260 | GPSR(gpio) = saved_gplr[i]; | ||
261 | GPCR(gpio) = ~saved_gplr[i]; | ||
262 | |||
263 | GRER(gpio) = saved_grer[i]; | ||
264 | GFER(gpio) = saved_gfer[i]; | ||
265 | GPDR(gpio) = saved_gpdr[i]; | ||
266 | } | ||
267 | return 0; | ||
268 | } | ||
269 | #else | ||
270 | #define pxa_gpio_suspend NULL | ||
271 | #define pxa_gpio_resume NULL | ||
272 | #endif | ||
273 | |||
274 | struct sysdev_class pxa_gpio_sysclass = { | ||
275 | .name = "gpio", | ||
276 | .suspend = pxa_gpio_suspend, | ||
277 | .resume = pxa_gpio_resume, | ||
278 | }; | ||
279 | |||
280 | static int __init pxa_gpio_init(void) | ||
281 | { | ||
282 | return sysdev_class_register(&pxa_gpio_sysclass); | ||
283 | } | ||
284 | |||
285 | core_initcall(pxa_gpio_init); | ||
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 367b67923e11..1a16ad3ecee6 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h | |||
@@ -54,3 +54,4 @@ extern unsigned pxa3xx_get_memclk_frequency_10khz(void); | |||
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | extern struct sysdev_class pxa_irq_sysclass; | 56 | extern struct sysdev_class pxa_irq_sysclass; |
57 | extern struct sysdev_class pxa_gpio_sysclass; | ||
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 797635eec6b6..599e53fcc2c5 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c | |||
@@ -142,11 +142,6 @@ static struct clk pxa25x_clks[] = { | |||
142 | #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x | 142 | #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x |
143 | #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] | 143 | #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] |
144 | 144 | ||
145 | #define RESTORE_GPLEVEL(n) do { \ | ||
146 | GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \ | ||
147 | GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \ | ||
148 | } while (0) | ||
149 | |||
150 | /* | 145 | /* |
151 | * List of global PXA peripheral registers to preserve. | 146 | * List of global PXA peripheral registers to preserve. |
152 | * More ones like CP and general purpose register values are preserved | 147 | * More ones like CP and general purpose register values are preserved |
@@ -154,10 +149,6 @@ static struct clk pxa25x_clks[] = { | |||
154 | */ | 149 | */ |
155 | enum { SLEEP_SAVE_START = 0, | 150 | enum { SLEEP_SAVE_START = 0, |
156 | 151 | ||
157 | SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, | ||
158 | SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, | ||
159 | SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, | ||
160 | SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, | ||
161 | SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, | 152 | SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, |
162 | 153 | ||
163 | SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, | 154 | SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, |
@@ -174,10 +165,6 @@ enum { SLEEP_SAVE_START = 0, | |||
174 | 165 | ||
175 | static void pxa25x_cpu_pm_save(unsigned long *sleep_save) | 166 | static void pxa25x_cpu_pm_save(unsigned long *sleep_save) |
176 | { | 167 | { |
177 | SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); | ||
178 | SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); | ||
179 | SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); | ||
180 | SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); | ||
181 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); | 168 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); |
182 | 169 | ||
183 | SAVE(GAFR0_L); SAVE(GAFR0_U); | 170 | SAVE(GAFR0_L); SAVE(GAFR0_U); |
@@ -197,13 +184,9 @@ static void pxa25x_cpu_pm_restore(unsigned long *sleep_save) | |||
197 | PSPR = 0; | 184 | PSPR = 0; |
198 | 185 | ||
199 | /* restore registers */ | 186 | /* restore registers */ |
200 | RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2); | ||
201 | RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); | ||
202 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); | 187 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); |
203 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); | 188 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); |
204 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); | 189 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); |
205 | RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); | ||
206 | RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); | ||
207 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); | 190 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); |
208 | 191 | ||
209 | PSSR = PSSR_RDH | PSSR_PH; | 192 | PSSR = PSSR_RDH | PSSR_PH; |
@@ -302,6 +285,8 @@ static struct platform_device *pxa25x_devices[] __initdata = { | |||
302 | static struct sys_device pxa25x_sysdev[] = { | 285 | static struct sys_device pxa25x_sysdev[] = { |
303 | { | 286 | { |
304 | .cls = &pxa_irq_sysclass, | 287 | .cls = &pxa_irq_sysclass, |
288 | }, { | ||
289 | .cls = &pxa_gpio_sysclass, | ||
305 | }, | 290 | }, |
306 | }; | 291 | }; |
307 | 292 | ||
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 343296a710b3..46a951c3e5a0 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
@@ -172,11 +172,6 @@ static struct clk pxa27x_clks[] = { | |||
172 | #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x | 172 | #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x |
173 | #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] | 173 | #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] |
174 | 174 | ||
175 | #define RESTORE_GPLEVEL(n) do { \ | ||
176 | GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \ | ||
177 | GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \ | ||
178 | } while (0) | ||
179 | |||
180 | /* | 175 | /* |
181 | * List of global PXA peripheral registers to preserve. | 176 | * List of global PXA peripheral registers to preserve. |
182 | * More ones like CP and general purpose register values are preserved | 177 | * More ones like CP and general purpose register values are preserved |
@@ -184,10 +179,6 @@ static struct clk pxa27x_clks[] = { | |||
184 | */ | 179 | */ |
185 | enum { SLEEP_SAVE_START = 0, | 180 | enum { SLEEP_SAVE_START = 0, |
186 | 181 | ||
187 | SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3, | ||
188 | SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3, | ||
189 | SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3, | ||
190 | SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3, | ||
191 | SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, | 182 | SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, |
192 | 183 | ||
193 | SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, | 184 | SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, |
@@ -208,10 +199,6 @@ enum { SLEEP_SAVE_START = 0, | |||
208 | 199 | ||
209 | void pxa27x_cpu_pm_save(unsigned long *sleep_save) | 200 | void pxa27x_cpu_pm_save(unsigned long *sleep_save) |
210 | { | 201 | { |
211 | SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3); | ||
212 | SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3); | ||
213 | SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3); | ||
214 | SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3); | ||
215 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3); | 202 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3); |
216 | 203 | ||
217 | SAVE(GAFR0_L); SAVE(GAFR0_U); | 204 | SAVE(GAFR0_L); SAVE(GAFR0_U); |
@@ -225,9 +212,6 @@ void pxa27x_cpu_pm_save(unsigned long *sleep_save) | |||
225 | 212 | ||
226 | SAVE(CKEN); | 213 | SAVE(CKEN); |
227 | SAVE(PSTR); | 214 | SAVE(PSTR); |
228 | |||
229 | /* Clear GPIO transition detect bits */ | ||
230 | GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3; | ||
231 | } | 215 | } |
232 | 216 | ||
233 | void pxa27x_cpu_pm_restore(unsigned long *sleep_save) | 217 | void pxa27x_cpu_pm_restore(unsigned long *sleep_save) |
@@ -236,15 +220,10 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save) | |||
236 | PSPR = 0; | 220 | PSPR = 0; |
237 | 221 | ||
238 | /* restore registers */ | 222 | /* restore registers */ |
239 | RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); | ||
240 | RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3); | ||
241 | RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3); | ||
242 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); | 223 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); |
243 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); | 224 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); |
244 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); | 225 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); |
245 | RESTORE(GAFR3_L); RESTORE(GAFR3_U); | 226 | RESTORE(GAFR3_L); RESTORE(GAFR3_U); |
246 | RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3); | ||
247 | RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3); | ||
248 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3); | 227 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3); |
249 | 228 | ||
250 | RESTORE(MDREFR); | 229 | RESTORE(MDREFR); |
@@ -412,6 +391,8 @@ static struct sys_device pxa27x_sysdev[] = { | |||
412 | }, { | 391 | }, { |
413 | .id = 1, | 392 | .id = 1, |
414 | .cls = &pxa_irq_sysclass, | 393 | .cls = &pxa_irq_sysclass, |
394 | }, { | ||
395 | .cls = &pxa_gpio_sysclass, | ||
415 | }, | 396 | }, |
416 | }; | 397 | }; |
417 | 398 | ||
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 3a7e8ccd70bd..d0b2afd4368a 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c | |||
@@ -460,6 +460,8 @@ static struct sys_device pxa3xx_sysdev[] = { | |||
460 | }, { | 460 | }, { |
461 | .id = 1, | 461 | .id = 1, |
462 | .cls = &pxa_irq_sysclass, | 462 | .cls = &pxa_irq_sysclass, |
463 | }, { | ||
464 | .cls = &pxa_gpio_sysclass, | ||
463 | }, | 465 | }, |
464 | }; | 466 | }; |
465 | 467 | ||