aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/pxa25x.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa/pxa25x.c')
-rw-r--r--arch/arm/mach-pxa/pxa25x.c109
1 files changed, 91 insertions, 18 deletions
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index f36ca448338e..6dfcca72e90f 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -110,26 +110,99 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
110 110
111#ifdef CONFIG_PM 111#ifdef CONFIG_PM
112 112
113void pxa_cpu_pm_enter(suspend_state_t state) 113#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
114#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
115
116#define RESTORE_GPLEVEL(n) do { \
117 GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
118 GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
119} while (0)
120
121/*
122 * List of global PXA peripheral registers to preserve.
123 * More ones like CP and general purpose register values are preserved
124 * with the stack pointer in sleep.S.
125 */
126enum { SLEEP_SAVE_START = 0,
127
128 SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
129 SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
130 SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
131 SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
132 SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
133
134 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
135 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
136 SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
137
138 SLEEP_SAVE_PSTR,
139
140 SLEEP_SAVE_ICMR,
141 SLEEP_SAVE_CKEN,
142
143 SLEEP_SAVE_SIZE
144};
145
146
147static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
148{
149 SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
150 SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
151 SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
152 SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
153 SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
154
155 SAVE(GAFR0_L); SAVE(GAFR0_U);
156 SAVE(GAFR1_L); SAVE(GAFR1_U);
157 SAVE(GAFR2_L); SAVE(GAFR2_U);
158
159 SAVE(ICMR);
160 SAVE(CKEN);
161 SAVE(PSTR);
162}
163
164static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
114{ 165{
115 extern void pxa_cpu_suspend(unsigned int); 166 /* restore registers */
116 extern void pxa_cpu_resume(void); 167 RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
168 RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
169 RESTORE(GAFR0_L); RESTORE(GAFR0_U);
170 RESTORE(GAFR1_L); RESTORE(GAFR1_U);
171 RESTORE(GAFR2_L); RESTORE(GAFR2_U);
172 RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
173 RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
174 RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
175
176 RESTORE(CKEN);
177 RESTORE(ICMR);
178 RESTORE(PSTR);
179}
117 180
181static void pxa25x_cpu_pm_enter(suspend_state_t state)
182{
118 CKEN = 0; 183 CKEN = 0;
119 184
120 switch (state) { 185 switch (state) {
121 case PM_SUSPEND_MEM: 186 case PM_SUSPEND_MEM:
122 /* set resume return address */ 187 /* set resume return address */
123 PSPR = virt_to_phys(pxa_cpu_resume); 188 PSPR = virt_to_phys(pxa_cpu_resume);
124 pxa_cpu_suspend(PWRMODE_SLEEP); 189 pxa25x_cpu_suspend(PWRMODE_SLEEP);
125 break; 190 break;
126 } 191 }
127} 192}
128 193
129static struct pm_ops pxa25x_pm_ops = { 194static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
130 .enter = pxa_pm_enter, 195 .save_size = SLEEP_SAVE_SIZE,
131 .valid = pm_valid_only_mem, 196 .valid = pm_valid_only_mem,
197 .save = pxa25x_cpu_pm_save,
198 .restore = pxa25x_cpu_pm_restore,
199 .enter = pxa25x_cpu_pm_enter,
132}; 200};
201
202static void __init pxa25x_init_pm(void)
203{
204 pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns;
205}
133#endif 206#endif
134 207
135void __init pxa25x_init_irq(void) 208void __init pxa25x_init_irq(void)
@@ -139,16 +212,16 @@ void __init pxa25x_init_irq(void)
139} 212}
140 213
141static struct platform_device *pxa25x_devices[] __initdata = { 214static struct platform_device *pxa25x_devices[] __initdata = {
142 &pxamci_device, 215 &pxa_device_mci,
143 &pxaudc_device, 216 &pxa_device_udc,
144 &pxafb_device, 217 &pxa_device_fb,
145 &ffuart_device, 218 &pxa_device_ffuart,
146 &btuart_device, 219 &pxa_device_btuart,
147 &stuart_device, 220 &pxa_device_stuart,
148 &pxai2c_device, 221 &pxa_device_i2c,
149 &pxai2s_device, 222 &pxa_device_i2s,
150 &pxaficp_device, 223 &pxa_device_ficp,
151 &pxartc_device, 224 &pxa_device_rtc,
152}; 225};
153 226
154static int __init pxa25x_init(void) 227static int __init pxa25x_init(void)
@@ -159,14 +232,14 @@ static int __init pxa25x_init(void)
159 if ((ret = pxa_init_dma(16))) 232 if ((ret = pxa_init_dma(16)))
160 return ret; 233 return ret;
161#ifdef CONFIG_PM 234#ifdef CONFIG_PM
162 pm_set_ops(&pxa25x_pm_ops); 235 pxa25x_init_pm();
163#endif 236#endif
164 ret = platform_add_devices(pxa25x_devices, 237 ret = platform_add_devices(pxa25x_devices,
165 ARRAY_SIZE(pxa25x_devices)); 238 ARRAY_SIZE(pxa25x_devices));
166 } 239 }
167 /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ 240 /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
168 if (cpu_is_pxa25x()) 241 if (cpu_is_pxa25x())
169 ret = platform_device_register(&hwuart_device); 242 ret = platform_device_register(&pxa_device_hwuart);
170 243
171 return ret; 244 return ret;
172} 245}