diff options
author | Eric Miao <eric.y.miao@gmail.com> | 2007-07-18 11:38:45 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-07-20 17:25:10 +0100 |
commit | 711be5ccfe9a02ba560aa918a008c31ea4760163 (patch) | |
tree | b54cba04944a5ae0cb8a2d8ecd4d8efd14f2e495 /arch/arm/mach-pxa/pxa25x.c | |
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>
Diffstat (limited to 'arch/arm/mach-pxa/pxa25x.c')
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 84 |
1 files changed, 80 insertions, 4 deletions
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); #ifdef CONFIG_PM -void pxa_cpu_pm_enter(suspend_state_t state) +#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x +#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] + +#define RESTORE_GPLEVEL(n) do { \ + GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \ + GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \ +} while (0) + +/* + * List of global PXA peripheral registers to preserve. + * More ones like CP and general purpose register values are preserved + * with the stack pointer in sleep.S. + */ +enum { SLEEP_SAVE_START = 0, + + SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, + SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, + SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, + SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, + SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, + + SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, + SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U, + SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U, + + SLEEP_SAVE_PSTR, + + SLEEP_SAVE_ICMR, + SLEEP_SAVE_CKEN, + + SLEEP_SAVE_SIZE +}; + + +static void pxa25x_cpu_pm_save(unsigned long *sleep_save) +{ + SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); + SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); + SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); + SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); + SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); + + SAVE(GAFR0_L); SAVE(GAFR0_U); + SAVE(GAFR1_L); SAVE(GAFR1_U); + SAVE(GAFR2_L); SAVE(GAFR2_U); + + SAVE(ICMR); + SAVE(CKEN); + SAVE(PSTR); +} + +static void pxa25x_cpu_pm_restore(unsigned long *sleep_save) +{ + /* restore registers */ + RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2); + RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); + RESTORE(GAFR0_L); RESTORE(GAFR0_U); + RESTORE(GAFR1_L); RESTORE(GAFR1_U); + RESTORE(GAFR2_L); RESTORE(GAFR2_U); + RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); + RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); + RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); + + RESTORE(CKEN); + RESTORE(ICMR); + RESTORE(PSTR); +} + +static void pxa25x_cpu_pm_enter(suspend_state_t state) { extern void pxa_cpu_suspend(unsigned int); extern void pxa_cpu_resume(void); @@ -126,10 +194,18 @@ void pxa_cpu_pm_enter(suspend_state_t state) } } -static struct pm_ops pxa25x_pm_ops = { - .enter = pxa_pm_enter, +static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = { + .save_size = SLEEP_SAVE_SIZE, .valid = pm_valid_only_mem, + .save = pxa25x_cpu_pm_save, + .restore = pxa25x_cpu_pm_restore, + .enter = pxa25x_cpu_pm_enter, }; + +static void __init pxa25x_init_pm(void) +{ + pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns; +} #endif void __init pxa25x_init_irq(void) @@ -159,7 +235,7 @@ static int __init pxa25x_init(void) if ((ret = pxa_init_dma(16))) return ret; #ifdef CONFIG_PM - pm_set_ops(&pxa25x_pm_ops); + pxa25x_init_pm(); #endif ret = platform_add_devices(pxa25x_devices, ARRAY_SIZE(pxa25x_devices)); |