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