1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * loongson-specific suspend support |
4 | * |
5 | * Author: Huacai Chen <chenhuacai@loongson.cn> |
6 | * Copyright (C) 2020-2022 Loongson Technology Corporation Limited |
7 | */ |
8 | #include <linux/acpi.h> |
9 | #include <linux/pm.h> |
10 | #include <linux/suspend.h> |
11 | |
12 | #include <asm/loongarch.h> |
13 | #include <asm/loongson.h> |
14 | #include <asm/setup.h> |
15 | #include <asm/time.h> |
16 | #include <asm/tlbflush.h> |
17 | |
18 | u64 loongarch_suspend_addr; |
19 | |
20 | struct saved_registers { |
21 | u32 ecfg; |
22 | u32 euen; |
23 | u64 pgd; |
24 | u64 kpgd; |
25 | u32 pwctl0; |
26 | u32 pwctl1; |
27 | }; |
28 | static struct saved_registers saved_regs; |
29 | |
30 | void loongarch_common_suspend(void) |
31 | { |
32 | save_counter(); |
33 | saved_regs.pgd = csr_read64(LOONGARCH_CSR_PGDL); |
34 | saved_regs.kpgd = csr_read64(LOONGARCH_CSR_PGDH); |
35 | saved_regs.pwctl0 = csr_read32(LOONGARCH_CSR_PWCTL0); |
36 | saved_regs.pwctl1 = csr_read32(LOONGARCH_CSR_PWCTL1); |
37 | saved_regs.ecfg = csr_read32(LOONGARCH_CSR_ECFG); |
38 | saved_regs.euen = csr_read32(LOONGARCH_CSR_EUEN); |
39 | |
40 | loongarch_suspend_addr = loongson_sysconf.suspend_addr; |
41 | } |
42 | |
43 | void loongarch_common_resume(void) |
44 | { |
45 | sync_counter(); |
46 | local_flush_tlb_all(); |
47 | csr_write64(per_cpu_offset(0), PERCPU_BASE_KS); |
48 | csr_write64(eentry, LOONGARCH_CSR_EENTRY); |
49 | csr_write64(eentry, LOONGARCH_CSR_MERRENTRY); |
50 | csr_write64(tlbrentry, LOONGARCH_CSR_TLBRENTRY); |
51 | |
52 | csr_write64(saved_regs.pgd, LOONGARCH_CSR_PGDL); |
53 | csr_write64(saved_regs.kpgd, LOONGARCH_CSR_PGDH); |
54 | csr_write32(saved_regs.pwctl0, LOONGARCH_CSR_PWCTL0); |
55 | csr_write32(saved_regs.pwctl1, LOONGARCH_CSR_PWCTL1); |
56 | csr_write32(saved_regs.ecfg, LOONGARCH_CSR_ECFG); |
57 | csr_write32(saved_regs.euen, LOONGARCH_CSR_EUEN); |
58 | } |
59 | |
60 | int loongarch_acpi_suspend(void) |
61 | { |
62 | enable_gpe_wakeup(); |
63 | enable_pci_wakeup(); |
64 | |
65 | loongarch_common_suspend(); |
66 | |
67 | /* processor specific suspend */ |
68 | loongarch_suspend_enter(); |
69 | |
70 | loongarch_common_resume(); |
71 | |
72 | return 0; |
73 | } |
74 | |