forked from grate-driver/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LoongArch: Add suspend (ACPI S3) support
Add suspend (Suspend To RAM, aka ACPI S3) support for LoongArch. Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
- Loading branch information
1 parent
27cab43
commit 366bb35
Showing
13 changed files
with
260 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
obj-y += platform.o | ||
|
||
obj-$(CONFIG_SUSPEND) += suspend.o suspend_asm.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Author: Huacai Chen <chenhuacai@loongson.cn> | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
#include <linux/acpi.h> | ||
#include <linux/platform_device.h> | ||
|
||
#include <asm/bootinfo.h> | ||
#include <asm/loongson.h> | ||
|
||
void enable_gpe_wakeup(void) | ||
{ | ||
if (acpi_disabled) | ||
return; | ||
|
||
if (acpi_gbl_reduced_hardware) | ||
return; | ||
|
||
acpi_enable_all_wakeup_gpes(); | ||
} | ||
|
||
void enable_pci_wakeup(void) | ||
{ | ||
if (acpi_disabled) | ||
return; | ||
|
||
if (acpi_gbl_reduced_hardware) | ||
return; | ||
|
||
acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_STATUS, 1); | ||
|
||
if (acpi_gbl_FADT.flags & ACPI_FADT_PCI_EXPRESS_WAKE) | ||
acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0); | ||
} | ||
|
||
static int __init loongson3_acpi_suspend_init(void) | ||
{ | ||
#ifdef CONFIG_ACPI | ||
acpi_status status; | ||
uint64_t suspend_addr = 0; | ||
|
||
if (acpi_disabled || acpi_gbl_reduced_hardware) | ||
return 0; | ||
|
||
acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); | ||
status = acpi_evaluate_integer(NULL, "\\SADR", NULL, &suspend_addr); | ||
if (ACPI_FAILURE(status) || !suspend_addr) { | ||
pr_err("ACPI S3 is not support!\n"); | ||
return -1; | ||
} | ||
loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr)); | ||
#endif | ||
return 0; | ||
} | ||
|
||
device_initcall(loongson3_acpi_suspend_init); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* loongson-specific suspend support | ||
* | ||
* Author: Huacai Chen <chenhuacai@loongson.cn> | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
#include <linux/acpi.h> | ||
#include <linux/pm.h> | ||
#include <linux/suspend.h> | ||
|
||
#include <asm/loongarch.h> | ||
#include <asm/loongson.h> | ||
#include <asm/setup.h> | ||
#include <asm/time.h> | ||
#include <asm/tlbflush.h> | ||
|
||
u64 loongarch_suspend_addr; | ||
|
||
struct saved_registers { | ||
u32 ecfg; | ||
u32 euen; | ||
u64 pgd; | ||
u64 kpgd; | ||
u32 pwctl0; | ||
u32 pwctl1; | ||
}; | ||
static struct saved_registers saved_regs; | ||
|
||
static void arch_common_suspend(void) | ||
{ | ||
save_counter(); | ||
saved_regs.pgd = csr_read64(LOONGARCH_CSR_PGDL); | ||
saved_regs.kpgd = csr_read64(LOONGARCH_CSR_PGDH); | ||
saved_regs.pwctl0 = csr_read32(LOONGARCH_CSR_PWCTL0); | ||
saved_regs.pwctl1 = csr_read32(LOONGARCH_CSR_PWCTL1); | ||
saved_regs.ecfg = csr_read32(LOONGARCH_CSR_ECFG); | ||
saved_regs.euen = csr_read32(LOONGARCH_CSR_EUEN); | ||
|
||
loongarch_suspend_addr = loongson_sysconf.suspend_addr; | ||
} | ||
|
||
static void arch_common_resume(void) | ||
{ | ||
sync_counter(); | ||
local_flush_tlb_all(); | ||
csr_write64(per_cpu_offset(0), PERCPU_BASE_KS); | ||
csr_write64(eentry, LOONGARCH_CSR_EENTRY); | ||
csr_write64(eentry, LOONGARCH_CSR_MERRENTRY); | ||
csr_write64(tlbrentry, LOONGARCH_CSR_TLBRENTRY); | ||
|
||
csr_write64(saved_regs.pgd, LOONGARCH_CSR_PGDL); | ||
csr_write64(saved_regs.kpgd, LOONGARCH_CSR_PGDH); | ||
csr_write32(saved_regs.pwctl0, LOONGARCH_CSR_PWCTL0); | ||
csr_write32(saved_regs.pwctl1, LOONGARCH_CSR_PWCTL1); | ||
csr_write32(saved_regs.ecfg, LOONGARCH_CSR_ECFG); | ||
csr_write32(saved_regs.euen, LOONGARCH_CSR_EUEN); | ||
} | ||
|
||
int loongarch_acpi_suspend(void) | ||
{ | ||
enable_gpe_wakeup(); | ||
enable_pci_wakeup(); | ||
|
||
arch_common_suspend(); | ||
|
||
/* processor specific suspend */ | ||
loongarch_suspend_enter(); | ||
|
||
arch_common_resume(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* 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 a0, 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) | ||
li.d t0, CSR_DMW0_INIT # UC, PLV0 | ||
csrwr t0, LOONGARCH_CSR_DMWIN0 | ||
li.d t0, CSR_DMW1_INIT # CA, PLV0 | ||
csrwr t0, LOONGARCH_CSR_DMWIN1 | ||
|
||
la.abs t0, 0f | ||
jr t0 | ||
0: | ||
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) |