cpu_hibernate64.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/types.h>
  5. #include <linux/spinlock.h>
  6. #include <linux/poll.h>
  7. #include <linux/delay.h>
  8. #include <linux/sysrq.h>
  9. #include <linux/proc_fs.h>
  10. #include <linux/pm.h>
  11. #include <linux/device.h>
  12. #include <linux/suspend.h>
  13. #include <linux/mm.h>
  14. #include <asm/irq.h>
  15. #include <asm/uaccess.h>
  16. #include <asm/tlbflush.h>
  17. #include <asm/cacheflush.h>
  18. #include <asm/system_misc.h>
  19. #include <asm/mmu.h>
  20. #include <asm/suspend.h>
  21. #include <asm/sections.h>
  22. #include <mtk_hibernate_core.h>
  23. typedef struct fault_regs {
  24. unsigned dfar;
  25. unsigned ifar;
  26. unsigned ifsr;
  27. unsigned dfsr;
  28. unsigned adfsr;
  29. unsigned aifsr;
  30. } cp15_fault_regs;
  31. typedef struct ns_banked_cp15_context {
  32. unsigned int cp15_misc_regs[2]; /* cp15 miscellaneous registers */
  33. unsigned int cp15_ctrl_regs[20]; /* cp15 control registers */
  34. unsigned int cp15_mmu_regs[16]; /* cp15 mmu registers */
  35. cp15_fault_regs ns_cp15_fault_regs; /* cp15 fault status registers */
  36. } banked_cp15_context;
  37. typedef struct ns_hib_core_context {
  38. unsigned int banked_regs[32];
  39. unsigned int timer_data[8]; /* Global timers if the NS world has access to them */
  40. } hib_core_context;
  41. static banked_cp15_context saved_cp15_context;
  42. static hib_core_context saved_core_context;
  43. #define __pa_symbol(x)__pa(RELOC_HIDE((unsigned long)(x), 0))
  44. int pfn_is_nosave(unsigned long pfn)
  45. {
  46. unsigned long begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
  47. unsigned long end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
  48. return (pfn >= begin_pfn) && (pfn < end_pfn);
  49. }
  50. static void __save_processor_state(struct ns_banked_cp15_context *ctxt)
  51. {
  52. /* save preempt state and disable it */
  53. preempt_disable();
  54. mt_save_generic_timer(saved_core_context.timer_data, 0x0);
  55. mt_save_banked_registers(saved_core_context.banked_regs);
  56. }
  57. void notrace save_processor_state(void)
  58. {
  59. __save_processor_state(&saved_cp15_context);
  60. }
  61. EXPORT_SYMBOL(save_processor_state);
  62. static void __restore_processor_state(struct ns_banked_cp15_context *ctxt)
  63. {
  64. mt_restore_banked_registers(saved_core_context.banked_regs);
  65. mt_restore_generic_timer(saved_core_context.timer_data, 0x0);
  66. #ifdef CONFIG_MTK_ETM
  67. /* restore ETM module */
  68. trace_start_dormant();
  69. #endif
  70. /* restore preempt state */
  71. preempt_enable();
  72. }
  73. void notrace restore_processor_state(void)
  74. {
  75. __restore_processor_state(&saved_cp15_context);
  76. }
  77. EXPORT_SYMBOL(restore_processor_state);
  78. typedef void (*phys_reset_t)(unsigned long);
  79. static int swsusp_saved;
  80. /*
  81. * Snapshot kernel memory and reset the system.
  82. * After resume, the hibernation snapshot is written out.
  83. */
  84. int notrace swsusp_arch_save_image(unsigned long unused)
  85. {
  86. int ret;
  87. ret = swsusp_save();
  88. swsusp_saved = (ret == 0) ? 1 : 0;
  89. return ret;
  90. }
  91. /*
  92. * Save the current CPU state before suspend / poweroff.
  93. */
  94. int notrace swsusp_arch_suspend(void)
  95. {
  96. int retval = 0;
  97. retval = cpu_suspend(POWERMODE_HIBERNATE);
  98. if (swsusp_saved)
  99. retval = 0;
  100. return retval;
  101. }
  102. /*
  103. * The framework loads the hibernation image into a linked list anchored
  104. * at restore_pblist, for swsusp_arch_resume() to copy back to the proper
  105. * destinations.
  106. *
  107. * To make this work if resume is triggered from initramfs, the
  108. * pagetables need to be switched to allow writes to kernel mem.
  109. */
  110. static void notrace __swsusp_arch_restore_image(void *unused)
  111. {
  112. phys_reset_t phys_reset;
  113. struct pbe *pbe;
  114. for (pbe = restore_pblist; pbe; pbe = pbe->next)
  115. copy_page(pbe->orig_address, pbe->address);
  116. #if 0 /* [ALPS01496758] since CA17 has cache bug, replace with the modified assemlby version */
  117. /* Clean and invalidate caches */
  118. flush_cache_all();
  119. /* Turn D-cache off */
  120. cpu_cache_off();
  121. /* Push out any further dirty data, and ensure cache is empty */
  122. flush_cache_all();
  123. #else
  124. __disable_dcache__inner_flush_dcache_L1__inner_flush_dcache_L2();
  125. #endif
  126. /* Take out a flat memory mapping. */
  127. setup_mm_for_reboot();
  128. phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
  129. /* Return from cpu_suspend/swsusp_arch_suspend */
  130. phys_reset((unsigned long)virt_to_phys(cpu_resume));
  131. /* Should never get here. */
  132. BUG();
  133. }
  134. static u8 __aligned(16) __swsusp_resume_stk[PAGE_SIZE/2] __nosavedata;
  135. /*
  136. * Resume from the hibernation image.
  137. * Due to the kernel heap / data restore, stack contents change underneath
  138. * and that would make function calls impossible; switch to a temporary
  139. * stack within the nosave region to avoid that problem.
  140. */
  141. int swsusp_arch_resume(void)
  142. {
  143. #if 0 /* FIX ME: cpu_init in arm64 implementation */
  144. cpu_init(); /* get a clean PSR */
  145. #endif
  146. call_with_stack(__swsusp_arch_restore_image, 0,
  147. __swsusp_resume_stk + sizeof(__swsusp_resume_stk));
  148. return 0;
  149. }