linux/arch/arm/mach-sa1100/pm.c
<<
>>
Prefs
   1/*
   2 * SA1100 Power Management Routines
   3 *
   4 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License.
   8 *
   9 * History:
  10 *
  11 * 2001-02-06:  Cliff Brake         Initial code
  12 *
  13 * 2001-02-25:  Sukjae Cho <sjcho@east.isi.edu> &
  14 *              Chester Kuo <chester@linux.org.tw>
  15 *                      Save more value for the resume function! Support
  16 *                      Bitsy/Assabet/Freebird board
  17 *
  18 * 2001-08-29:  Nicolas Pitre <nico@fluxnic.net>
  19 *                      Cleaned up, pushed platform dependent stuff
  20 *                      in the platform specific files.
  21 *
  22 * 2002-05-27:  Nicolas Pitre   Killed sleep.h and the kmalloced save array.
  23 *                              Storage is local on the stack now.
  24 */
  25#include <linux/init.h>
  26#include <linux/suspend.h>
  27#include <linux/errno.h>
  28#include <linux/time.h>
  29
  30#include <mach/hardware.h>
  31#include <asm/memory.h>
  32#include <asm/system.h>
  33#include <asm/mach/time.h>
  34
  35extern void sa1100_cpu_suspend(void);
  36extern void sa1100_cpu_resume(void);
  37
  38#define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
  39#define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
  40
  41/*
  42 * List of global SA11x0 peripheral registers to preserve.
  43 * More ones like CP and general purpose register values are preserved
  44 * on the stack and then the stack pointer is stored last in sleep.S.
  45 */
  46enum {  SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
  47        SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
  48
  49        SLEEP_SAVE_Ser1SDCR0,
  50
  51        SLEEP_SAVE_COUNT
  52};
  53
  54
  55static int sa11x0_pm_enter(suspend_state_t state)
  56{
  57        unsigned long gpio, sleep_save[SLEEP_SAVE_COUNT];
  58
  59        gpio = GPLR;
  60
  61        /* save vital registers */
  62        SAVE(GPDR);
  63        SAVE(GAFR);
  64
  65        SAVE(PPDR);
  66        SAVE(PPSR);
  67        SAVE(PPAR);
  68        SAVE(PSDR);
  69
  70        SAVE(Ser1SDCR0);
  71
  72        /* Clear previous reset status */
  73        RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
  74
  75        /* set resume return address */
  76        PSPR = virt_to_phys(sa1100_cpu_resume);
  77
  78        /* go zzz */
  79        sa1100_cpu_suspend();
  80
  81        cpu_init();
  82
  83        /*
  84         * Ensure not to come back here if it wasn't intended
  85         */
  86        PSPR = 0;
  87
  88        /*
  89         * Ensure interrupt sources are disabled; we will re-init
  90         * the interrupt subsystem via the device manager.
  91         */
  92        ICLR = 0;
  93        ICCR = 1;
  94        ICMR = 0;
  95
  96        /* restore registers */
  97        RESTORE(GPDR);
  98        RESTORE(GAFR);
  99
 100        RESTORE(PPDR);
 101        RESTORE(PPSR);
 102        RESTORE(PPAR);
 103        RESTORE(PSDR);
 104
 105        RESTORE(Ser1SDCR0);
 106
 107        GPSR = gpio;
 108        GPCR = ~gpio;
 109
 110        /*
 111         * Clear the peripheral sleep-hold bit.
 112         */
 113        PSSR = PSSR_PH;
 114
 115        return 0;
 116}
 117
 118unsigned long sleep_phys_sp(void *sp)
 119{
 120        return virt_to_phys(sp);
 121}
 122
 123static struct platform_suspend_ops sa11x0_pm_ops = {
 124        .enter          = sa11x0_pm_enter,
 125        .valid          = suspend_valid_only_mem,
 126};
 127
 128static int __init sa11x0_pm_init(void)
 129{
 130        suspend_set_ops(&sa11x0_pm_ops);
 131        return 0;
 132}
 133
 134late_initcall(sa11x0_pm_init);
 135