Commit 16dfdbf038706c12c56f327d14c6b901edc376a3
Committed by
Russell King
1 parent
c016550490
[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>
Showing 5 changed files with 64 additions and 38 deletions Side-by-side Diff
arch/arm/mach-pxa/generic.c
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | #include <linux/ioport.h> |
24 | 24 | #include <linux/pm.h> |
25 | 25 | #include <linux/string.h> |
26 | +#include <linux/sysdev.h> | |
26 | 27 | |
27 | 28 | #include <asm/hardware.h> |
28 | 29 | #include <asm/irq.h> |
... | ... | @@ -226,4 +227,60 @@ |
226 | 227 | iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); |
227 | 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); |
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/pxa25x.c
... | ... | @@ -142,11 +142,6 @@ |
142 | 142 | #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x |
143 | 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 | 146 | * List of global PXA peripheral registers to preserve. |
152 | 147 | * More ones like CP and general purpose register values are preserved |
... | ... | @@ -154,10 +149,6 @@ |
154 | 149 | */ |
155 | 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 | 152 | SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, |
162 | 153 | |
163 | 154 | SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, |
... | ... | @@ -174,10 +165,6 @@ |
174 | 165 | |
175 | 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 | 168 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); |
182 | 169 | |
183 | 170 | SAVE(GAFR0_L); SAVE(GAFR0_U); |
184 | 171 | |
... | ... | @@ -197,13 +184,9 @@ |
197 | 184 | PSPR = 0; |
198 | 185 | |
199 | 186 | /* restore registers */ |
200 | - RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2); | |
201 | - RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); | |
202 | 187 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); |
203 | 188 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); |
204 | 189 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); |
205 | - RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); | |
206 | - RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); | |
207 | 190 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); |
208 | 191 | |
209 | 192 | PSSR = PSSR_RDH | PSSR_PH; |
... | ... | @@ -302,6 +285,8 @@ |
302 | 285 | static struct sys_device pxa25x_sysdev[] = { |
303 | 286 | { |
304 | 287 | .cls = &pxa_irq_sysclass, |
288 | + }, { | |
289 | + .cls = &pxa_gpio_sysclass, | |
305 | 290 | }, |
306 | 291 | }; |
307 | 292 |
arch/arm/mach-pxa/pxa27x.c
... | ... | @@ -172,11 +172,6 @@ |
172 | 172 | #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x |
173 | 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 | 176 | * List of global PXA peripheral registers to preserve. |
182 | 177 | * More ones like CP and general purpose register values are preserved |
... | ... | @@ -184,10 +179,6 @@ |
184 | 179 | */ |
185 | 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 | 182 | SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, |
192 | 183 | |
193 | 184 | SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, |
... | ... | @@ -208,10 +199,6 @@ |
208 | 199 | |
209 | 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 | 202 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3); |
216 | 203 | |
217 | 204 | SAVE(GAFR0_L); SAVE(GAFR0_U); |
... | ... | @@ -225,9 +212,6 @@ |
225 | 212 | |
226 | 213 | SAVE(CKEN); |
227 | 214 | SAVE(PSTR); |
228 | - | |
229 | - /* Clear GPIO transition detect bits */ | |
230 | - GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3; | |
231 | 215 | } |
232 | 216 | |
233 | 217 | void pxa27x_cpu_pm_restore(unsigned long *sleep_save) |
234 | 218 | |
... | ... | @@ -236,15 +220,10 @@ |
236 | 220 | PSPR = 0; |
237 | 221 | |
238 | 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 | 223 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); |
243 | 224 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); |
244 | 225 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); |
245 | 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 | 227 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3); |
249 | 228 | |
250 | 229 | RESTORE(MDREFR); |
... | ... | @@ -412,6 +391,8 @@ |
412 | 391 | }, { |
413 | 392 | .id = 1, |
414 | 393 | .cls = &pxa_irq_sysclass, |
394 | + }, { | |
395 | + .cls = &pxa_gpio_sysclass, | |
415 | 396 | }, |
416 | 397 | }; |
417 | 398 |