Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

authored by

Jiaxun Yang and committed by
Thomas Bogendoerfer
68557c59 2226d454

+38 -73
+1 -1
arch/mips/loongson64/Makefile
··· 8 8 obj-$(CONFIG_SMP) += smp.o 9 9 obj-$(CONFIG_NUMA) += numa.o 10 10 obj-$(CONFIG_RS780_HPET) += hpet.o 11 - obj-$(CONFIG_SUSPEND) += pm.o 11 + obj-$(CONFIG_SUSPEND) += pm.o sleeper.o 12 12 obj-$(CONFIG_PCI_QUIRKS) += vbios_quirk.o 13 13 obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o 14 14 obj-$(CONFIG_SYSFS) += boardinfo.o
+20 -72
arch/mips/loongson64/pm.c
··· 6 6 * Author: Wu Zhangjin <wuzhangjin@gmail.com> 7 7 */ 8 8 #include <linux/suspend.h> 9 - #include <linux/interrupt.h> 10 9 #include <linux/pm.h> 11 10 12 - #include <asm/i8259.h> 13 11 #include <asm/mipsregs.h> 14 12 15 13 #include <loongson.h> 16 14 17 - static unsigned int __maybe_unused cached_master_mask; /* i8259A */ 18 - static unsigned int __maybe_unused cached_slave_mask; 19 - static unsigned int __maybe_unused cached_bonito_irq_mask; /* bonito */ 15 + asmlinkage void loongson_lefi_sleep(unsigned long sleep_addr); 20 16 21 - void arch_suspend_disable_irqs(void) 22 - { 23 - /* disable all mips events */ 24 - local_irq_disable(); 25 - 26 - #ifdef CONFIG_I8259 27 - /* disable all events of i8259A */ 28 - cached_slave_mask = inb(PIC_SLAVE_IMR); 29 - cached_master_mask = inb(PIC_MASTER_IMR); 30 - 31 - outb(0xff, PIC_SLAVE_IMR); 32 - inb(PIC_SLAVE_IMR); 33 - outb(0xff, PIC_MASTER_IMR); 34 - inb(PIC_MASTER_IMR); 35 - #endif 36 - /* disable all events of bonito */ 37 - cached_bonito_irq_mask = LOONGSON_INTEN; 38 - LOONGSON_INTENCLR = 0xffff; 39 - (void)LOONGSON_INTENCLR; 40 - } 41 - 42 - void arch_suspend_enable_irqs(void) 43 - { 44 - /* enable all mips events */ 45 - local_irq_enable(); 46 - #ifdef CONFIG_I8259 47 - /* only enable the cached events of i8259A */ 48 - outb(cached_slave_mask, PIC_SLAVE_IMR); 49 - outb(cached_master_mask, PIC_MASTER_IMR); 50 - #endif 51 - /* enable all cached events of bonito */ 52 - LOONGSON_INTENSET = cached_bonito_irq_mask; 53 - (void)LOONGSON_INTENSET; 54 - } 55 - 56 - /* 57 - * Setup the board-specific events for waking up loongson from wait mode 58 - */ 59 - void __weak setup_wakeup_events(void) 60 - { 61 - } 62 - 63 - void __weak mach_suspend(void) 64 - { 65 - } 66 - 67 - void __weak mach_resume(void) 68 - { 69 - } 70 - 71 - static int loongson_pm_enter(suspend_state_t state) 72 - { 73 - mach_suspend(); 74 - 75 - mach_resume(); 76 - 77 - return 0; 78 - } 79 - 80 - static int loongson_pm_valid_state(suspend_state_t state) 17 + static int lefi_pm_enter(suspend_state_t state) 81 18 { 82 19 switch (state) { 83 - case PM_SUSPEND_ON: 84 - case PM_SUSPEND_STANDBY: 85 20 case PM_SUSPEND_MEM: 86 - return 1; 21 + pm_set_suspend_via_firmware(); 22 + loongson_lefi_sleep(loongson_sysconf.suspend_addr); 23 + pm_set_resume_via_firmware(); 24 + return 0; 25 + default: 26 + return -EINVAL; 27 + } 28 + } 87 29 30 + static int lefi_pm_valid_state(suspend_state_t state) 31 + { 32 + switch (state) { 33 + case PM_SUSPEND_MEM: 34 + return !!loongson_sysconf.suspend_addr; 88 35 default: 89 36 return 0; 90 37 } 91 38 } 92 39 93 - static const struct platform_suspend_ops loongson_pm_ops = { 94 - .valid = loongson_pm_valid_state, 95 - .enter = loongson_pm_enter, 40 + static const struct platform_suspend_ops lefi_pm_ops = { 41 + .valid = lefi_pm_valid_state, 42 + .enter = lefi_pm_enter, 96 43 }; 97 44 98 45 static int __init loongson_pm_init(void) 99 46 { 100 - suspend_set_ops(&loongson_pm_ops); 47 + if (loongson_sysconf.fw_interface == LOONGSON_LEFI) 48 + suspend_set_ops(&lefi_pm_ops); 101 49 102 50 return 0; 103 51 }
+17
arch/mips/loongson64/sleeper.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright (C) 2024, Jiaxun Yang <jiaxun.yang@flygoat.com> 4 + * Loongson EFI firmware sleeper routine 5 + */ 6 + 7 + #include <asm/asm.h> 8 + #include <asm/pm.h> 9 + 10 + #include <kernel-entry-init.h> 11 + 12 + LEAF(loongson_lefi_sleep) 13 + SUSPEND_SAVE 14 + jalr a0 15 + smp_slave_setup 16 + RESUME_RESTORE_REGS_RETURN 17 + END(loongson_lefi_sleep)