suspend.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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. #include <asm/loongarch.h>
  12. #include <asm/loongson.h>
  13. #include <asm/setup.h>
  14. #include <asm/time.h>
  15. #include <asm/tlbflush.h>
  16. u64 loongarch_suspend_addr;
  17. struct saved_registers {
  18. u32 ecfg;
  19. u32 euen;
  20. u64 pgd;
  21. u64 kpgd;
  22. u32 pwctl0;
  23. u32 pwctl1;
  24. u64 pcpu_base;
  25. };
  26. static struct saved_registers saved_regs;
  27. void loongarch_common_suspend(void)
  28. {
  29. save_counter();
  30. saved_regs.pgd = csr_read64(LOONGARCH_CSR_PGDL);
  31. saved_regs.kpgd = csr_read64(LOONGARCH_CSR_PGDH);
  32. saved_regs.pwctl0 = csr_read32(LOONGARCH_CSR_PWCTL0);
  33. saved_regs.pwctl1 = csr_read32(LOONGARCH_CSR_PWCTL1);
  34. saved_regs.ecfg = csr_read32(LOONGARCH_CSR_ECFG);
  35. saved_regs.euen = csr_read32(LOONGARCH_CSR_EUEN);
  36. saved_regs.pcpu_base = csr_read64(PERCPU_BASE_KS);
  37. loongarch_suspend_addr = loongson_sysconf.suspend_addr;
  38. }
  39. void loongarch_common_resume(void)
  40. {
  41. sync_counter();
  42. local_flush_tlb_all();
  43. csr_write64(eentry, LOONGARCH_CSR_EENTRY);
  44. csr_write64(eentry, LOONGARCH_CSR_MERRENTRY);
  45. csr_write64(tlbrentry, LOONGARCH_CSR_TLBRENTRY);
  46. csr_write64(saved_regs.pgd, LOONGARCH_CSR_PGDL);
  47. csr_write64(saved_regs.kpgd, LOONGARCH_CSR_PGDH);
  48. csr_write32(saved_regs.pwctl0, LOONGARCH_CSR_PWCTL0);
  49. csr_write32(saved_regs.pwctl1, LOONGARCH_CSR_PWCTL1);
  50. csr_write32(saved_regs.ecfg, LOONGARCH_CSR_ECFG);
  51. csr_write32(saved_regs.euen, LOONGARCH_CSR_EUEN);
  52. csr_write64(saved_regs.pcpu_base, PERCPU_BASE_KS);
  53. }
  54. int loongarch_acpi_suspend(void)
  55. {
  56. enable_gpe_wakeup();
  57. enable_pci_wakeup();
  58. loongarch_common_suspend();
  59. /* processor specific suspend */
  60. loongarch_suspend_enter();
  61. loongarch_common_resume();
  62. return 0;
  63. }