[ARM] 4488/1: pxa: move pxa25x/pxa27x specific code out of pm.c

1. introduce a structure pxa_cpu_pm_fns for pxa25x/pxa27x specific
operations as follows:

struct pxa_cpu_pm_fns {
int save_size;
void (*save)(unsigned long *);
void (*restore)(unsigned long *);
int (*valid)(suspend_state_t state);
void (*enter)(suspend_state_t state);
}

2. processor specific registers saving and restoring are performed
by calling the corresponding (*save) and (*restore)

3. pxa_cpu_pm_fns->save_size should be initialized to the required
size for processor specific registers saving, the allocated
memory address will be passed to (*save) and (*restore)

memory allocation happens early in pxa_pm_init(), and save_size
should be assigned prior to this (which is usually true, since
pxa_pm_init() happens in device_initcall()

4. there're some redundancies for those SLEEP_SAVE_XXX and related
macros, will be fixed later, one way possible is for the system
devices to handle the specific registers saving and restoring

Signed-off-by: eric miao <eric.y.miao@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by Eric Miao and committed by Russell King 711be5cc e09d02e1

+244 -137
+44 -125
arch/arm/mach-pxa/pm.c
··· 24 24 #include <asm/arch/lubbock.h> 25 25 #include <asm/mach/time.h> 26 26 27 - 28 - /* 29 - * Debug macros 30 - */ 31 - #undef DEBUG 32 - 33 - #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x 34 - #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] 35 - 36 - #define RESTORE_GPLEVEL(n) do { \ 37 - GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \ 38 - GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \ 39 - } while (0) 40 - 41 - /* 42 - * List of global PXA peripheral registers to preserve. 43 - * More ones like CP and general purpose register values are preserved 44 - * with the stack pointer in sleep.S. 45 - */ 46 - enum { SLEEP_SAVE_START = 0, 47 - 48 - SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3, 49 - SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3, 50 - SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3, 51 - SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3, 52 - SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, 53 - 54 - SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, 55 - SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, 56 - SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U, 57 - SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U, 58 - 59 - SLEEP_SAVE_PSTR, 60 - 61 - SLEEP_SAVE_ICMR, 62 - SLEEP_SAVE_CKEN, 63 - 64 - #ifdef CONFIG_PXA27x 65 - SLEEP_SAVE_MDREFR, 66 - SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER, 67 - SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR, 68 - #endif 69 - 70 - SLEEP_SAVE_CKSUM, 71 - 72 - SLEEP_SAVE_SIZE 73 - }; 74 - 27 + struct pxa_cpu_pm_fns *pxa_cpu_pm_fns; 28 + static unsigned long *sleep_save; 75 29 76 30 int pxa_pm_enter(suspend_state_t state) 77 31 { 78 - unsigned long sleep_save[SLEEP_SAVE_SIZE]; 79 - unsigned long checksum = 0; 32 + unsigned long sleep_save_checksum = 0, checksum = 0; 80 33 int i; 81 - extern void pxa_cpu_pm_enter(suspend_state_t state); 82 34 83 35 #ifdef CONFIG_IWMMXT 84 36 /* force any iWMMXt context to ram **/ ··· 38 86 iwmmxt_task_disable(NULL); 39 87 #endif 40 88 41 - SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); 42 - SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); 43 - SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); 44 - SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); 45 - SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); 46 - 47 - SAVE(GAFR0_L); SAVE(GAFR0_U); 48 - SAVE(GAFR1_L); SAVE(GAFR1_U); 49 - SAVE(GAFR2_L); SAVE(GAFR2_U); 50 - 51 - #ifdef CONFIG_PXA27x 52 - SAVE(MDREFR); 53 - SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3); 54 - SAVE(GAFR3_L); SAVE(GAFR3_U); 55 - SAVE(PWER); SAVE(PCFR); SAVE(PRER); 56 - SAVE(PFER); SAVE(PKWR); 57 - #endif 58 - 59 - SAVE(ICMR); 60 - ICMR = 0; 61 - 62 - SAVE(CKEN); 63 - SAVE(PSTR); 64 - 65 - /* Note: wake up source are set up in each machine specific files */ 66 - 67 - /* clear GPIO transition detect bits */ 68 - GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; 69 - #ifdef CONFIG_PXA27x 70 - GEDR3 = GEDR3; 71 - #endif 89 + pxa_cpu_pm_fns->save(sleep_save); 72 90 73 91 /* Clear sleep reset status */ 74 92 RCSR = RCSR_SMR; 75 93 76 94 /* before sleeping, calculate and save a checksum */ 77 - for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) 78 - checksum += sleep_save[i]; 79 - sleep_save[SLEEP_SAVE_CKSUM] = checksum; 95 + for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) 96 + sleep_save_checksum += sleep_save[i]; 80 97 81 98 /* *** go zzz *** */ 82 - pxa_cpu_pm_enter(state); 83 - 99 + pxa_cpu_pm_fns->enter(state); 84 100 cpu_init(); 85 101 86 102 /* after sleeping, validate the checksum */ 87 - checksum = 0; 88 - for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) 103 + for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) 89 104 checksum += sleep_save[i]; 90 105 91 106 /* if invalid, display message and wait for a hardware reset */ 92 - if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) { 107 + if (checksum != sleep_save_checksum) { 93 108 #ifdef CONFIG_ARCH_LUBBOCK 94 109 LUB_HEXLED = 0xbadbadc5; 95 110 #endif 96 111 while (1) 97 - pxa_cpu_pm_enter(state); 112 + pxa_cpu_pm_fns->enter(state); 98 113 } 99 114 100 - /* ensure not to come back here if it wasn't intended */ 101 - PSPR = 0; 115 + pxa_cpu_pm_fns->restore(sleep_save); 102 116 103 - /* restore registers */ 104 - RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2); 105 - RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); 106 - RESTORE(GAFR0_L); RESTORE(GAFR0_U); 107 - RESTORE(GAFR1_L); RESTORE(GAFR1_U); 108 - RESTORE(GAFR2_L); RESTORE(GAFR2_U); 109 - RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); 110 - RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); 111 - RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); 112 - 113 - #ifdef CONFIG_PXA27x 114 - RESTORE(MDREFR); 115 - RESTORE_GPLEVEL(3); RESTORE(GPDR3); 116 - RESTORE(GAFR3_L); RESTORE(GAFR3_U); 117 - RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3); 118 - RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER); 119 - RESTORE(PFER); RESTORE(PKWR); 120 - #endif 121 - 122 - PSSR = PSSR_RDH | PSSR_PH; 123 - 124 - RESTORE(CKEN); 125 - 126 - ICLR = 0; 127 - ICCR = 1; 128 - RESTORE(ICMR); 129 - 130 - RESTORE(PSTR); 131 - 132 - #ifdef DEBUG 133 - printk(KERN_DEBUG "*** made it back from resume\n"); 134 - #endif 117 + pr_debug("*** made it back from resume\n"); 135 118 136 119 return 0; 137 120 } ··· 77 190 { 78 191 return virt_to_phys(sp); 79 192 } 193 + 194 + static int pxa_pm_valid(suspend_state_t state) 195 + { 196 + if (pxa_cpu_pm_fns) 197 + return pxa_cpu_pm_fns->valid(state); 198 + 199 + return -EINVAL; 200 + } 201 + 202 + static struct pm_ops pxa_pm_ops = { 203 + .valid = pxa_pm_valid, 204 + .enter = pxa_pm_enter, 205 + }; 206 + 207 + static int __init pxa_pm_init(void) 208 + { 209 + if (!pxa_cpu_pm_fns) { 210 + printk(KERN_ERR "no valid pxa_cpu_pm_fns defined\n"); 211 + return -EINVAL; 212 + } 213 + 214 + sleep_save = kmalloc(pxa_cpu_pm_fns->save_size, GFP_KERNEL); 215 + if (!sleep_save) { 216 + printk(KERN_ERR "failed to alloc memory for pm save\n"); 217 + return -ENOMEM; 218 + } 219 + 220 + pm_set_ops(&pxa_pm_ops); 221 + return 0; 222 + } 223 + 224 + device_initcall(pxa_pm_init);
+80 -4
arch/arm/mach-pxa/pxa25x.c
··· 110 110 111 111 #ifdef CONFIG_PM 112 112 113 - void 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 + */ 126 + enum { 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 + 147 + static 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 + 164 + static void pxa25x_cpu_pm_restore(unsigned long *sleep_save) 165 + { 166 + /* restore registers */ 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 + } 180 + 181 + static void pxa25x_cpu_pm_enter(suspend_state_t state) 114 182 { 115 183 extern void pxa_cpu_suspend(unsigned int); 116 184 extern void pxa_cpu_resume(void); ··· 194 126 } 195 127 } 196 128 197 - static struct pm_ops pxa25x_pm_ops = { 198 - .enter = pxa_pm_enter, 129 + static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = { 130 + .save_size = SLEEP_SAVE_SIZE, 199 131 .valid = pm_valid_only_mem, 132 + .save = pxa25x_cpu_pm_save, 133 + .restore = pxa25x_cpu_pm_restore, 134 + .enter = pxa25x_cpu_pm_enter, 200 135 }; 136 + 137 + static void __init pxa25x_init_pm(void) 138 + { 139 + pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns; 140 + } 201 141 #endif 202 142 203 143 void __init pxa25x_init_irq(void) ··· 235 159 if ((ret = pxa_init_dma(16))) 236 160 return ret; 237 161 #ifdef CONFIG_PM 238 - pm_set_ops(&pxa25x_pm_ops); 162 + pxa25x_init_pm(); 239 163 #endif 240 164 ret = platform_add_devices(pxa25x_devices, 241 165 ARRAY_SIZE(pxa25x_devices));
+110 -7
arch/arm/mach-pxa/pxa27x.c
··· 126 126 127 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 225 extern void pxa_cpu_standby(void); 132 226 extern void pxa_cpu_suspend(unsigned int); 133 227 extern void pxa_cpu_resume(void); 134 228 135 229 if (state == PM_SUSPEND_STANDBY) 136 - CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | (1 << CKEN_LCD) | (1 << CKEN_PWM0); 230 + CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | 231 + (1 << CKEN_LCD) | (1 << CKEN_PWM0); 137 232 else 138 233 CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER); 139 234 ··· 250 155 } 251 156 } 252 157 253 - static int pxa27x_pm_valid(suspend_state_t state) 158 + static int pxa27x_cpu_pm_valid(suspend_state_t state) 254 159 { 255 160 return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; 256 161 } 257 162 258 - static struct pm_ops pxa27x_pm_ops = { 259 - .enter = pxa_pm_enter, 260 - .valid = pxa27x_pm_valid, 163 + static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = { 164 + .save_size = SLEEP_SAVE_SIZE, 165 + .save = pxa27x_cpu_pm_save, 166 + .restore = pxa27x_cpu_pm_restore, 167 + .valid = pxa27x_cpu_pm_valid, 168 + .enter = pxa27x_cpu_pm_enter, 261 169 }; 170 + 171 + static void __init pxa27x_init_pm(void) 172 + { 173 + pxa_cpu_pm_fns = &pxa27x_cpu_pm_fns; 174 + } 262 175 #endif 263 176 264 177 /* ··· 352 249 if ((ret = pxa_init_dma(32))) 353 250 return ret; 354 251 #ifdef CONFIG_PM 355 - pm_set_ops(&pxa27x_pm_ops); 252 + pxa27x_init_pm(); 356 253 #endif 357 254 ret = platform_add_devices(devices, ARRAY_SIZE(devices)); 358 255 }
+10 -1
include/asm-arm/arch-pxa/pm.h
··· 7 7 * 8 8 */ 9 9 10 - extern int pxa_pm_prepare(suspend_state_t state); 10 + struct pxa_cpu_pm_fns { 11 + int save_size; 12 + void (*save)(unsigned long *); 13 + void (*restore)(unsigned long *); 14 + int (*valid)(suspend_state_t state); 15 + void (*enter)(suspend_state_t state); 16 + }; 17 + 18 + extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns; 19 + 11 20 extern int pxa_pm_enter(suspend_state_t state);