diff options
| author | Eric Miao <eric.y.miao@gmail.com> | 2007-07-18 06:38:45 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-07-20 12:25:10 -0400 |
| commit | 711be5ccfe9a02ba560aa918a008c31ea4760163 (patch) | |
| tree | b54cba04944a5ae0cb8a2d8ecd4d8efd14f2e495 | |
| parent | e09d02e123fb6944af23a0697369ebcfc15acf73 (diff) | |
[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>
| -rw-r--r-- | arch/arm/mach-pxa/pm.c | 169 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 84 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 117 | ||||
| -rw-r--r-- | include/asm-arm/arch-pxa/pm.h | 11 |
4 files changed, 244 insertions, 137 deletions
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index e66dbc26add1..b59a81a8e7d3 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c | |||
| @@ -24,61 +24,13 @@ | |||
| 24 | #include <asm/arch/lubbock.h> | 24 | #include <asm/arch/lubbock.h> |
| 25 | #include <asm/mach/time.h> | 25 | #include <asm/mach/time.h> |
| 26 | 26 | ||
| 27 | 27 | struct pxa_cpu_pm_fns *pxa_cpu_pm_fns; | |
| 28 | /* | 28 | static unsigned long *sleep_save; |
| 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 | |||
| 75 | 29 | ||
| 76 | int pxa_pm_enter(suspend_state_t state) | 30 | int pxa_pm_enter(suspend_state_t state) |
| 77 | { | 31 | { |
| 78 | unsigned long sleep_save[SLEEP_SAVE_SIZE]; | 32 | unsigned long sleep_save_checksum = 0, checksum = 0; |
| 79 | unsigned long checksum = 0; | ||
| 80 | int i; | 33 | int i; |
| 81 | extern void pxa_cpu_pm_enter(suspend_state_t state); | ||
| 82 | 34 | ||
| 83 | #ifdef CONFIG_IWMMXT | 35 | #ifdef CONFIG_IWMMXT |
| 84 | /* force any iWMMXt context to ram **/ | 36 | /* force any iWMMXt context to ram **/ |
| @@ -86,100 +38,35 @@ int pxa_pm_enter(suspend_state_t state) | |||
| 86 | iwmmxt_task_disable(NULL); | 38 | iwmmxt_task_disable(NULL); |
| 87 | #endif | 39 | #endif |
| 88 | 40 | ||
| 89 | SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); | 41 | pxa_cpu_pm_fns->save(sleep_save); |
| 90 | SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); | ||
| 91 | SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); | ||
| 92 | SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); | ||
| 93 | SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); | ||
| 94 | |||
| 95 | SAVE(GAFR0_L); SAVE(GAFR0_U); | ||
| 96 | SAVE(GAFR1_L); SAVE(GAFR1_U); | ||
| 97 | SAVE(GAFR2_L); SAVE(GAFR2_U); | ||
| 98 | |||
| 99 | #ifdef CONFIG_PXA27x | ||
| 100 | SAVE(MDREFR); | ||
| 101 | SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3); | ||
| 102 | SAVE(GAFR3_L); SAVE(GAFR3_U); | ||
| 103 | SAVE(PWER); SAVE(PCFR); SAVE(PRER); | ||
| 104 | SAVE(PFER); SAVE(PKWR); | ||
| 105 | #endif | ||
| 106 | |||
| 107 | SAVE(ICMR); | ||
| 108 | ICMR = 0; | ||
| 109 | |||
| 110 | SAVE(CKEN); | ||
| 111 | SAVE(PSTR); | ||
| 112 | |||
| 113 | /* Note: wake up source are set up in each machine specific files */ | ||
| 114 | |||
| 115 | /* clear GPIO transition detect bits */ | ||
| 116 | GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; | ||
| 117 | #ifdef CONFIG_PXA27x | ||
| 118 | GEDR3 = GEDR3; | ||
| 119 | #endif | ||
| 120 | 42 | ||
| 121 | /* Clear sleep reset status */ | 43 | /* Clear sleep reset status */ |
| 122 | RCSR = RCSR_SMR; | 44 | RCSR = RCSR_SMR; |
| 123 | 45 | ||
| 124 | /* before sleeping, calculate and save a checksum */ | 46 | /* before sleeping, calculate and save a checksum */ |
| 125 | for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) | 47 | for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) |
| 126 | checksum += sleep_save[i]; | 48 | sleep_save_checksum += sleep_save[i]; |
| 127 | sleep_save[SLEEP_SAVE_CKSUM] = checksum; | ||
| 128 | 49 | ||
| 129 | /* *** go zzz *** */ | 50 | /* *** go zzz *** */ |
| 130 | pxa_cpu_pm_enter(state); | 51 | pxa_cpu_pm_fns->enter(state); |
| 131 | |||
| 132 | cpu_init(); | 52 | cpu_init(); |
| 133 | 53 | ||
| 134 | /* after sleeping, validate the checksum */ | 54 | /* after sleeping, validate the checksum */ |
| 135 | checksum = 0; | 55 | for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++) |
| 136 | for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) | ||
| 137 | checksum += sleep_save[i]; | 56 | checksum += sleep_save[i]; |
| 138 | 57 | ||
| 139 | /* if invalid, display message and wait for a hardware reset */ | 58 | /* if invalid, display message and wait for a hardware reset */ |
| 140 | if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) { | 59 | if (checksum != sleep_save_checksum) { |
| 141 | #ifdef CONFIG_ARCH_LUBBOCK | 60 | #ifdef CONFIG_ARCH_LUBBOCK |
| 142 | LUB_HEXLED = 0xbadbadc5; | 61 | LUB_HEXLED = 0xbadbadc5; |
| 143 | #endif | 62 | #endif |
| 144 | while (1) | 63 | while (1) |
| 145 | pxa_cpu_pm_enter(state); | 64 | pxa_cpu_pm_fns->enter(state); |
| 146 | } | 65 | } |
| 147 | 66 | ||
| 148 | /* ensure not to come back here if it wasn't intended */ | 67 | pxa_cpu_pm_fns->restore(sleep_save); |
| 149 | PSPR = 0; | ||
| 150 | |||
| 151 | /* restore registers */ | ||
| 152 | RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2); | ||
| 153 | RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); | ||
| 154 | RESTORE(GAFR0_L); RESTORE(GAFR0_U); | ||
| 155 | RESTORE(GAFR1_L); RESTORE(GAFR1_U); | ||
| 156 | RESTORE(GAFR2_L); RESTORE(GAFR2_U); | ||
| 157 | RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); | ||
| 158 | RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); | ||
| 159 | RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); | ||
| 160 | |||
| 161 | #ifdef CONFIG_PXA27x | ||
| 162 | RESTORE(MDREFR); | ||
| 163 | RESTORE_GPLEVEL(3); RESTORE(GPDR3); | ||
| 164 | RESTORE(GAFR3_L); RESTORE(GAFR3_U); | ||
| 165 | RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3); | ||
| 166 | RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER); | ||
| 167 | RESTORE(PFER); RESTORE(PKWR); | ||
| 168 | #endif | ||
| 169 | |||
| 170 | PSSR = PSSR_RDH | PSSR_PH; | ||
| 171 | |||
| 172 | RESTORE(CKEN); | ||
| 173 | |||
| 174 | ICLR = 0; | ||
| 175 | ICCR = 1; | ||
| 176 | RESTORE(ICMR); | ||
| 177 | 68 | ||
| 178 | RESTORE(PSTR); | 69 | pr_debug("*** made it back from resume\n"); |
| 179 | |||
| 180 | #ifdef DEBUG | ||
| 181 | printk(KERN_DEBUG "*** made it back from resume\n"); | ||
| 182 | #endif | ||
| 183 | 70 | ||
| 184 | return 0; | 71 | return 0; |
| 185 | } | 72 | } |
| @@ -190,3 +77,35 @@ unsigned long sleep_phys_sp(void *sp) | |||
| 190 | { | 77 | { |
| 191 | return virt_to_phys(sp); | 78 | return virt_to_phys(sp); |
| 192 | } | 79 | } |
| 80 | |||
| 81 | static int pxa_pm_valid(suspend_state_t state) | ||
| 82 | { | ||
| 83 | if (pxa_cpu_pm_fns) | ||
| 84 | return pxa_cpu_pm_fns->valid(state); | ||
| 85 | |||
| 86 | return -EINVAL; | ||
| 87 | } | ||
| 88 | |||
| 89 | static struct pm_ops pxa_pm_ops = { | ||
| 90 | .valid = pxa_pm_valid, | ||
| 91 | .enter = pxa_pm_enter, | ||
| 92 | }; | ||
| 93 | |||
| 94 | static int __init pxa_pm_init(void) | ||
| 95 | { | ||
| 96 | if (!pxa_cpu_pm_fns) { | ||
| 97 | printk(KERN_ERR "no valid pxa_cpu_pm_fns defined\n"); | ||
| 98 | return -EINVAL; | ||
| 99 | } | ||
| 100 | |||
| 101 | sleep_save = kmalloc(pxa_cpu_pm_fns->save_size, GFP_KERNEL); | ||
| 102 | if (!sleep_save) { | ||
| 103 | printk(KERN_ERR "failed to alloc memory for pm save\n"); | ||
| 104 | return -ENOMEM; | ||
| 105 | } | ||
| 106 | |||
| 107 | pm_set_ops(&pxa_pm_ops); | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | device_initcall(pxa_pm_init); | ||
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 9d9422e2f75c..1ec4bf1ff249 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c | |||
| @@ -110,7 +110,75 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz); | |||
| 110 | 110 | ||
| 111 | #ifdef CONFIG_PM | 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 | extern void pxa_cpu_suspend(unsigned int); | 183 | extern void pxa_cpu_suspend(unsigned int); |
| 116 | extern void pxa_cpu_resume(void); | 184 | extern void pxa_cpu_resume(void); |
| @@ -126,10 +194,18 @@ void pxa_cpu_pm_enter(suspend_state_t state) | |||
| 126 | } | 194 | } |
| 127 | } | 195 | } |
| 128 | 196 | ||
| 129 | static struct pm_ops pxa25x_pm_ops = { | 197 | static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = { |
| 130 | .enter = pxa_pm_enter, | 198 | .save_size = SLEEP_SAVE_SIZE, |
| 131 | .valid = pm_valid_only_mem, | 199 | .valid = pm_valid_only_mem, |
| 200 | .save = pxa25x_cpu_pm_save, | ||
| 201 | .restore = pxa25x_cpu_pm_restore, | ||
| 202 | .enter = pxa25x_cpu_pm_enter, | ||
| 132 | }; | 203 | }; |
| 204 | |||
| 205 | static void __init pxa25x_init_pm(void) | ||
| 206 | { | ||
| 207 | pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns; | ||
| 208 | } | ||
| 133 | #endif | 209 | #endif |
| 134 | 210 | ||
| 135 | void __init pxa25x_init_irq(void) | 211 | void __init pxa25x_init_irq(void) |
| @@ -159,7 +235,7 @@ static int __init pxa25x_init(void) | |||
| 159 | if ((ret = pxa_init_dma(16))) | 235 | if ((ret = pxa_init_dma(16))) |
| 160 | return ret; | 236 | return ret; |
| 161 | #ifdef CONFIG_PM | 237 | #ifdef CONFIG_PM |
| 162 | pm_set_ops(&pxa25x_pm_ops); | 238 | pxa25x_init_pm(); |
| 163 | #endif | 239 | #endif |
| 164 | ret = platform_add_devices(pxa25x_devices, | 240 | ret = platform_add_devices(pxa25x_devices, |
| 165 | ARRAY_SIZE(pxa25x_devices)); | 241 | ARRAY_SIZE(pxa25x_devices)); |
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index c85f0b01c326..9240d37e23fa 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
| @@ -126,14 +126,109 @@ 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); | 226 | extern void pxa_cpu_suspend(unsigned int); |
| 133 | extern void pxa_cpu_resume(void); | 227 | extern void pxa_cpu_resume(void); |
| 134 | 228 | ||
| 135 | if (state == PM_SUSPEND_STANDBY) | 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 | else | 232 | else |
| 138 | CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER); | 233 | CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER); |
| 139 | 234 | ||
| @@ -155,15 +250,23 @@ void pxa_cpu_pm_enter(suspend_state_t state) | |||
| 155 | } | 250 | } |
| 156 | } | 251 | } |
| 157 | 252 | ||
| 158 | static int pxa27x_pm_valid(suspend_state_t state) | 253 | static int pxa27x_cpu_pm_valid(suspend_state_t state) |
| 159 | { | 254 | { |
| 160 | return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; | 255 | return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; |
| 161 | } | 256 | } |
| 162 | 257 | ||
| 163 | static struct pm_ops pxa27x_pm_ops = { | 258 | static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = { |
| 164 | .enter = pxa_pm_enter, | 259 | .save_size = SLEEP_SAVE_SIZE, |
| 165 | .valid = pxa27x_pm_valid, | 260 | .save = pxa27x_cpu_pm_save, |
| 261 | .restore = pxa27x_cpu_pm_restore, | ||
| 262 | .valid = pxa27x_cpu_pm_valid, | ||
| 263 | .enter = pxa27x_cpu_pm_enter, | ||
| 166 | }; | 264 | }; |
| 265 | |||
| 266 | static void __init pxa27x_init_pm(void) | ||
| 267 | { | ||
| 268 | pxa_cpu_pm_fns = &pxa27x_cpu_pm_fns; | ||
| 269 | } | ||
| 167 | #endif | 270 | #endif |
| 168 | 271 | ||
| 169 | /* | 272 | /* |
| @@ -249,7 +352,7 @@ static int __init pxa27x_init(void) | |||
| 249 | if ((ret = pxa_init_dma(32))) | 352 | if ((ret = pxa_init_dma(32))) |
| 250 | return ret; | 353 | return ret; |
| 251 | #ifdef CONFIG_PM | 354 | #ifdef CONFIG_PM |
| 252 | pm_set_ops(&pxa27x_pm_ops); | 355 | pxa27x_init_pm(); |
| 253 | #endif | 356 | #endif |
| 254 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); | 357 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); |
| 255 | } | 358 | } |
diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h index 52243a62c4e7..62b69004819d 100644 --- a/include/asm-arm/arch-pxa/pm.h +++ b/include/asm-arm/arch-pxa/pm.h | |||
| @@ -7,5 +7,14 @@ | |||
| 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 | extern int pxa_pm_enter(suspend_state_t state); | 20 | extern int pxa_pm_enter(suspend_state_t state); |
