1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * loongson-specific suspend support 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2009 Lemote Inc. 6*4882a593Smuzhiyun * Author: Wu Zhangjin <wuzhangjin@gmail.com> 7*4882a593Smuzhiyun */ 8*4882a593Smuzhiyun #include <linux/suspend.h> 9*4882a593Smuzhiyun #include <linux/interrupt.h> 10*4882a593Smuzhiyun #include <linux/pm.h> 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #include <asm/i8259.h> 13*4882a593Smuzhiyun #include <asm/mipsregs.h> 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun #include <loongson.h> 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun static unsigned int __maybe_unused cached_master_mask; /* i8259A */ 18*4882a593Smuzhiyun static unsigned int __maybe_unused cached_slave_mask; 19*4882a593Smuzhiyun static unsigned int __maybe_unused cached_bonito_irq_mask; /* bonito */ 20*4882a593Smuzhiyun arch_suspend_disable_irqs(void)21*4882a593Smuzhiyunvoid arch_suspend_disable_irqs(void) 22*4882a593Smuzhiyun { 23*4882a593Smuzhiyun /* disable all mips events */ 24*4882a593Smuzhiyun local_irq_disable(); 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun #ifdef CONFIG_I8259 27*4882a593Smuzhiyun /* disable all events of i8259A */ 28*4882a593Smuzhiyun cached_slave_mask = inb(PIC_SLAVE_IMR); 29*4882a593Smuzhiyun cached_master_mask = inb(PIC_MASTER_IMR); 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun outb(0xff, PIC_SLAVE_IMR); 32*4882a593Smuzhiyun inb(PIC_SLAVE_IMR); 33*4882a593Smuzhiyun outb(0xff, PIC_MASTER_IMR); 34*4882a593Smuzhiyun inb(PIC_MASTER_IMR); 35*4882a593Smuzhiyun #endif 36*4882a593Smuzhiyun /* disable all events of bonito */ 37*4882a593Smuzhiyun cached_bonito_irq_mask = LOONGSON_INTEN; 38*4882a593Smuzhiyun LOONGSON_INTENCLR = 0xffff; 39*4882a593Smuzhiyun (void)LOONGSON_INTENCLR; 40*4882a593Smuzhiyun } 41*4882a593Smuzhiyun arch_suspend_enable_irqs(void)42*4882a593Smuzhiyunvoid arch_suspend_enable_irqs(void) 43*4882a593Smuzhiyun { 44*4882a593Smuzhiyun /* enable all mips events */ 45*4882a593Smuzhiyun local_irq_enable(); 46*4882a593Smuzhiyun #ifdef CONFIG_I8259 47*4882a593Smuzhiyun /* only enable the cached events of i8259A */ 48*4882a593Smuzhiyun outb(cached_slave_mask, PIC_SLAVE_IMR); 49*4882a593Smuzhiyun outb(cached_master_mask, PIC_MASTER_IMR); 50*4882a593Smuzhiyun #endif 51*4882a593Smuzhiyun /* enable all cached events of bonito */ 52*4882a593Smuzhiyun LOONGSON_INTENSET = cached_bonito_irq_mask; 53*4882a593Smuzhiyun (void)LOONGSON_INTENSET; 54*4882a593Smuzhiyun } 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun /* 57*4882a593Smuzhiyun * Setup the board-specific events for waking up loongson from wait mode 58*4882a593Smuzhiyun */ setup_wakeup_events(void)59*4882a593Smuzhiyunvoid __weak setup_wakeup_events(void) 60*4882a593Smuzhiyun { 61*4882a593Smuzhiyun } 62*4882a593Smuzhiyun mach_suspend(void)63*4882a593Smuzhiyunvoid __weak mach_suspend(void) 64*4882a593Smuzhiyun { 65*4882a593Smuzhiyun } 66*4882a593Smuzhiyun mach_resume(void)67*4882a593Smuzhiyunvoid __weak mach_resume(void) 68*4882a593Smuzhiyun { 69*4882a593Smuzhiyun } 70*4882a593Smuzhiyun loongson_pm_enter(suspend_state_t state)71*4882a593Smuzhiyunstatic int loongson_pm_enter(suspend_state_t state) 72*4882a593Smuzhiyun { 73*4882a593Smuzhiyun mach_suspend(); 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun mach_resume(); 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun return 0; 78*4882a593Smuzhiyun } 79*4882a593Smuzhiyun loongson_pm_valid_state(suspend_state_t state)80*4882a593Smuzhiyunstatic int loongson_pm_valid_state(suspend_state_t state) 81*4882a593Smuzhiyun { 82*4882a593Smuzhiyun switch (state) { 83*4882a593Smuzhiyun case PM_SUSPEND_ON: 84*4882a593Smuzhiyun case PM_SUSPEND_STANDBY: 85*4882a593Smuzhiyun case PM_SUSPEND_MEM: 86*4882a593Smuzhiyun return 1; 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun default: 89*4882a593Smuzhiyun return 0; 90*4882a593Smuzhiyun } 91*4882a593Smuzhiyun } 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun static const struct platform_suspend_ops loongson_pm_ops = { 94*4882a593Smuzhiyun .valid = loongson_pm_valid_state, 95*4882a593Smuzhiyun .enter = loongson_pm_enter, 96*4882a593Smuzhiyun }; 97*4882a593Smuzhiyun loongson_pm_init(void)98*4882a593Smuzhiyunstatic int __init loongson_pm_init(void) 99*4882a593Smuzhiyun { 100*4882a593Smuzhiyun suspend_set_ops(&loongson_pm_ops); 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun return 0; 103*4882a593Smuzhiyun } 104*4882a593Smuzhiyun arch_initcall(loongson_pm_init); 105