Commit 68557c59 authored by Jiaxun Yang's avatar Jiaxun Yang Committed by Thomas Bogendoerfer

MIPS: Loongson64: Implement PM suspend for LEFI firmware

Implement PM suspend for LEFI firmware.
Entering STR (Suspend to RAM) is as simple as save our context
then go to a firmware vector.
Wake is a little bit treaky as we need to setup some CP0 status
first, which can be done with smp_slave_setup.
Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
parent 2226d454
...@@ -8,7 +8,7 @@ obj-$(CONFIG_MACH_LOONGSON64) += cop2-ex.o dma.o \ ...@@ -8,7 +8,7 @@ obj-$(CONFIG_MACH_LOONGSON64) += cop2-ex.o dma.o \
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_NUMA) += numa.o
obj-$(CONFIG_RS780_HPET) += hpet.o obj-$(CONFIG_RS780_HPET) += hpet.o
obj-$(CONFIG_SUSPEND) += pm.o obj-$(CONFIG_SUSPEND) += pm.o sleeper.o
obj-$(CONFIG_PCI_QUIRKS) += vbios_quirk.o obj-$(CONFIG_PCI_QUIRKS) += vbios_quirk.o
obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o
obj-$(CONFIG_SYSFS) += boardinfo.o obj-$(CONFIG_SYSFS) += boardinfo.o
...@@ -6,98 +6,46 @@ ...@@ -6,98 +6,46 @@
* Author: Wu Zhangjin <wuzhangjin@gmail.com> * Author: Wu Zhangjin <wuzhangjin@gmail.com>
*/ */
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/interrupt.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <asm/i8259.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
#include <loongson.h> #include <loongson.h>
static unsigned int __maybe_unused cached_master_mask; /* i8259A */ asmlinkage void loongson_lefi_sleep(unsigned long sleep_addr);
static unsigned int __maybe_unused cached_slave_mask;
static unsigned int __maybe_unused cached_bonito_irq_mask; /* bonito */
void arch_suspend_disable_irqs(void) static int lefi_pm_enter(suspend_state_t state)
{ {
/* disable all mips events */ switch (state) {
local_irq_disable(); case PM_SUSPEND_MEM:
pm_set_suspend_via_firmware();
#ifdef CONFIG_I8259 loongson_lefi_sleep(loongson_sysconf.suspend_addr);
/* disable all events of i8259A */ pm_set_resume_via_firmware();
cached_slave_mask = inb(PIC_SLAVE_IMR); return 0;
cached_master_mask = inb(PIC_MASTER_IMR); default:
return -EINVAL;
outb(0xff, PIC_SLAVE_IMR); }
inb(PIC_SLAVE_IMR);
outb(0xff, PIC_MASTER_IMR);
inb(PIC_MASTER_IMR);
#endif
/* disable all events of bonito */
cached_bonito_irq_mask = LOONGSON_INTEN;
LOONGSON_INTENCLR = 0xffff;
(void)LOONGSON_INTENCLR;
}
void arch_suspend_enable_irqs(void)
{
/* enable all mips events */
local_irq_enable();
#ifdef CONFIG_I8259
/* only enable the cached events of i8259A */
outb(cached_slave_mask, PIC_SLAVE_IMR);
outb(cached_master_mask, PIC_MASTER_IMR);
#endif
/* enable all cached events of bonito */
LOONGSON_INTENSET = cached_bonito_irq_mask;
(void)LOONGSON_INTENSET;
}
/*
* Setup the board-specific events for waking up loongson from wait mode
*/
void __weak setup_wakeup_events(void)
{
}
void __weak mach_suspend(void)
{
}
void __weak mach_resume(void)
{
}
static int loongson_pm_enter(suspend_state_t state)
{
mach_suspend();
mach_resume();
return 0;
} }
static int loongson_pm_valid_state(suspend_state_t state) static int lefi_pm_valid_state(suspend_state_t state)
{ {
switch (state) { switch (state) {
case PM_SUSPEND_ON:
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM: case PM_SUSPEND_MEM:
return 1; return !!loongson_sysconf.suspend_addr;
default: default:
return 0; return 0;
} }
} }
static const struct platform_suspend_ops loongson_pm_ops = { static const struct platform_suspend_ops lefi_pm_ops = {
.valid = loongson_pm_valid_state, .valid = lefi_pm_valid_state,
.enter = loongson_pm_enter, .enter = lefi_pm_enter,
}; };
static int __init loongson_pm_init(void) static int __init loongson_pm_init(void)
{ {
suspend_set_ops(&loongson_pm_ops); if (loongson_sysconf.fw_interface == LOONGSON_LEFI)
suspend_set_ops(&lefi_pm_ops);
return 0; return 0;
} }
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2024, Jiaxun Yang <jiaxun.yang@flygoat.com>
* Loongson EFI firmware sleeper routine
*/
#include <asm/asm.h>
#include <asm/pm.h>
#include <kernel-entry-init.h>
LEAF(loongson_lefi_sleep)
SUSPEND_SAVE
jalr a0
smp_slave_setup
RESUME_RESTORE_REGS_RETURN
END(loongson_lefi_sleep)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment