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 11 unsigned int resume_addr; 12 unsigned int *phy_addr_sp_tmp; 13 nds32_suspend2ram(void)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 nds32_suspend_cpu(void)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 nds32_pm_valid(suspend_state_t state)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 nds32_pm_enter(suspend_state_t state)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 67 static const struct platform_suspend_ops nds32_pm_ops = { 68 .valid = nds32_pm_valid, 69 .enter = nds32_pm_enter, 70 }; 71 nds32_pm_init(void)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 } 78 late_initcall(nds32_pm_init); 79