forked from Minki/linux
26398a70ea
The name of 'struct pm_ops' suggests that it is related to the power management in general, but in fact it is only related to suspend. Moreover, its name should indicate what this structure is used for, so it seems reasonable to change it to 'struct platform_suspend_ops'. In that case, the name of the global variable of this type used by the PM core and the names of related functions should be changed accordingly. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Cc: Len Brown <lenb@kernel.org> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
137 lines
2.7 KiB
C
137 lines
2.7 KiB
C
/*
|
|
* SA1100 Power Management Routines
|
|
*
|
|
* Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License.
|
|
*
|
|
* History:
|
|
*
|
|
* 2001-02-06: Cliff Brake Initial code
|
|
*
|
|
* 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
|
|
* Chester Kuo <chester@linux.org.tw>
|
|
* Save more value for the resume function! Support
|
|
* Bitsy/Assabet/Freebird board
|
|
*
|
|
* 2001-08-29: Nicolas Pitre <nico@cam.org>
|
|
* Cleaned up, pushed platform dependent stuff
|
|
* in the platform specific files.
|
|
*
|
|
* 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
|
|
* Storage is local on the stack now.
|
|
*/
|
|
#include <linux/init.h>
|
|
#include <linux/suspend.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/time.h>
|
|
|
|
#include <asm/hardware.h>
|
|
#include <asm/memory.h>
|
|
#include <asm/system.h>
|
|
#include <asm/mach/time.h>
|
|
|
|
extern void sa1100_cpu_suspend(void);
|
|
extern void sa1100_cpu_resume(void);
|
|
|
|
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
|
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
|
|
|
/*
|
|
* List of global SA11x0 peripheral registers to preserve.
|
|
* More ones like CP and general purpose register values are preserved
|
|
* on the stack and then the stack pointer is stored last in sleep.S.
|
|
*/
|
|
enum { SLEEP_SAVE_SP = 0,
|
|
|
|
SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
|
|
SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
|
|
|
|
SLEEP_SAVE_Ser1SDCR0,
|
|
|
|
SLEEP_SAVE_SIZE
|
|
};
|
|
|
|
|
|
static int sa11x0_pm_enter(suspend_state_t state)
|
|
{
|
|
unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
|
|
|
|
gpio = GPLR;
|
|
|
|
/* save vital registers */
|
|
SAVE(GPDR);
|
|
SAVE(GAFR);
|
|
|
|
SAVE(PPDR);
|
|
SAVE(PPSR);
|
|
SAVE(PPAR);
|
|
SAVE(PSDR);
|
|
|
|
SAVE(Ser1SDCR0);
|
|
|
|
/* Clear previous reset status */
|
|
RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
|
|
|
|
/* set resume return address */
|
|
PSPR = virt_to_phys(sa1100_cpu_resume);
|
|
|
|
/* go zzz */
|
|
sa1100_cpu_suspend();
|
|
|
|
cpu_init();
|
|
|
|
/*
|
|
* Ensure not to come back here if it wasn't intended
|
|
*/
|
|
PSPR = 0;
|
|
|
|
/*
|
|
* Ensure interrupt sources are disabled; we will re-init
|
|
* the interrupt subsystem via the device manager.
|
|
*/
|
|
ICLR = 0;
|
|
ICCR = 1;
|
|
ICMR = 0;
|
|
|
|
/* restore registers */
|
|
RESTORE(GPDR);
|
|
RESTORE(GAFR);
|
|
|
|
RESTORE(PPDR);
|
|
RESTORE(PPSR);
|
|
RESTORE(PPAR);
|
|
RESTORE(PSDR);
|
|
|
|
RESTORE(Ser1SDCR0);
|
|
|
|
GPSR = gpio;
|
|
GPCR = ~gpio;
|
|
|
|
/*
|
|
* Clear the peripheral sleep-hold bit.
|
|
*/
|
|
PSSR = PSSR_PH;
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned long sleep_phys_sp(void *sp)
|
|
{
|
|
return virt_to_phys(sp);
|
|
}
|
|
|
|
static struct platform_suspend_ops sa11x0_pm_ops = {
|
|
.enter = sa11x0_pm_enter,
|
|
.valid = suspend_valid_only_mem,
|
|
};
|
|
|
|
static int __init sa11x0_pm_init(void)
|
|
{
|
|
suspend_set_ops(&sa11x0_pm_ops);
|
|
return 0;
|
|
}
|
|
|
|
late_initcall(sa11x0_pm_init);
|