linux/arch/nds32/kernel/pm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2008-2017 Andes Technology Corporation
   3
   4#include <linux/init.h>
   5#include <linux/suspend.h>
   6#include <linux/device.h>
   7#include <linux/printk.h>
   8#include <asm/suspend.h>
   9#include <nds32_intrinsic.h>
  10
  11unsigned int resume_addr;
  12unsigned int *phy_addr_sp_tmp;
  13
  14static void nds32_suspend2ram(void)
  15{
  16        pgd_t *pgdv;
  17        pud_t *pudv;
  18        pmd_t *pmdv;
  19        pte_t *ptev;
  20
  21        pgdv = (pgd_t *)__va((__nds32__mfsr(NDS32_SR_L1_PPTB) &
  22                L1_PPTB_mskBASE)) + pgd_index((unsigned int)cpu_resume);
  23
  24        pudv = pud_offset(pgdv, (unsigned int)cpu_resume);
  25        pmdv = pmd_offset(pudv, (unsigned int)cpu_resume);
  26        ptev = pte_offset_map(pmdv, (unsigned int)cpu_resume);
  27
  28        resume_addr = ((*ptev) & TLB_DATA_mskPPN)
  29                        | ((unsigned int)cpu_resume & 0x00000fff);
  30
  31        suspend2ram();
  32}
  33
  34static void nds32_suspend_cpu(void)
  35{
  36        while (!(__nds32__mfsr(NDS32_SR_INT_PEND) & wake_mask))
  37                __asm__ volatile ("standby no_wake_grant\n\t");
  38}
  39
  40static int nds32_pm_valid(suspend_state_t state)
  41{
  42        switch (state) {
  43        case PM_SUSPEND_ON:
  44        case PM_SUSPEND_STANDBY:
  45        case PM_SUSPEND_MEM:
  46                return 1;
  47        default:
  48                return 0;
  49        }
  50}
  51
  52static int nds32_pm_enter(suspend_state_t state)
  53{
  54        pr_debug("%s:state:%d\n", __func__, state);
  55        switch (state) {
  56        case PM_SUSPEND_STANDBY:
  57                nds32_suspend_cpu();
  58                return 0;
  59        case PM_SUSPEND_MEM:
  60                nds32_suspend2ram();
  61                return 0;
  62        default:
  63                return -EINVAL;
  64        }
  65}
  66
  67static const struct platform_suspend_ops nds32_pm_ops = {
  68        .valid = nds32_pm_valid,
  69        .enter = nds32_pm_enter,
  70};
  71
  72static int __init nds32_pm_init(void)
  73{
  74        pr_debug("Enter %s\n", __func__);
  75        suspend_set_ops(&nds32_pm_ops);
  76        return 0;
  77}
  78late_initcall(nds32_pm_init);
  79