aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-samsung
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2010-01-19 22:29:25 -0500
committerBen Dooks <ben-linux@fluff.org>2010-01-20 23:45:58 -0500
commit8005745d6eea79da8ee2e7fe978d14e412aa3353 (patch)
tree12b3e6d2fcaa1f07f8b3d68a7ad53960d565146f /arch/arm/plat-samsung
parent106cc6aa73f594015fc8b99f7c70d1b7cf23f19a (diff)
ARM: SAMSUNG: Move pm-check.c to plat-samsung
Move the pm-check.c file to plat-samsung for all Samsung SoC users, and update Kconfig names to make them SAMSUNG_ instead of S3C2410_ Sed expresions used to make the change: s/S3C2410_PM_DEBUG/SAMSUNG_PM_DEBUG/g s/S3C2410_PM_CHECK/SAMSUNG_PM_CHECK/g Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm/plat-samsung')
-rw-r--r--arch/arm/plat-samsung/Kconfig45
-rw-r--r--arch/arm/plat-samsung/Makefile1
-rw-r--r--arch/arm/plat-samsung/pm-check.c242
3 files changed, 288 insertions, 0 deletions
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 6484b5bf82c3..1c2fe91c23e9 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -132,4 +132,49 @@ config S3C_DEV_NAND
132 help 132 help
133 Compile in platform device definition for NAND controller 133 Compile in platform device definition for NAND controller
134 134
135comment "Power management"
136
137config SAMSUNG_PM_DEBUG
138 bool "S3C2410 PM Suspend debug"
139 depends on PM
140 help
141 Say Y here if you want verbose debugging from the PM Suspend and
142 Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
143 for more information.
144
145config S3C_PM_DEBUG_LED_SMDK
146 bool "SMDK LED suspend/resume debugging"
147 depends on PM && (MACH_SMDK6410)
148 help
149 Say Y here to enable the use of the SMDK LEDs on the baseboard
150 for debugging of the state of the suspend and resume process.
151
152 Note, this currently only works for S3C64XX based SMDK boards.
153
154config SAMSUNG_PM_CHECK
155 bool "S3C2410 PM Suspend Memory CRC"
156 depends on PM && CRC32
157 help
158 Enable the PM code's memory area checksum over sleep. This option
159 will generate CRCs of all blocks of memory, and store them before
160 going to sleep. The blocks are then checked on resume for any
161 errors.
162
163 Note, this can take several seconds depending on memory size
164 and CPU speed.
165
166 See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
167
168config SAMSUNG_PM_CHECK_CHUNKSIZE
169 int "S3C2410 PM Suspend CRC Chunksize (KiB)"
170 depends on PM && SAMSUNG_PM_CHECK
171 default 64
172 help
173 Set the chunksize in Kilobytes of the CRC for checking memory
174 corruption over suspend and resume. A smaller value will mean that
175 the CRC data block will take more memory, but wil identify any
176 faults with better precision.
177
178 See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
179
135endif 180endif
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index f31e64f3a1c3..c8c8caec8cde 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o
42# PM support 42# PM support
43 43
44obj-$(CONFIG_PM) += pm-gpio.o 44obj-$(CONFIG_PM) += pm-gpio.o
45obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o
45 46
46# PWM support 47# PWM support
47 48
diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c
new file mode 100644
index 000000000000..0b5bb774192a
--- /dev/null
+++ b/arch/arm/plat-samsung/pm-check.c
@@ -0,0 +1,242 @@
1/* linux/arch/arm/plat-s3c/pm-check.c
2 * originally in linux/arch/arm/plat-s3c24xx/pm.c
3 *
4 * Copyright (c) 2004-2008 Simtec Electronics
5 * http://armlinux.simtec.co.uk
6 * Ben Dooks <ben@simtec.co.uk>
7 *
8 * S3C Power Mangament - suspend/resume memory corruptiuon check.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/suspend.h>
17#include <linux/init.h>
18#include <linux/crc32.h>
19#include <linux/ioport.h>
20
21#include <plat/pm.h>
22
23#if CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE < 1
24#error CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE must be a positive non-zero value
25#endif
26
27/* suspend checking code...
28 *
29 * this next area does a set of crc checks over all the installed
30 * memory, so the system can verify if the resume was ok.
31 *
32 * CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
33 * increasing it will mean that the area corrupted will be less easy to spot,
34 * and reducing the size will cause the CRC save area to grow
35*/
36
37#define CHECK_CHUNKSIZE (CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE * 1024)
38
39static u32 crc_size; /* size needed for the crc block */
40static u32 *crcs; /* allocated over suspend/resume */
41
42typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
43
44/* s3c_pm_run_res
45 *
46 * go through the given resource list, and look for system ram
47*/
48
49static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
50{
51 while (ptr != NULL) {
52 if (ptr->child != NULL)
53 s3c_pm_run_res(ptr->child, fn, arg);
54
55 if ((ptr->flags & IORESOURCE_MEM) &&
56 strcmp(ptr->name, "System RAM") == 0) {
57 S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
58 (unsigned long)ptr->start,
59 (unsigned long)ptr->end);
60 arg = (fn)(ptr, arg);
61 }
62
63 ptr = ptr->sibling;
64 }
65}
66
67static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
68{
69 s3c_pm_run_res(&iomem_resource, fn, arg);
70}
71
72static u32 *s3c_pm_countram(struct resource *res, u32 *val)
73{
74 u32 size = (u32)(res->end - res->start)+1;
75
76 size += CHECK_CHUNKSIZE-1;
77 size /= CHECK_CHUNKSIZE;
78
79 S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
80 (unsigned long)res->start, (unsigned long)res->end, size);
81
82 *val += size * sizeof(u32);
83 return val;
84}
85
86/* s3c_pm_prepare_check
87 *
88 * prepare the necessary information for creating the CRCs. This
89 * must be done before the final save, as it will require memory
90 * allocating, and thus touching bits of the kernel we do not
91 * know about.
92*/
93
94void s3c_pm_check_prepare(void)
95{
96 crc_size = 0;
97
98 s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
99
100 S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
101
102 crcs = kmalloc(crc_size+4, GFP_KERNEL);
103 if (crcs == NULL)
104 printk(KERN_ERR "Cannot allocated CRC save area\n");
105}
106
107static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
108{
109 unsigned long addr, left;
110
111 for (addr = res->start; addr < res->end;
112 addr += CHECK_CHUNKSIZE) {
113 left = res->end - addr;
114
115 if (left > CHECK_CHUNKSIZE)
116 left = CHECK_CHUNKSIZE;
117
118 *val = crc32_le(~0, phys_to_virt(addr), left);
119 val++;
120 }
121
122 return val;
123}
124
125/* s3c_pm_check_store
126 *
127 * compute the CRC values for the memory blocks before the final
128 * sleep.
129*/
130
131void s3c_pm_check_store(void)
132{
133 if (crcs != NULL)
134 s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
135}
136
137/* in_region
138 *
139 * return TRUE if the area defined by ptr..ptr+size contains the
140 * what..what+whatsz
141*/
142
143static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
144{
145 if ((what+whatsz) < ptr)
146 return 0;
147
148 if (what > (ptr+size))
149 return 0;
150
151 return 1;
152}
153
154/**
155 * s3c_pm_runcheck() - helper to check a resource on restore.
156 * @res: The resource to check
157 * @vak: Pointer to list of CRC32 values to check.
158 *
159 * Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
160 * function runs the given memory resource checking it against the stored
161 * CRC to ensure that memory is restored. The function tries to skip as
162 * many of the areas used during the suspend process.
163 */
164static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
165{
166 void *save_at = phys_to_virt(s3c_sleep_save_phys);
167 unsigned long addr;
168 unsigned long left;
169 void *stkpage;
170 void *ptr;
171 u32 calc;
172
173 stkpage = (void *)((u32)&calc & ~PAGE_MASK);
174
175 for (addr = res->start; addr < res->end;
176 addr += CHECK_CHUNKSIZE) {
177 left = res->end - addr;
178
179 if (left > CHECK_CHUNKSIZE)
180 left = CHECK_CHUNKSIZE;
181
182 ptr = phys_to_virt(addr);
183
184 if (in_region(ptr, left, stkpage, 4096)) {
185 S3C_PMDBG("skipping %08lx, has stack in\n", addr);
186 goto skip_check;
187 }
188
189 if (in_region(ptr, left, crcs, crc_size)) {
190 S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
191 goto skip_check;
192 }
193
194 if (in_region(ptr, left, save_at, 32*4 )) {
195 S3C_PMDBG("skipping %08lx, has save block in\n", addr);
196 goto skip_check;
197 }
198
199 /* calculate and check the checksum */
200
201 calc = crc32_le(~0, ptr, left);
202 if (calc != *val) {
203 printk(KERN_ERR "Restore CRC error at "
204 "%08lx (%08x vs %08x)\n", addr, calc, *val);
205
206 S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
207 addr, calc, *val);
208 }
209
210 skip_check:
211 val++;
212 }
213
214 return val;
215}
216
217/**
218 * s3c_pm_check_restore() - memory check called on resume
219 *
220 * check the CRCs after the restore event and free the memory used
221 * to hold them
222*/
223void s3c_pm_check_restore(void)
224{
225 if (crcs != NULL)
226 s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
227}
228
229/**
230 * s3c_pm_check_cleanup() - free memory resources
231 *
232 * Free the resources that where allocated by the suspend
233 * memory check code. We do this separately from the
234 * s3c_pm_check_restore() function as we cannot call any
235 * functions that might sleep during that resume.
236 */
237void s3c_pm_check_cleanup(void)
238{
239 kfree(crcs);
240 crcs = NULL;
241}
242