2024-05-07 15:22:20

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH 0/3] MIPS: Loongson64: Implement PM suspend for LEFI firmware

Hi all,

This series implemented PM suspend for LEFI firmware.
We missed this for long in upstream kernel...

Please review
Thanks

Signed-off-by: Jiaxun Yang <[email protected]>
---
Jiaxun Yang (3):
MIPS: asm/pm.h: Use platform agnostic macros
MIPS: select CPU_PM with SUSPEND
MIPS: Loongson64: Implement PM suspend for LEFI firmware

arch/mips/Kconfig | 2 +-
arch/mips/include/asm/pm.h | 22 +++++------
arch/mips/loongson64/Makefile | 2 +-
arch/mips/loongson64/pm.c | 88 +++++++++---------------------------------
arch/mips/loongson64/sleeper.S | 17 ++++++++
5 files changed, 48 insertions(+), 83 deletions(-)
---
base-commit: 93a39e4766083050ca0ecd6a3548093a3b9eb60c
change-id: 20240507-loongson64-suspend-7535521cd01e

Best regards,
--
Jiaxun Yang <[email protected]>



2024-05-07 15:22:31

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH 1/3] MIPS: asm/pm.h: Use platform agnostic macros

Use platform agnostic macros so it can be compiled on all
MIPS platforms.

Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/include/asm/pm.h | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/mips/include/asm/pm.h b/arch/mips/include/asm/pm.h
index 10bb7b640738..7ecd4dfe3846 100644
--- a/arch/mips/include/asm/pm.h
+++ b/arch/mips/include/asm/pm.h
@@ -17,7 +17,7 @@

/* Save CPU state to stack for suspend to RAM */
.macro SUSPEND_SAVE_REGS
- subu sp, PT_SIZE
+ PTR_SUBU sp, PT_SIZE
/* Call preserved GPRs */
LONG_S $16, PT_R16(sp)
LONG_S $17, PT_R17(sp)
@@ -56,13 +56,13 @@
LONG_L $31, PT_R31(sp)
/* Pop and return */
jr ra
- addiu sp, PT_SIZE
+ PTR_ADDIU sp, PT_SIZE
.set pop
.endm

/* Get address of static suspend state into t1 */
.macro LA_STATIC_SUSPEND
- la t1, mips_static_suspend_state
+ PTR_LA t1, mips_static_suspend_state
.endm

/* Save important CPU state for early restoration to global data */
@@ -72,11 +72,11 @@
* Segment configuration is saved in global data where it can be easily
* reloaded without depending on the segment configuration.
*/
- mfc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
+ mfc0 k0, CP0_SEGCTL0
LONG_S k0, SSS_SEGCTL0(t1)
- mfc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
+ mfc0 k0, CP0_SEGCTL1
LONG_S k0, SSS_SEGCTL1(t1)
- mfc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
+ mfc0 k0, CP0_SEGCTL2
LONG_S k0, SSS_SEGCTL2(t1)
#endif
/* save stack pointer (pointing to GPRs) */
@@ -92,11 +92,11 @@
* segments.
*/
LONG_L k0, SSS_SEGCTL0(t1)
- mtc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */
+ mtc0 k0, CP0_SEGCTL0
LONG_L k0, SSS_SEGCTL1(t1)
- mtc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */
+ mtc0 k0, CP0_SEGCTL1
LONG_L k0, SSS_SEGCTL2(t1)
- mtc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */
+ mtc0 k0, CP0_SEGCTL2
tlbw_use_hazard
#endif
/* restore stack pointer (pointing to GPRs) */
@@ -105,10 +105,10 @@

/* flush caches to make sure context has reached memory */
.macro SUSPEND_CACHE_FLUSH
- .extern __wback_cache_all
+ .extern __flush_cache_all
.set push
.set noreorder
- la t1, __wback_cache_all
+ PTR_LA t1, __flush_cache_all
LONG_L t0, 0(t1)
jalr t0
nop

--
2.34.1


2024-05-07 15:22:41

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH 2/3] MIPS: select CPU_PM with SUSPEND

Functionalities provided by CPU_PM are essential for suspend
to work on all platforms.

Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f1aa1bf11166..c5753cb0953d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -30,7 +30,7 @@ config MIPS
select BUILDTIME_TABLE_SORT
select CLONE_BACKWARDS
select CPU_NO_EFFICIENT_FFS if (TARGET_ISA_REV < 1)
- select CPU_PM if CPU_IDLE
+ select CPU_PM if CPU_IDLE || SUSPEND
select GENERIC_ATOMIC64 if !64BIT
select GENERIC_CMOS_UPDATE
select GENERIC_CPU_AUTOPROBE

