2023-08-30 17:31:07 +02:00
|
|
|
// 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;
|
|
|
|
|
2023-10-24 12:59:35 +02:00
|
|
|
void loongarch_common_suspend(void)
|
2023-08-30 17:31:07 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-10-24 12:59:35 +02:00
|
|
|
void loongarch_common_resume(void)
|
2023-08-30 17:31:07 +02:00
|
|
|
{
|
|
|
|
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();
|
|
|
|
|
2023-10-24 12:59:35 +02:00
|
|
|
loongarch_common_suspend();
|
2023-08-30 17:31:07 +02:00
|
|
|
|
|
|
|
/* processor specific suspend */
|
|
|
|
loongarch_suspend_enter();
|
|
|
|
|
2023-10-24 12:59:35 +02:00
|
|
|
loongarch_common_resume();
|
2023-08-30 17:31:07 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|