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 (4263B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Copyright 2008 Openmoko, Inc.
      4// Copyright 2004-2008 Simtec Electronics
      5//	Ben Dooks <ben@simtec.co.uk>
      6//	http://armlinux.simtec.co.uk/
      7//
      8// S3C common power management (suspend to ram) support.
      9
     10#include <linux/init.h>
     11#include <linux/suspend.h>
     12#include <linux/errno.h>
     13#include <linux/delay.h>
     14#include <linux/of.h>
     15#include <linux/serial_s3c.h>
     16#include <linux/io.h>
     17
     18#include <asm/cacheflush.h>
     19#include <asm/suspend.h>
     20
     21#include "map.h"
     22#include "regs-clock.h"
     23#include "regs-irq.h"
     24#include "irqs.h"
     25
     26#include <asm/irq.h>
     27
     28#include "cpu.h"
     29#include "pm.h"
     30#include "pm-core.h"
     31
     32/* for external use */
     33
     34unsigned long s3c_pm_flags;
     35
     36/* The IRQ ext-int code goes here, it is too small to currently bother
     37 * with its own file. */
     38
     39unsigned long s3c_irqwake_intmask	= 0xffffffffL;
     40unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
     41
     42int s3c_irqext_wake(struct irq_data *data, unsigned int state)
     43{
     44	unsigned long bit = 1L << IRQ_EINT_BIT(data->irq);
     45
     46	if (!(s3c_irqwake_eintallow & bit))
     47		return -ENOENT;
     48
     49	printk(KERN_INFO "wake %s for irq %d\n",
     50	       state ? "enabled" : "disabled", data->irq);
     51
     52	if (!state)
     53		s3c_irqwake_eintmask |= bit;
     54	else
     55		s3c_irqwake_eintmask &= ~bit;
     56
     57	return 0;
     58}
     59
     60void (*pm_cpu_prep)(void);
     61int (*pm_cpu_sleep)(unsigned long);
     62
     63#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
     64
     65/* s3c_pm_enter
     66 *
     67 * central control for sleep/resume process
     68*/
     69
     70static int s3c_pm_enter(suspend_state_t state)
     71{
     72	int ret;
     73	/* ensure the debug is initialised (if enabled) */
     74	s3c_pm_debug_init_uart();
     75
     76	S3C_PMDBG("%s(%d)\n", __func__, state);
     77
     78	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
     79		printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
     80		return -EINVAL;
     81	}
     82
     83	/* check if we have anything to wake-up with... bad things seem
     84	 * to happen if you suspend with no wakeup (system will often
     85	 * require a full power-cycle)
     86	*/
     87
     88	if (!of_have_populated_dt() &&
     89	    !any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
     90	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
     91		printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
     92		printk(KERN_ERR "%s: Aborting sleep\n", __func__);
     93		return -EINVAL;
     94	}
     95
     96	/* save all necessary core registers not covered by the drivers */
     97
     98	if (!of_have_populated_dt()) {
     99		samsung_pm_save_gpios();
    100		samsung_pm_saved_gpios();
    101	}
    102
    103	s3c_pm_save_uarts(soc_is_s3c2410());
    104	s3c_pm_save_core();
    105
    106	/* set the irq configuration for wake */
    107
    108	s3c_pm_configure_extint();
    109
    110	S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
    111	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
    112
    113	s3c_pm_arch_prepare_irqs();
    114
    115	/* call cpu specific preparation */
    116
    117	pm_cpu_prep();
    118
    119	/* flush cache back to ram */
    120
    121	flush_cache_all();
    122
    123	s3c_pm_check_store();
    124
    125	/* send the cpu to sleep... */
    126
    127	s3c_pm_arch_stop_clocks();
    128
    129	/* this will also act as our return point from when
    130	 * we resume as it saves its own register state and restores it
    131	 * during the resume.  */
    132
    133	ret = cpu_suspend(0, pm_cpu_sleep);
    134	if (ret)
    135		return ret;
    136
    137	/* restore the system state */
    138
    139	s3c_pm_restore_core();
    140	s3c_pm_restore_uarts(soc_is_s3c2410());
    141
    142	if (!of_have_populated_dt()) {
    143		samsung_pm_restore_gpios();
    144		s3c_pm_restored_gpios();
    145	}
    146
    147	s3c_pm_debug_init_uart();
    148
    149	/* check what irq (if any) restored the system */
    150
    151	s3c_pm_arch_show_resume_irqs();
    152
    153	S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
    154
    155	/* LEDs should now be 1110 */
    156	s3c_pm_debug_smdkled(1 << 1, 0);
    157
    158	s3c_pm_check_restore();
    159
    160	/* ok, let's return from sleep */
    161
    162	S3C_PMDBG("S3C PM Resume (post-restore)\n");
    163	return 0;
    164}
    165
    166static int s3c_pm_prepare(void)
    167{
    168	/* prepare check area if configured */
    169
    170	s3c_pm_check_prepare();
    171	return 0;
    172}
    173
    174static void s3c_pm_finish(void)
    175{
    176	s3c_pm_check_cleanup();
    177}
    178
    179static const struct platform_suspend_ops s3c_pm_ops = {
    180	.enter		= s3c_pm_enter,
    181	.prepare	= s3c_pm_prepare,
    182	.finish		= s3c_pm_finish,
    183	.valid		= suspend_valid_only_mem,
    184};
    185
    186/* s3c_pm_init
    187 *
    188 * Attach the power management functions. This should be called
    189 * from the board specific initialisation if the board supports
    190 * it.
    191*/
    192
    193int __init s3c_pm_init(void)
    194{
    195	printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
    196
    197	suspend_set_ops(&s3c_pm_ops);
    198	return 0;
    199}