162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <asm/fpu.h>
362306a36Sopenharmony_ci#include <asm/loongson.h>
462306a36Sopenharmony_ci#include <asm/sections.h>
562306a36Sopenharmony_ci#include <asm/tlbflush.h>
662306a36Sopenharmony_ci#include <linux/suspend.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistatic u32 saved_crmd;
962306a36Sopenharmony_cistatic u32 saved_prmd;
1062306a36Sopenharmony_cistatic u32 saved_euen;
1162306a36Sopenharmony_cistatic u32 saved_ecfg;
1262306a36Sopenharmony_cistatic u64 saved_pcpu_base;
1362306a36Sopenharmony_cistruct pt_regs saved_regs;
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_civoid save_processor_state(void)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	saved_crmd = csr_read32(LOONGARCH_CSR_CRMD);
1862306a36Sopenharmony_ci	saved_prmd = csr_read32(LOONGARCH_CSR_PRMD);
1962306a36Sopenharmony_ci	saved_euen = csr_read32(LOONGARCH_CSR_EUEN);
2062306a36Sopenharmony_ci	saved_ecfg = csr_read32(LOONGARCH_CSR_ECFG);
2162306a36Sopenharmony_ci	saved_pcpu_base = csr_read64(PERCPU_BASE_KS);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	if (is_fpu_owner())
2462306a36Sopenharmony_ci		save_fp(current);
2562306a36Sopenharmony_ci}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_civoid restore_processor_state(void)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	csr_write32(saved_crmd, LOONGARCH_CSR_CRMD);
3062306a36Sopenharmony_ci	csr_write32(saved_prmd, LOONGARCH_CSR_PRMD);
3162306a36Sopenharmony_ci	csr_write32(saved_euen, LOONGARCH_CSR_EUEN);
3262306a36Sopenharmony_ci	csr_write32(saved_ecfg, LOONGARCH_CSR_ECFG);
3362306a36Sopenharmony_ci	csr_write64(saved_pcpu_base, PERCPU_BASE_KS);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	if (is_fpu_owner())
3662306a36Sopenharmony_ci		restore_fp(current);
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciint pfn_is_nosave(unsigned long pfn)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
4262306a36Sopenharmony_ci	unsigned long nosave_end_pfn = PFN_UP(__pa(&__nosave_end));
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	return	(pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciextern int swsusp_asm_suspend(void);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ciint swsusp_arch_suspend(void)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	enable_pci_wakeup();
5262306a36Sopenharmony_ci	return swsusp_asm_suspend();
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciextern int swsusp_asm_resume(void);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciint swsusp_arch_resume(void)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	/* Avoid TLB mismatch during and after kernel resume */
6062306a36Sopenharmony_ci	local_flush_tlb_all();
6162306a36Sopenharmony_ci	return swsusp_asm_resume();
6262306a36Sopenharmony_ci}
63