diff options
Diffstat (limited to 'arch/arm/mach-pxa/pxa27x.c')
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 151 |
1 files changed, 126 insertions, 25 deletions
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index aa5bb02c897b..203371ab19db 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
@@ -126,14 +126,107 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz); | |||
126 | 126 | ||
127 | #ifdef CONFIG_PM | 127 | #ifdef CONFIG_PM |
128 | 128 | ||
129 | void pxa_cpu_pm_enter(suspend_state_t state) | 129 | #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x |
130 | #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] | ||
131 | |||
132 | #define RESTORE_GPLEVEL(n) do { \ | ||
133 | GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \ | ||
134 | GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \ | ||
135 | } while (0) | ||
136 | |||
137 | /* | ||
138 | * List of global PXA peripheral registers to preserve. | ||
139 | * More ones like CP and general purpose register values are preserved | ||
140 | * with the stack pointer in sleep.S. | ||
141 | */ | ||
142 | enum { SLEEP_SAVE_START = 0, | ||
143 | |||
144 | SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3, | ||
145 | SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3, | ||
146 | SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3, | ||
147 | SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3, | ||
148 | SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, | ||
149 | |||
150 | SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, | ||
151 | SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, | ||
152 | SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U, | ||
153 | SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U, | ||
154 | |||
155 | SLEEP_SAVE_PSTR, | ||
156 | |||
157 | SLEEP_SAVE_ICMR, | ||
158 | SLEEP_SAVE_CKEN, | ||
159 | |||
160 | SLEEP_SAVE_MDREFR, | ||
161 | SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER, | ||
162 | SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR, | ||
163 | |||
164 | SLEEP_SAVE_SIZE | ||
165 | }; | ||
166 | |||
167 | void pxa27x_cpu_pm_save(unsigned long *sleep_save) | ||
168 | { | ||
169 | SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3); | ||
170 | SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3); | ||
171 | SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3); | ||
172 | SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3); | ||
173 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3); | ||
174 | |||
175 | SAVE(GAFR0_L); SAVE(GAFR0_U); | ||
176 | SAVE(GAFR1_L); SAVE(GAFR1_U); | ||
177 | SAVE(GAFR2_L); SAVE(GAFR2_U); | ||
178 | SAVE(GAFR3_L); SAVE(GAFR3_U); | ||
179 | |||
180 | SAVE(MDREFR); | ||
181 | SAVE(PWER); SAVE(PCFR); SAVE(PRER); | ||
182 | SAVE(PFER); SAVE(PKWR); | ||
183 | |||
184 | SAVE(ICMR); ICMR = 0; | ||
185 | SAVE(CKEN); | ||
186 | SAVE(PSTR); | ||
187 | |||
188 | /* Clear GPIO transition detect bits */ | ||
189 | GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3; | ||
190 | } | ||
191 | |||
192 | void pxa27x_cpu_pm_restore(unsigned long *sleep_save) | ||
193 | { | ||
194 | /* ensure not to come back here if it wasn't intended */ | ||
195 | PSPR = 0; | ||
196 | |||
197 | /* restore registers */ | ||
198 | RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); | ||
199 | RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3); | ||
200 | RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3); | ||
201 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); | ||
202 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); | ||
203 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); | ||
204 | RESTORE(GAFR3_L); RESTORE(GAFR3_U); | ||
205 | RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3); | ||
206 | RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3); | ||
207 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3); | ||
208 | |||
209 | RESTORE(MDREFR); | ||
210 | RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER); | ||
211 | RESTORE(PFER); RESTORE(PKWR); | ||
212 | |||
213 | PSSR = PSSR_RDH | PSSR_PH; | ||
214 | |||
215 | RESTORE(CKEN); | ||
216 | |||
217 | ICLR = 0; | ||
218 | ICCR = 1; | ||
219 | RESTORE(ICMR); | ||
220 | RESTORE(PSTR); | ||
221 | } | ||
222 | |||
223 | void pxa27x_cpu_pm_enter(suspend_state_t state) | ||
130 | { | 224 | { |
131 | extern void pxa_cpu_standby(void); | 225 | extern void pxa_cpu_standby(void); |
132 | extern void pxa_cpu_suspend(unsigned int); | ||
133 | extern void pxa_cpu_resume(void); | ||
134 | 226 | ||
135 | if (state == PM_SUSPEND_STANDBY) | 227 | if (state == PM_SUSPEND_STANDBY) |
136 | CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | (1 << CKEN_LCD) | (1 << CKEN_PWM0); | 228 | CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | |
229 | (1 << CKEN_LCD) | (1 << CKEN_PWM0); | ||
137 | else | 230 | else |
138 | CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER); | 231 | CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER); |
139 | 232 | ||
@@ -150,20 +243,28 @@ void pxa_cpu_pm_enter(suspend_state_t state) | |||
150 | case PM_SUSPEND_MEM: | 243 | case PM_SUSPEND_MEM: |
151 | /* set resume return address */ | 244 | /* set resume return address */ |
152 | PSPR = virt_to_phys(pxa_cpu_resume); | 245 | PSPR = virt_to_phys(pxa_cpu_resume); |
153 | pxa_cpu_suspend(PWRMODE_SLEEP); | 246 | pxa27x_cpu_suspend(PWRMODE_SLEEP); |
154 | break; | 247 | break; |
155 | } | 248 | } |
156 | } | 249 | } |
157 | 250 | ||
158 | static int pxa27x_pm_valid(suspend_state_t state) | 251 | static int pxa27x_cpu_pm_valid(suspend_state_t state) |
159 | { | 252 | { |
160 | return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; | 253 | return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; |
161 | } | 254 | } |
162 | 255 | ||
163 | static struct pm_ops pxa27x_pm_ops = { | 256 | static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = { |
164 | .enter = pxa_pm_enter, | 257 | .save_size = SLEEP_SAVE_SIZE, |
165 | .valid = pxa27x_pm_valid, | 258 | .save = pxa27x_cpu_pm_save, |
259 | .restore = pxa27x_cpu_pm_restore, | ||
260 | .valid = pxa27x_cpu_pm_valid, | ||
261 | .enter = pxa27x_cpu_pm_enter, | ||
166 | }; | 262 | }; |
263 | |||
264 | static void __init pxa27x_init_pm(void) | ||
265 | { | ||
266 | pxa_cpu_pm_fns = &pxa27x_cpu_pm_fns; | ||
267 | } | ||
167 | #endif | 268 | #endif |
168 | 269 | ||
169 | /* | 270 | /* |
@@ -185,7 +286,7 @@ static struct resource pxa27x_ohci_resources[] = { | |||
185 | }, | 286 | }, |
186 | }; | 287 | }; |
187 | 288 | ||
188 | static struct platform_device pxaohci_device = { | 289 | static struct platform_device pxa27x_device_ohci = { |
189 | .name = "pxa27x-ohci", | 290 | .name = "pxa27x-ohci", |
190 | .id = -1, | 291 | .id = -1, |
191 | .dev = { | 292 | .dev = { |
@@ -198,7 +299,7 @@ static struct platform_device pxaohci_device = { | |||
198 | 299 | ||
199 | void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) | 300 | void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) |
200 | { | 301 | { |
201 | pxaohci_device.dev.platform_data = info; | 302 | pxa27x_device_ohci.dev.platform_data = info; |
202 | } | 303 | } |
203 | 304 | ||
204 | static struct resource i2c_power_resources[] = { | 305 | static struct resource i2c_power_resources[] = { |
@@ -213,7 +314,7 @@ static struct resource i2c_power_resources[] = { | |||
213 | }, | 314 | }, |
214 | }; | 315 | }; |
215 | 316 | ||
216 | static struct platform_device pxai2c_power_device = { | 317 | static struct platform_device pxa27x_device_i2c_power = { |
217 | .name = "pxa2xx-i2c", | 318 | .name = "pxa2xx-i2c", |
218 | .id = 1, | 319 | .id = 1, |
219 | .resource = i2c_power_resources, | 320 | .resource = i2c_power_resources, |
@@ -221,18 +322,18 @@ static struct platform_device pxai2c_power_device = { | |||
221 | }; | 322 | }; |
222 | 323 | ||
223 | static struct platform_device *devices[] __initdata = { | 324 | static struct platform_device *devices[] __initdata = { |
224 | &pxamci_device, | 325 | &pxa_device_mci, |
225 | &pxaudc_device, | 326 | &pxa_device_udc, |
226 | &pxafb_device, | 327 | &pxa_device_fb, |
227 | &ffuart_device, | 328 | &pxa_device_ffuart, |
228 | &btuart_device, | 329 | &pxa_device_btuart, |
229 | &stuart_device, | 330 | &pxa_device_stuart, |
230 | &pxai2c_device, | 331 | &pxa_device_i2c, |
231 | &pxai2c_power_device, | 332 | &pxa_device_i2s, |
232 | &pxai2s_device, | 333 | &pxa_device_ficp, |
233 | &pxaficp_device, | 334 | &pxa_device_rtc, |
234 | &pxartc_device, | 335 | &pxa27x_device_i2c_power, |
235 | &pxaohci_device, | 336 | &pxa27x_device_ohci, |
236 | }; | 337 | }; |
237 | 338 | ||
238 | void __init pxa27x_init_irq(void) | 339 | void __init pxa27x_init_irq(void) |
@@ -249,7 +350,7 @@ static int __init pxa27x_init(void) | |||
249 | if ((ret = pxa_init_dma(32))) | 350 | if ((ret = pxa_init_dma(32))) |
250 | return ret; | 351 | return ret; |
251 | #ifdef CONFIG_PM | 352 | #ifdef CONFIG_PM |
252 | pm_set_ops(&pxa27x_pm_ops); | 353 | pxa27x_init_pm(); |
253 | #endif | 354 | #endif |
254 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); | 355 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); |
255 | } | 356 | } |