mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:18:58 +00:00
e523a5a65f
Most LoongArch 64 machines are using custom "SADR" ACPI extension to perform ACPI S3 sleep. However the standard ACPI way to perform sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this is never supported properly in kernel. Add standard S3 sleep by providing a default DoSuspend function which calls ACPI's acpi_enter_sleep_state() routine when SADR is not provided by the firmware. Also fix suspend assembly code so that ra is set properly before go into sleep routine. (Previously linked address of jirl was set to a0, some firmware do require return address in a0 but it's already set with la.pcrel before). Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
89 lines
1.9 KiB
ArmAsm
89 lines
1.9 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Sleep helper for Loongson-3 sleep mode.
|
|
*
|
|
* Author: Huacai Chen <chenhuacai@loongson.cn>
|
|
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
|
*/
|
|
|
|
#include <asm/asm.h>
|
|
#include <asm/asmmacro.h>
|
|
#include <asm/addrspace.h>
|
|
#include <asm/loongarch.h>
|
|
#include <asm/stackframe.h>
|
|
|
|
/* preparatory stuff */
|
|
.macro SETUP_SLEEP
|
|
addi.d sp, sp, -PT_SIZE
|
|
st.d $r1, sp, PT_R1
|
|
st.d $r2, sp, PT_R2
|
|
st.d $r3, sp, PT_R3
|
|
st.d $r4, sp, PT_R4
|
|
st.d $r21, sp, PT_R21
|
|
st.d $r22, sp, PT_R22
|
|
st.d $r23, sp, PT_R23
|
|
st.d $r24, sp, PT_R24
|
|
st.d $r25, sp, PT_R25
|
|
st.d $r26, sp, PT_R26
|
|
st.d $r27, sp, PT_R27
|
|
st.d $r28, sp, PT_R28
|
|
st.d $r29, sp, PT_R29
|
|
st.d $r30, sp, PT_R30
|
|
st.d $r31, sp, PT_R31
|
|
|
|
la.pcrel t0, acpi_saved_sp
|
|
st.d sp, t0, 0
|
|
.endm
|
|
|
|
.macro SETUP_WAKEUP
|
|
ld.d $r1, sp, PT_R1
|
|
ld.d $r2, sp, PT_R2
|
|
ld.d $r3, sp, PT_R3
|
|
ld.d $r4, sp, PT_R4
|
|
ld.d $r21, sp, PT_R21
|
|
ld.d $r22, sp, PT_R22
|
|
ld.d $r23, sp, PT_R23
|
|
ld.d $r24, sp, PT_R24
|
|
ld.d $r25, sp, PT_R25
|
|
ld.d $r26, sp, PT_R26
|
|
ld.d $r27, sp, PT_R27
|
|
ld.d $r28, sp, PT_R28
|
|
ld.d $r29, sp, PT_R29
|
|
ld.d $r30, sp, PT_R30
|
|
ld.d $r31, sp, PT_R31
|
|
.endm
|
|
|
|
.text
|
|
.align 12
|
|
|
|
/* Sleep/wakeup code for Loongson-3 */
|
|
SYM_FUNC_START(loongarch_suspend_enter)
|
|
SETUP_SLEEP
|
|
bl __flush_cache_all
|
|
|
|
/* Pass RA and SP to BIOS */
|
|
addi.d a1, sp, 0
|
|
la.pcrel a0, loongarch_wakeup_start
|
|
la.pcrel t0, loongarch_suspend_addr
|
|
ld.d t0, t0, 0
|
|
jirl ra, t0, 0 /* Call BIOS's STR sleep routine */
|
|
|
|
/*
|
|
* This is where we return upon wakeup.
|
|
* Reload all of the registers and return.
|
|
*/
|
|
SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
|
|
SETUP_DMWINS t0
|
|
JUMP_VIRT_ADDR t0, t1
|
|
|
|
/* Enable PG */
|
|
li.w t0, 0xb0 # PLV=0, IE=0, PG=1
|
|
csrwr t0, LOONGARCH_CSR_CRMD
|
|
|
|
la.pcrel t0, acpi_saved_sp
|
|
ld.d sp, t0, 0
|
|
SETUP_WAKEUP
|
|
addi.d sp, sp, PT_SIZE
|
|
jr ra
|
|
SYM_FUNC_END(loongarch_suspend_enter)
|