cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pm.c (2648B)


      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}