Commit 8775420d authored by Todd Poynor's avatar Todd Poynor Committed by Russell King

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 718a30a5
...@@ -304,6 +304,15 @@ static void __init mainstone_map_io(void) ...@@ -304,6 +304,15 @@ static void __init mainstone_map_io(void)
PWER = 0xC0000002; PWER = 0xC0000002;
PRER = 0x00000002; PRER = 0x00000002;
PFER = 0x00000002; PFER = 0x00000002;
/* for use I SRAM as framebuffer. */
PSLR |= 0xF04;
PCFR = 0x66;
/* For Keypad wakeup. */
KPC &=~KPC_ASACT;
KPC |=KPC_AS;
PKWR = 0x000FD000;
/* Need read PKWR back after set it. */
PKWR;
} }
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)") MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
......
...@@ -29,9 +29,6 @@ ...@@ -29,9 +29,6 @@
*/ */
#undef DEBUG #undef DEBUG
extern void pxa_cpu_suspend(void);
extern void pxa_cpu_resume(void);
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
...@@ -63,6 +60,12 @@ enum { SLEEP_SAVE_START = 0, ...@@ -63,6 +60,12 @@ enum { SLEEP_SAVE_START = 0,
SLEEP_SAVE_ICMR, SLEEP_SAVE_ICMR,
SLEEP_SAVE_CKEN, SLEEP_SAVE_CKEN,
#ifdef CONFIG_PXA27x
SLEEP_SAVE_MDREFR,
SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
#endif
SLEEP_SAVE_CKSUM, SLEEP_SAVE_CKSUM,
SLEEP_SAVE_SIZE SLEEP_SAVE_SIZE
...@@ -75,9 +78,7 @@ static int pxa_pm_enter(suspend_state_t state) ...@@ -75,9 +78,7 @@ static int pxa_pm_enter(suspend_state_t state)
unsigned long checksum = 0; unsigned long checksum = 0;
struct timespec delta, rtc; struct timespec delta, rtc;
int i; int i;
extern void pxa_cpu_pm_enter(suspend_state_t state);
if (state != PM_SUSPEND_MEM)
return -EINVAL;
#ifdef CONFIG_IWMMXT #ifdef CONFIG_IWMMXT
/* force any iWMMXt context to ram **/ /* force any iWMMXt context to ram **/
...@@ -100,16 +101,17 @@ static int pxa_pm_enter(suspend_state_t state) ...@@ -100,16 +101,17 @@ static int pxa_pm_enter(suspend_state_t state)
SAVE(GAFR2_L); SAVE(GAFR2_U); SAVE(GAFR2_L); SAVE(GAFR2_U);
#ifdef CONFIG_PXA27x #ifdef CONFIG_PXA27x
SAVE(MDREFR);
SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3); SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
SAVE(GAFR3_L); SAVE(GAFR3_U); SAVE(GAFR3_L); SAVE(GAFR3_U);
SAVE(PWER); SAVE(PCFR); SAVE(PRER);
SAVE(PFER); SAVE(PKWR);
#endif #endif
SAVE(ICMR); SAVE(ICMR);
ICMR = 0; ICMR = 0;
SAVE(CKEN); SAVE(CKEN);
CKEN = 0;
SAVE(PSTR); SAVE(PSTR);
/* Note: wake up source are set up in each machine specific files */ /* Note: wake up source are set up in each machine specific files */
...@@ -123,16 +125,13 @@ static int pxa_pm_enter(suspend_state_t state) ...@@ -123,16 +125,13 @@ static int pxa_pm_enter(suspend_state_t state)
/* Clear sleep reset status */ /* Clear sleep reset status */
RCSR = RCSR_SMR; RCSR = RCSR_SMR;
/* set resume return address */
PSPR = virt_to_phys(pxa_cpu_resume);
/* before sleeping, calculate and save a checksum */ /* before sleeping, calculate and save a checksum */
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
checksum += sleep_save[i]; checksum += sleep_save[i];
sleep_save[SLEEP_SAVE_CKSUM] = checksum; sleep_save[SLEEP_SAVE_CKSUM] = checksum;
/* *** go zzz *** */ /* *** go zzz *** */
pxa_cpu_suspend(); pxa_cpu_pm_enter(state);
/* after sleeping, validate the checksum */ /* after sleeping, validate the checksum */
checksum = 0; checksum = 0;
...@@ -145,7 +144,7 @@ static int pxa_pm_enter(suspend_state_t state) ...@@ -145,7 +144,7 @@ static int pxa_pm_enter(suspend_state_t state)
LUB_HEXLED = 0xbadbadc5; LUB_HEXLED = 0xbadbadc5;
#endif #endif
while (1) while (1)
pxa_cpu_suspend(); pxa_cpu_pm_enter(state);
} }
/* ensure not to come back here if it wasn't intended */ /* ensure not to come back here if it wasn't intended */
...@@ -162,8 +161,11 @@ static int pxa_pm_enter(suspend_state_t state) ...@@ -162,8 +161,11 @@ static int pxa_pm_enter(suspend_state_t state)
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
#ifdef CONFIG_PXA27x #ifdef CONFIG_PXA27x
RESTORE(MDREFR);
RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3); RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3); RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
RESTORE(PFER); RESTORE(PKWR);
#endif #endif
PSSR = PSSR_RDH | PSSR_PH; PSSR = PSSR_RDH | PSSR_PH;
...@@ -197,7 +199,9 @@ unsigned long sleep_phys_sp(void *sp) ...@@ -197,7 +199,9 @@ unsigned long sleep_phys_sp(void *sp)
*/ */
static int pxa_pm_prepare(suspend_state_t state) static int pxa_pm_prepare(suspend_state_t state)
{ {
return 0; extern int pxa_cpu_pm_prepare(suspend_state_t state);
return pxa_cpu_pm_prepare(state);
} }
/* /*
......
...@@ -102,3 +102,32 @@ unsigned int get_lcdclk_frequency_10khz(void) ...@@ -102,3 +102,32 @@ unsigned int get_lcdclk_frequency_10khz(void)
} }
EXPORT_SYMBOL(get_lcdclk_frequency_10khz); EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
int pxa_cpu_pm_prepare(suspend_state_t state)
{
switch (state) {
case PM_SUSPEND_MEM:
break;
default:
return -EINVAL;
}
return 0;
}
void pxa_cpu_pm_enter(suspend_state_t state)
{
extern void pxa_cpu_suspend(unsigned int);
extern void pxa_cpu_resume(void);
CKEN = 0;
switch (state) {
case PM_SUSPEND_MEM:
/* set resume return address */
PSPR = virt_to_phys(pxa_cpu_resume);
pxa_cpu_suspend(3);
break;
}
}
...@@ -120,6 +120,38 @@ EXPORT_SYMBOL(get_clk_frequency_khz); ...@@ -120,6 +120,38 @@ EXPORT_SYMBOL(get_clk_frequency_khz);
EXPORT_SYMBOL(get_memclk_frequency_10khz); EXPORT_SYMBOL(get_memclk_frequency_10khz);
EXPORT_SYMBOL(get_lcdclk_frequency_10khz); EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
int pxa_cpu_pm_prepare(suspend_state_t state)
{
switch (state) {
case PM_SUSPEND_MEM:
return 0;
default:
return -EINVAL;
}
}
void pxa_cpu_pm_enter(suspend_state_t state)
{
extern void pxa_cpu_standby(void);
extern void pxa_cpu_suspend(unsigned int);
extern void pxa_cpu_resume(void);
CKEN = CKEN22_MEMC | CKEN9_OSTIMER;
/* ensure voltage-change sequencer not initiated, which hangs */
PCFR &= ~PCFR_FVC;
/* Clear edge-detect status register. */
PEDR = 0xDF12FE1B;
switch (state) {
case PM_SUSPEND_MEM:
/* set resume return address */
PSPR = virt_to_phys(pxa_cpu_resume);
pxa_cpu_suspend(3);
break;
}
}
/* /*
* device registration specific to PXA27x. * device registration specific to PXA27x.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment