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        p4d_t *p4dv;
  18        pud_t *pudv;
  19        pmd_t *pmdv;
  20        pte_t *ptev;
  21
  22        pgdv = (pgd_t *)__va((__nds32__mfsr(NDS32_SR_L1_PPTB) &
  23                L1_PPTB_mskBASE)) + pgd_index((unsigned int)cpu_resume);
  24
  25        p4dv = p4d_offset(pgdv, (unsigned int)cpu_resume);
  26        pudv = pud_offset(p4dv, (unsigned int)cpu_resume);
  27        pmdv = pmd_offset(pudv, (unsigned int)cpu_resume);
  28        ptev = pte_offset_map(pmdv, (unsigned int)cpu_resume);
  29
  30        resume_addr = ((*ptev) & TLB_DATA_mskPPN)
  31                        | ((unsigned int)cpu_resume & 0x00000fff);
  32
  33        suspend2ram();
  34}
  35
  36static void nds32_suspend_cpu(void)
  37{
  38        while (!(__nds32__mfsr(NDS32_SR_INT_PEND) & wake_mask))
  39                __asm__ volatile ("standby no_wake_grant\n\t");
  40}
  41
  42static int nds32_pm_valid(suspend_state_t state)
  43{
  44        switch (state) {
  45        case PM_SUSPEND_ON:
  46        case PM_SUSPEND_STANDBY:
  47        case PM_SUSPEND_MEM:
  48                return 1;
  49        default:
  50                return 0;
  51        }
  52}
  53
  54static int nds32_pm_enter(suspend_state_t state)
  55{
  56        pr_debug("%s:state:%d\n", __func__, state);
  57        switch (state) {
  58        case PM_SUSPEND_STANDBY:
  59                nds32_suspend_cpu();
  60                return 0;
  61        case PM_SUSPEND_MEM:
  62                nds32_suspend2ram();
  63                return 0;
  64        default:
  65                return -EINVAL;
  66        }
  67}
  68
  69static const struct platform_suspend_ops nds32_pm_ops = {
  70        .valid = nds32_pm_valid,
  71        .enter = nds32_pm_enter,
  72};
  73
  74static int __init nds32_pm_init(void)
  75{
  76        pr_debug("Enter %s\n", __func__);
  77        suspend_set_ops(&nds32_pm_ops);
  78        return 0;
  79}
  80late_initcall(nds32_pm_init);
  81