Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] ARM: 2691/1: PXA27x sleep fixes take 2

Patch from Todd Poynor

PXA27x sleep fixes:
* set additional sleep/wakeup registers for Mainstone boards.
* move CKEN=0 to pxa25x-specific code; that value is harmful on pxa27x.
* save/restore additional registers, including some found necessary for
C5 processors and/or newer blob versions.
* enable future support of additional sleep modes for PXA27x (eg,
standby, deep sleep).
* split off cpu-specific sleep processing between pxa27x and pxa25x into
separate files (partly in preparation for additional sleep modes).
Includes fixes from David Burrage.

Signed-off-by: Todd Poynor
Signed-off-by: Nicolas Pitre
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Todd Poynor and committed by
Russell King
8775420d 718a30a5

+88 -14
+9
arch/arm/mach-pxa/mainstone.c
··· 304 304 PWER = 0xC0000002; 305 305 PRER = 0x00000002; 306 306 PFER = 0x00000002; 307 + /* for use I SRAM as framebuffer. */ 308 + PSLR |= 0xF04; 309 + PCFR = 0x66; 310 + /* For Keypad wakeup. */ 311 + KPC &=~KPC_ASACT; 312 + KPC |=KPC_AS; 313 + PKWR = 0x000FD000; 314 + /* Need read PKWR back after set it. */ 315 + PKWR; 307 316 } 308 317 309 318 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
+18 -14
arch/arm/mach-pxa/pm.c
··· 29 29 */ 30 30 #undef DEBUG 31 31 32 - extern void pxa_cpu_suspend(void); 33 - extern void pxa_cpu_resume(void); 34 - 35 32 #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x 36 33 #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] 37 34 ··· 60 63 SLEEP_SAVE_ICMR, 61 64 SLEEP_SAVE_CKEN, 62 65 66 + #ifdef CONFIG_PXA27x 67 + SLEEP_SAVE_MDREFR, 68 + SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER, 69 + SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR, 70 + #endif 71 + 63 72 SLEEP_SAVE_CKSUM, 64 73 65 74 SLEEP_SAVE_SIZE ··· 78 75 unsigned long checksum = 0; 79 76 struct timespec delta, rtc; 80 77 int i; 81 - 82 - if (state != PM_SUSPEND_MEM) 83 - return -EINVAL; 78 + extern void pxa_cpu_pm_enter(suspend_state_t state); 84 79 85 80 #ifdef CONFIG_IWMMXT 86 81 /* force any iWMMXt context to ram **/ ··· 101 100 SAVE(GAFR2_L); SAVE(GAFR2_U); 102 101 103 102 #ifdef CONFIG_PXA27x 103 + SAVE(MDREFR); 104 104 SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3); 105 105 SAVE(GAFR3_L); SAVE(GAFR3_U); 106 + SAVE(PWER); SAVE(PCFR); SAVE(PRER); 107 + SAVE(PFER); SAVE(PKWR); 106 108 #endif 107 109 108 110 SAVE(ICMR); 109 111 ICMR = 0; 110 112 111 113 SAVE(CKEN); 112 - CKEN = 0; 113 - 114 114 SAVE(PSTR); 115 115 116 116 /* Note: wake up source are set up in each machine specific files */ ··· 125 123 /* Clear sleep reset status */ 126 124 RCSR = RCSR_SMR; 127 125 128 - /* set resume return address */ 129 - PSPR = virt_to_phys(pxa_cpu_resume); 130 - 131 126 /* before sleeping, calculate and save a checksum */ 132 127 for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) 133 128 checksum += sleep_save[i]; 134 129 sleep_save[SLEEP_SAVE_CKSUM] = checksum; 135 130 136 131 /* *** go zzz *** */ 137 - pxa_cpu_suspend(); 132 + pxa_cpu_pm_enter(state); 138 133 139 134 /* after sleeping, validate the checksum */ 140 135 checksum = 0; ··· 144 145 LUB_HEXLED = 0xbadbadc5; 145 146 #endif 146 147 while (1) 147 - pxa_cpu_suspend(); 148 + pxa_cpu_pm_enter(state); 148 149 } 149 150 150 151 /* ensure not to come back here if it wasn't intended */ ··· 161 162 RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); 162 163 163 164 #ifdef CONFIG_PXA27x 165 + RESTORE(MDREFR); 164 166 RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3); 165 167 RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3); 168 + RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER); 169 + RESTORE(PFER); RESTORE(PKWR); 166 170 #endif 167 171 168 172 PSSR = PSSR_RDH | PSSR_PH; ··· 199 197 */ 200 198 static int pxa_pm_prepare(suspend_state_t state) 201 199 { 202 - return 0; 200 + extern int pxa_cpu_pm_prepare(suspend_state_t state); 201 + 202 + return pxa_cpu_pm_prepare(state); 203 203 } 204 204 205 205 /*
+29
arch/arm/mach-pxa/pxa25x.c
··· 102 102 } 103 103 104 104 EXPORT_SYMBOL(get_lcdclk_frequency_10khz); 105 + 106 + 107 + int pxa_cpu_pm_prepare(suspend_state_t state) 108 + { 109 + switch (state) { 110 + case PM_SUSPEND_MEM: 111 + break; 112 + default: 113 + return -EINVAL; 114 + } 115 + 116 + return 0; 117 + } 118 + 119 + void pxa_cpu_pm_enter(suspend_state_t state) 120 + { 121 + extern void pxa_cpu_suspend(unsigned int); 122 + extern void pxa_cpu_resume(void); 123 + 124 + CKEN = 0; 125 + 126 + switch (state) { 127 + case PM_SUSPEND_MEM: 128 + /* set resume return address */ 129 + PSPR = virt_to_phys(pxa_cpu_resume); 130 + pxa_cpu_suspend(3); 131 + break; 132 + } 133 + }
+32
arch/arm/mach-pxa/pxa27x.c
··· 120 120 EXPORT_SYMBOL(get_memclk_frequency_10khz); 121 121 EXPORT_SYMBOL(get_lcdclk_frequency_10khz); 122 122 123 + int pxa_cpu_pm_prepare(suspend_state_t state) 124 + { 125 + switch (state) { 126 + case PM_SUSPEND_MEM: 127 + return 0; 128 + default: 129 + return -EINVAL; 130 + } 131 + } 132 + 133 + void pxa_cpu_pm_enter(suspend_state_t state) 134 + { 135 + extern void pxa_cpu_standby(void); 136 + extern void pxa_cpu_suspend(unsigned int); 137 + extern void pxa_cpu_resume(void); 138 + 139 + CKEN = CKEN22_MEMC | CKEN9_OSTIMER; 140 + 141 + /* ensure voltage-change sequencer not initiated, which hangs */ 142 + PCFR &= ~PCFR_FVC; 143 + 144 + /* Clear edge-detect status register. */ 145 + PEDR = 0xDF12FE1B; 146 + 147 + switch (state) { 148 + case PM_SUSPEND_MEM: 149 + /* set resume return address */ 150 + PSPR = virt_to_phys(pxa_cpu_resume); 151 + pxa_cpu_suspend(3); 152 + break; 153 + } 154 + } 123 155 124 156 /* 125 157 * device registration specific to PXA27x.