--
2.34.1


2024-05-07 15:23:00

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH 3/3] 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 <[email protected]>
---
arch/mips/loongson64/Makefile | 2 +-
arch/mips/loongson64/pm.c | 88 +++++++++---------------------------------
arch/mips/loongson64/sleeper.S | 17 ++++++++
3 files changed, 36 insertions(+), 71 deletions(-)

diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
index e806280bbb85..cbba30dfddf5 100644
--- a/arch/mips/loongson64/Makefile
+++ b/arch/mips/loongson64/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_MACH_LOONGSON64) += cop2-ex.o dma.o \
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_NUMA) += numa.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_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o
obj-$(CONFIG_SYSFS) += boardinfo.o
diff --git a/arch/mips/loongson64/pm.c b/arch/mips/loongson64/pm.c
index 7c8556f09781..5f0604af8f13 100644
--- a/arch/mips/loongson64/pm.c
+++ b/arch/mips/loongson64/pm.c
@@ -6,98 +6,46 @@
* Author: Wu Zhangjin <[email protected]>
*/
#include <linux/suspend.h>
-#include <linux/interrupt.h>
#include <linux/pm.h>

-#include <asm/i8259.h>
#include <asm/mipsregs.h>

#include <loongson.h>

-static unsigned int __maybe_unused cached_master_mask; /* i8259A */
-static unsigned int __maybe_unused cached_slave_mask;
-static unsigned int __maybe_unused cached_bonito_irq_mask; /* bonito */
+asmlinkage void loongson_lefi_sleep(unsigned long sleep_addr);

-void arch_suspend_disable_irqs(void)
+static int lefi_pm_enter(suspend_state_t state)
{
- /* disable all mips events */
- local_irq_disable();
-
-#ifdef CONFIG_I8259
- /* disable all events of i8259A */
- cached_slave_mask = inb(PIC_SLAVE_IMR);
- cached_master_mask = inb(PIC_MASTER_IMR);
-
- 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;
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ pm_set_suspend_via_firmware();
+ loongson_lefi_sleep(loongson_sysconf.suspend_addr);
+ pm_set_resume_via_firmware();
+ return 0;
+ default:
+ return -EINVAL;
+ }
}

-static int loongson_pm_valid_state(suspend_state_t state)
+static int lefi_pm_valid_state(suspend_state_t state)
{
switch (state) {
- case PM_SUSPEND_ON:
- case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
- return 1;
-
+ return !!loongson_sysconf.suspend_addr;
default:
return 0;
}
}

-static const struct platform_suspend_ops loongson_pm_ops = {
- .valid = loongson_pm_valid_state,
- .enter = loongson_pm_enter,
+static const struct platform_suspend_ops lefi_pm_ops = {
+ .valid = lefi_pm_valid_state,
+ .enter = lefi_pm_enter,
};

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;
}
diff --git a/arch/mips/loongson64/sleeper.S b/arch/mips/loongson64/sleeper.S
new file mode 100644
index 000000000000..04874b9bf430
--- /dev/null
+++ b/arch/mips/loongson64/sleeper.S
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2024, Jiaxun Yang <[email protected]>
+ * 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)

--
2.34.1


2024-06-11 12:22:30

by Thomas Bogendoerfer

[permalink] [raw]
Subject: Re: [PATCH 0/3] MIPS: Loongson64: Implement PM suspend for LEFI firmware

On Tue, May 07, 2024 at 04:21:58PM +0100, Jiaxun Yang wrote:
> Hi all,
>
> This series implemented PM suspend for LEFI firmware.
> We missed this for long in upstream kernel...
>
> Please review
> Thanks
>
> Signed-off-by: Jiaxun Yang <[email protected]>
> ---
> Jiaxun Yang (3):
> MIPS: asm/pm.h: Use platform agnostic macros
> MIPS: select CPU_PM with SUSPEND
> MIPS: Loongson64: Implement PM suspend for LEFI firmware
>
> arch/mips/Kconfig | 2 +-
> arch/mips/include/asm/pm.h | 22 +++++------
> arch/mips/loongson64/Makefile | 2 +-
> arch/mips/loongson64/pm.c | 88 +++++++++---------------------------------
> arch/mips/loongson64/sleeper.S | 17 ++++++++
> 5 files changed, 48 insertions(+), 83 deletions(-)

series applied to mips-next.

Thomas.

--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]