hc
2023-02-13 e440ec23c5a540cdd3f7464e8779219be6fd3d95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * Copyright (C) 2014 Imagination Technologies Ltd.
 *
 * This program is free software; you can redistribute    it and/or modify it
 * under  the terms of    the GNU General     Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 *
 * CPU PM notifiers for saving/restoring general CPU state.
 */
 
#include <linux/cpu_pm.h>
#include <linux/init.h>
 
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/mmu_context.h>
#include <asm/pm.h>
#include <asm/watch.h>
 
/* Used by PM helper macros in asm/pm.h */
struct mips_static_suspend_state mips_static_suspend_state;
 
/**
 * mips_cpu_save() - Save general CPU state.
 * Ensures that general CPU context is saved, notably FPU and DSP.
 */
static int mips_cpu_save(void)
{
   /* Save FPU state */
   lose_fpu(1);
 
   /* Save DSP state */
   save_dsp(current);
 
   return 0;
}
 
/**
 * mips_cpu_restore() - Restore general CPU state.
 * Restores important CPU context.
 */
static void mips_cpu_restore(void)
{
   unsigned int cpu = smp_processor_id();
 
   /* Restore ASID */
   if (current->mm)
       write_c0_entryhi(cpu_asid(cpu, current->mm));
 
   /* Restore DSP state */
   restore_dsp(current);
 
   /* Restore UserLocal */
   if (cpu_has_userlocal)
       write_c0_userlocal(current_thread_info()->tp_value);
 
   /* Restore watch registers */
   __restore_watch(current);
}
 
/**
 * mips_pm_notifier() - Notifier for preserving general CPU context.
 * @self:    Notifier block.
 * @cmd:    CPU PM event.
 * @v:        Private data (unused).
 *
 * This is called when a CPU power management event occurs, and is used to
 * ensure that important CPU context is preserved across a CPU power down.
 */
static int mips_pm_notifier(struct notifier_block *self, unsigned long cmd,
               void *v)
{
   int ret;
 
   switch (cmd) {
   case CPU_PM_ENTER:
       ret = mips_cpu_save();
       if (ret)
           return NOTIFY_STOP;
       break;
   case CPU_PM_ENTER_FAILED:
   case CPU_PM_EXIT:
       mips_cpu_restore();
       break;
   }
 
   return NOTIFY_OK;
}
 
static struct notifier_block mips_pm_notifier_block = {
   .notifier_call = mips_pm_notifier,
};
 
static int __init mips_pm_init(void)
{
   return cpu_pm_register_notifier(&mips_pm_notifier_block);
}
arch_initcall(mips_pm_init);