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(long);
  36
  37#define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
  38#define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
  39
  40/*
  41 * List of global SA11x0 peripheral registers to preserve.
  42 * More ones like CP and general purpose register values are preserved
  43 * on the stack and then the stack pointer is stored last in sleep.S.
  44 */
  45enum {  SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
  46        SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
  47
  48        SLEEP_SAVE_Ser1SDCR0,
  49
  50        SLEEP_SAVE_COUNT
  51};
  52
  53
  54static int sa11x0_pm_enter(suspend_state_t state)
  55{
  56        unsigned long gpio, sleep_save[SLEEP_SAVE_COUNT];
  57
  58        gpio = GPLR;
  59
  60        /* save vital registers */
  61        SAVE(GPDR);
  62        SAVE(GAFR);
  63
  64        SAVE(PPDR);
  65        SAVE(PPSR);
  66        SAVE(PPAR);
  67        SAVE(PSDR);
  68
  69        SAVE(Ser1SDCR0);
  70
  71        /* Clear previous reset status */
  72        RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
  73
  74        /* set resume return address */
  75        PSPR = virt_to_phys(cpu_resume);
  76
  77        /* go zzz */
  78        sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
  79
  80        cpu_init();
  81
  82        /*
  83         * Ensure not to come back here if it wasn't intended
  84         */
  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
 122static int __init sa11x0_pm_init(void)
 123{
 124        suspend_set_ops(&sa11x0_pm_ops);
 125        return 0;
 126}
 127
 128late_initcall(sa11x0_pm_init);
 129