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