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