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/io.h>
  27#include <linux/suspend.h>
  28#include <linux/errno.h>
  29#include <linux/time.h>
  30
  31#include <mach/hardware.h>
  32#include <asm/memory.h>
  33#include <asm/suspend.h>
  34#include <asm/mach/time.h>
  35
  36extern int sa1100_finish_suspend(unsigned long);
  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(cpu_resume);
  77
  78        /* go zzz */
  79        cpu_suspend(0, sa1100_finish_suspend);
  80
  81        /*
  82         * Ensure not to come back here if it wasn't intended
  83         */
  84        PSPR = 0;
  85
  86        /*
  87         * Ensure interrupt sources are disabled; we will re-init
  88         * the interrupt subsystem via the device manager.
  89         */
  90        ICLR = 0;
  91        ICCR = 1;
  92        ICMR = 0;
  93
  94        /* restore registers */
  95        RESTORE(GPDR);
  96        RESTORE(GAFR);
  97
  98        RESTORE(PPDR);
  99        RESTORE(PPSR);
 100        RESTORE(PPAR);
 101        RESTORE(PSDR);
 102
 103        RESTORE(Ser1SDCR0);
 104
 105        GPSR = gpio;
 106        GPCR = ~gpio;
 107
 108        /*
 109         * Clear the peripheral sleep-hold bit.
 110         */
 111        PSSR = PSSR_PH;
 112
 113        return 0;
 114}
 115
 116static const struct platform_suspend_ops sa11x0_pm_ops = {
 117        .enter          = sa11x0_pm_enter,
 118        .valid          = suspend_valid_only_mem,
 119};
 120
 121int __init sa11x0_pm_init(void)
 122{
 123        suspend_set_ops(&sa11x0_pm_ops);
 124        return 0;
 125}
 126