18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * loongson-specific suspend support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author: Huacai Chen <chenhuacai@loongson.cn>
68c2ecf20Sopenharmony_ci * Copyright (C) 2020 Loongson Technology Co., Ltd.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/acpi.h>
98c2ecf20Sopenharmony_ci#include <linux/pm.h>
108c2ecf20Sopenharmony_ci#include <linux/suspend.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <asm/loongarchregs.h>
138c2ecf20Sopenharmony_ci#include <asm/setup.h>
148c2ecf20Sopenharmony_ci#include <asm/time.h>
158c2ecf20Sopenharmony_ci#include <asm/tlbflush.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <loongson.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciu64 loongarch_suspend_addr;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct saved_registers {
228c2ecf20Sopenharmony_ci	u32 ecfg;
238c2ecf20Sopenharmony_ci	u32 euen;
248c2ecf20Sopenharmony_ci	u64 pgd;
258c2ecf20Sopenharmony_ci	u64 kpgd;
268c2ecf20Sopenharmony_ci	u32 pwctl0;
278c2ecf20Sopenharmony_ci	u32 pwctl1;
288c2ecf20Sopenharmony_ci};
298c2ecf20Sopenharmony_cistatic struct saved_registers saved_regs;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic void arch_common_suspend(void)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	save_counter();
348c2ecf20Sopenharmony_ci	saved_regs.pgd = csr_read64(LOONGARCH_CSR_PGDL);
358c2ecf20Sopenharmony_ci	saved_regs.kpgd = csr_read64(LOONGARCH_CSR_PGDH);
368c2ecf20Sopenharmony_ci	saved_regs.pwctl0 = csr_read32(LOONGARCH_CSR_PWCTL0);
378c2ecf20Sopenharmony_ci	saved_regs.pwctl1 = csr_read32(LOONGARCH_CSR_PWCTL1);
388c2ecf20Sopenharmony_ci	saved_regs.ecfg = csr_read32(LOONGARCH_CSR_ECFG);
398c2ecf20Sopenharmony_ci	saved_regs.euen = csr_read32(LOONGARCH_CSR_EUEN);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	loongarch_suspend_addr = loongson_sysconf.suspend_addr;
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic void arch_common_resume(void)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	sync_counter();
478c2ecf20Sopenharmony_ci	local_flush_tlb_all();
488c2ecf20Sopenharmony_ci	csr_write64(per_cpu_offset(0), PERCPU_BASE_KS);
498c2ecf20Sopenharmony_ci	csr_write64(eentry, LOONGARCH_CSR_EENTRY);
508c2ecf20Sopenharmony_ci	csr_write64(eentry, LOONGARCH_CSR_MERRENTRY);
518c2ecf20Sopenharmony_ci	csr_write64(tlbrentry, LOONGARCH_CSR_TLBRENTRY);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	csr_write64(saved_regs.pgd, LOONGARCH_CSR_PGDL);
548c2ecf20Sopenharmony_ci	csr_write64(saved_regs.kpgd, LOONGARCH_CSR_PGDH);
558c2ecf20Sopenharmony_ci	csr_write32(saved_regs.pwctl0, LOONGARCH_CSR_PWCTL0);
568c2ecf20Sopenharmony_ci	csr_write32(saved_regs.pwctl1, LOONGARCH_CSR_PWCTL1);
578c2ecf20Sopenharmony_ci	csr_write32(saved_regs.ecfg, LOONGARCH_CSR_ECFG);
588c2ecf20Sopenharmony_ci	csr_write32(saved_regs.euen, LOONGARCH_CSR_EUEN);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ciint loongarch_acpi_suspend(void)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	enable_gpe_wakeup();
648c2ecf20Sopenharmony_ci	enable_pci_wakeup();
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	arch_common_suspend();
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	/* processor specific suspend */
698c2ecf20Sopenharmony_ci	loongarch_suspend_enter();
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	arch_common_resume();
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	return 0;
748c2ecf20Sopenharmony_ci}
75