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 = __pa_symbol(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        RCSR = RCSR_SMR;
  85        PSPR = 0;
  86
  87        /*
  88         * Ensure interrupt sources are disabled; we will re-init
  89         * the interrupt subsystem via the device manager.
  90         */
  91        ICLR = 0;
  92        ICCR = 1;
  93        ICMR = 0;
  94
  95        /* restore registers */
  96        RESTORE(GPDR);
  97        RESTORE(GAFR);
  98
  99        RESTORE(PPDR);
 100        RESTORE(PPSR);
 101        RESTORE(PPAR);
 102        RESTORE(PSDR);
 103
 104        RESTORE(Ser1SDCR0);
 105
 106        GPSR = gpio;
 107        GPCR = ~gpio;
 108
 109        /*
 110         * Clear the peripheral sleep-hold bit.
 111         */
 112        PSSR = PSSR_PH;
 113
 114        return 0;
 115}
 116
 117static const struct platform_suspend_ops sa11x0_pm_ops = {
 118        .enter          = sa11x0_pm_enter,
 119        .valid          = suspend_valid_only_mem,
 120};
 121
 122int __init sa11x0_pm_init(void)
 123{
 124        suspend_set_ops(&sa11x0_pm_ops);
 125        return 0;
 126}
 127