xref: /openbmc/linux/arch/mips/loongson64/pm.c (revision c95baf12f5077419db01313ab61c2aac007d40cd)
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 Yang void 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 Yang void 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 Yang void __weak setup_wakeup_events(void)
60*6fbde6b4SJiaxun Yang {
61*6fbde6b4SJiaxun Yang }
62*6fbde6b4SJiaxun Yang 
mach_suspend(void)63*6fbde6b4SJiaxun Yang void __weak mach_suspend(void)
64*6fbde6b4SJiaxun Yang {
65*6fbde6b4SJiaxun Yang }
66*6fbde6b4SJiaxun Yang 
mach_resume(void)67*6fbde6b4SJiaxun Yang void __weak mach_resume(void)
68*6fbde6b4SJiaxun Yang {
69*6fbde6b4SJiaxun Yang }
70*6fbde6b4SJiaxun Yang 
loongson_pm_enter(suspend_state_t state)71*6fbde6b4SJiaxun Yang static 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 Yang static 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 Yang static 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