diff options
Diffstat (limited to 'arch/arm/plat-s3c24xx')
-rw-r--r-- | arch/arm/plat-s3c24xx/pm.c | 210 |
1 files changed, 7 insertions, 203 deletions
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index c161f9c9a1d4..e2ae12da16e7 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
32 | #include <linux/time.h> | 32 | #include <linux/time.h> |
33 | #include <linux/interrupt.h> | 33 | #include <linux/interrupt.h> |
34 | #include <linux/crc32.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/serial_core.h> | 34 | #include <linux/serial_core.h> |
37 | #include <linux/io.h> | 35 | #include <linux/io.h> |
38 | 36 | ||
@@ -159,200 +157,6 @@ static void s3c2410_pm_debug_init(void) | |||
159 | static struct sleep_save uart_save[] = {}; | 157 | static struct sleep_save uart_save[] = {}; |
160 | #endif | 158 | #endif |
161 | 159 | ||
162 | #if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0 | ||
163 | |||
164 | /* suspend checking code... | ||
165 | * | ||
166 | * this next area does a set of crc checks over all the installed | ||
167 | * memory, so the system can verify if the resume was ok. | ||
168 | * | ||
169 | * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC, | ||
170 | * increasing it will mean that the area corrupted will be less easy to spot, | ||
171 | * and reducing the size will cause the CRC save area to grow | ||
172 | */ | ||
173 | |||
174 | #define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024) | ||
175 | |||
176 | static u32 crc_size; /* size needed for the crc block */ | ||
177 | static u32 *crcs; /* allocated over suspend/resume */ | ||
178 | |||
179 | typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg); | ||
180 | |||
181 | /* s3c2410_pm_run_res | ||
182 | * | ||
183 | * go thorugh the given resource list, and look for system ram | ||
184 | */ | ||
185 | |||
186 | static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg) | ||
187 | { | ||
188 | while (ptr != NULL) { | ||
189 | if (ptr->child != NULL) | ||
190 | s3c2410_pm_run_res(ptr->child, fn, arg); | ||
191 | |||
192 | if ((ptr->flags & IORESOURCE_MEM) && | ||
193 | strcmp(ptr->name, "System RAM") == 0) { | ||
194 | S3C_PMDBG("Found system RAM at %08lx..%08lx\n", | ||
195 | ptr->start, ptr->end); | ||
196 | arg = (fn)(ptr, arg); | ||
197 | } | ||
198 | |||
199 | ptr = ptr->sibling; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg) | ||
204 | { | ||
205 | s3c2410_pm_run_res(&iomem_resource, fn, arg); | ||
206 | } | ||
207 | |||
208 | static u32 *s3c2410_pm_countram(struct resource *res, u32 *val) | ||
209 | { | ||
210 | u32 size = (u32)(res->end - res->start)+1; | ||
211 | |||
212 | size += CHECK_CHUNKSIZE-1; | ||
213 | size /= CHECK_CHUNKSIZE; | ||
214 | |||
215 | S3C_PMDBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size); | ||
216 | |||
217 | *val += size * sizeof(u32); | ||
218 | return val; | ||
219 | } | ||
220 | |||
221 | /* s3c2410_pm_prepare_check | ||
222 | * | ||
223 | * prepare the necessary information for creating the CRCs. This | ||
224 | * must be done before the final save, as it will require memory | ||
225 | * allocating, and thus touching bits of the kernel we do not | ||
226 | * know about. | ||
227 | */ | ||
228 | |||
229 | static void s3c2410_pm_check_prepare(void) | ||
230 | { | ||
231 | crc_size = 0; | ||
232 | |||
233 | s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size); | ||
234 | |||
235 | S3C_PMDBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size); | ||
236 | |||
237 | crcs = kmalloc(crc_size+4, GFP_KERNEL); | ||
238 | if (crcs == NULL) | ||
239 | printk(KERN_ERR "Cannot allocated CRC save area\n"); | ||
240 | } | ||
241 | |||
242 | static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val) | ||
243 | { | ||
244 | unsigned long addr, left; | ||
245 | |||
246 | for (addr = res->start; addr < res->end; | ||
247 | addr += CHECK_CHUNKSIZE) { | ||
248 | left = res->end - addr; | ||
249 | |||
250 | if (left > CHECK_CHUNKSIZE) | ||
251 | left = CHECK_CHUNKSIZE; | ||
252 | |||
253 | *val = crc32_le(~0, phys_to_virt(addr), left); | ||
254 | val++; | ||
255 | } | ||
256 | |||
257 | return val; | ||
258 | } | ||
259 | |||
260 | /* s3c2410_pm_check_store | ||
261 | * | ||
262 | * compute the CRC values for the memory blocks before the final | ||
263 | * sleep. | ||
264 | */ | ||
265 | |||
266 | static void s3c2410_pm_check_store(void) | ||
267 | { | ||
268 | if (crcs != NULL) | ||
269 | s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs); | ||
270 | } | ||
271 | |||
272 | /* in_region | ||
273 | * | ||
274 | * return TRUE if the area defined by ptr..ptr+size contatins the | ||
275 | * what..what+whatsz | ||
276 | */ | ||
277 | |||
278 | static inline int in_region(void *ptr, int size, void *what, size_t whatsz) | ||
279 | { | ||
280 | if ((what+whatsz) < ptr) | ||
281 | return 0; | ||
282 | |||
283 | if (what > (ptr+size)) | ||
284 | return 0; | ||
285 | |||
286 | return 1; | ||
287 | } | ||
288 | |||
289 | static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val) | ||
290 | { | ||
291 | void *save_at = phys_to_virt(s3c_sleep_save_phys); | ||
292 | unsigned long addr; | ||
293 | unsigned long left; | ||
294 | void *ptr; | ||
295 | u32 calc; | ||
296 | |||
297 | for (addr = res->start; addr < res->end; | ||
298 | addr += CHECK_CHUNKSIZE) { | ||
299 | left = res->end - addr; | ||
300 | |||
301 | if (left > CHECK_CHUNKSIZE) | ||
302 | left = CHECK_CHUNKSIZE; | ||
303 | |||
304 | ptr = phys_to_virt(addr); | ||
305 | |||
306 | if (in_region(ptr, left, crcs, crc_size)) { | ||
307 | S3C_PMDBG("skipping %08lx, has crc block in\n", addr); | ||
308 | goto skip_check; | ||
309 | } | ||
310 | |||
311 | if (in_region(ptr, left, save_at, 32*4 )) { | ||
312 | S3C_PMDBG("skipping %08lx, has save block in\n", addr); | ||
313 | goto skip_check; | ||
314 | } | ||
315 | |||
316 | /* calculate and check the checksum */ | ||
317 | |||
318 | calc = crc32_le(~0, ptr, left); | ||
319 | if (calc != *val) { | ||
320 | printk(KERN_ERR PFX "Restore CRC error at " | ||
321 | "%08lx (%08x vs %08x)\n", addr, calc, *val); | ||
322 | |||
323 | S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n", | ||
324 | addr, calc, *val); | ||
325 | } | ||
326 | |||
327 | skip_check: | ||
328 | val++; | ||
329 | } | ||
330 | |||
331 | return val; | ||
332 | } | ||
333 | |||
334 | /* s3c2410_pm_check_restore | ||
335 | * | ||
336 | * check the CRCs after the restore event and free the memory used | ||
337 | * to hold them | ||
338 | */ | ||
339 | |||
340 | static void s3c2410_pm_check_restore(void) | ||
341 | { | ||
342 | if (crcs != NULL) { | ||
343 | s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs); | ||
344 | kfree(crcs); | ||
345 | crcs = NULL; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | #else | ||
350 | |||
351 | #define s3c2410_pm_check_prepare() do { } while(0) | ||
352 | #define s3c2410_pm_check_restore() do { } while(0) | ||
353 | #define s3c2410_pm_check_store() do { } while(0) | ||
354 | #endif | ||
355 | |||
356 | /* s3c2410_pm_show_resume_irqs | 160 | /* s3c2410_pm_show_resume_irqs |
357 | * | 161 | * |
358 | * print any IRQs asserted at resume time (ie, we woke from) | 162 | * print any IRQs asserted at resume time (ie, we woke from) |
@@ -372,13 +176,13 @@ static void s3c2410_pm_show_resume_irqs(int start, unsigned long which, | |||
372 | } | 176 | } |
373 | } | 177 | } |
374 | 178 | ||
375 | /* s3c2410_pm_check_resume_pin | 179 | /* s3c_pm_check_resume_pin |
376 | * | 180 | * |
377 | * check to see if the pin is configured correctly for sleep mode, and | 181 | * check to see if the pin is configured correctly for sleep mode, and |
378 | * make any necessary adjustments if it is not | 182 | * make any necessary adjustments if it is not |
379 | */ | 183 | */ |
380 | 184 | ||
381 | static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) | 185 | static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) |
382 | { | 186 | { |
383 | unsigned long irqstate; | 187 | unsigned long irqstate; |
384 | unsigned long pinstate; | 188 | unsigned long pinstate; |
@@ -417,11 +221,11 @@ static void s3c2410_pm_configure_extint(void) | |||
417 | */ | 221 | */ |
418 | 222 | ||
419 | for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) { | 223 | for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) { |
420 | s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0); | 224 | s3c_pm_check_resume_pin(pin, pin - S3C2410_GPF0); |
421 | } | 225 | } |
422 | 226 | ||
423 | for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) { | 227 | for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) { |
424 | s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8); | 228 | s3c_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8); |
425 | } | 229 | } |
426 | } | 230 | } |
427 | 231 | ||
@@ -642,7 +446,7 @@ static int s3c2410_pm_enter(suspend_state_t state) | |||
642 | 446 | ||
643 | /* prepare check area if configured */ | 447 | /* prepare check area if configured */ |
644 | 448 | ||
645 | s3c2410_pm_check_prepare(); | 449 | s3c_pm_check_prepare(); |
646 | 450 | ||
647 | /* store the physical address of the register recovery block */ | 451 | /* store the physical address of the register recovery block */ |
648 | 452 | ||
@@ -681,7 +485,7 @@ static int s3c2410_pm_enter(suspend_state_t state) | |||
681 | 485 | ||
682 | flush_cache_all(); | 486 | flush_cache_all(); |
683 | 487 | ||
684 | s3c2410_pm_check_store(); | 488 | s3c_pm_check_store(); |
685 | 489 | ||
686 | /* send the cpu to sleep... */ | 490 | /* send the cpu to sleep... */ |
687 | 491 | ||
@@ -723,7 +527,7 @@ static int s3c2410_pm_enter(suspend_state_t state) | |||
723 | 527 | ||
724 | S3C_PMDBG("post sleep, preparing to return\n"); | 528 | S3C_PMDBG("post sleep, preparing to return\n"); |
725 | 529 | ||
726 | s3c2410_pm_check_restore(); | 530 | s3c_pm_check_restore(); |
727 | 531 | ||
728 | /* ok, let's return from sleep */ | 532 | /* ok, let's return from sleep */ |
729 | 533 | ||