idle_85xx.S 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
  4. * Dave Liu <[email protected]>
  5. * copy from idle_6xx.S and modify for e500 based processor,
  6. * implement the power_save function in idle.
  7. */
  8. #include <linux/threads.h>
  9. #include <asm/reg.h>
  10. #include <asm/page.h>
  11. #include <asm/cputable.h>
  12. #include <asm/thread_info.h>
  13. #include <asm/ppc_asm.h>
  14. #include <asm/asm-offsets.h>
  15. #include <asm/feature-fixups.h>
  16. .text
  17. _GLOBAL(e500_idle)
  18. lwz r4,TI_LOCAL_FLAGS(r2) /* set napping bit */
  19. ori r4,r4,_TLF_NAPPING /* so when we take an exception */
  20. stw r4,TI_LOCAL_FLAGS(r2) /* it will return to our caller */
  21. #ifdef CONFIG_PPC_E500MC
  22. wrteei 1
  23. 1: wait
  24. /*
  25. * Guard against spurious wakeups (e.g. from a hypervisor) --
  26. * any real interrupt will cause us to return to LR due to
  27. * _TLF_NAPPING.
  28. */
  29. b 1b
  30. #else
  31. /* Check if we can nap or doze, put HID0 mask in r3 */
  32. lis r3,0
  33. BEGIN_FTR_SECTION
  34. lis r3,HID0_DOZE@h
  35. END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
  36. BEGIN_FTR_SECTION
  37. /* Now check if user enabled NAP mode */
  38. lis r4,powersave_nap@ha
  39. lwz r4,powersave_nap@l(r4)
  40. cmpwi 0,r4,0
  41. beq 1f
  42. stwu r1,-16(r1)
  43. mflr r0
  44. stw r0,20(r1)
  45. bl flush_dcache_L1
  46. lwz r0,20(r1)
  47. addi r1,r1,16
  48. mtlr r0
  49. lis r3,HID0_NAP@h
  50. END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
  51. 1:
  52. /* Go to NAP or DOZE now */
  53. mfspr r4,SPRN_HID0
  54. rlwinm r4,r4,0,~(HID0_DOZE|HID0_NAP|HID0_SLEEP)
  55. or r4,r4,r3
  56. isync
  57. mtspr SPRN_HID0,r4
  58. isync
  59. mfmsr r7
  60. oris r7,r7,MSR_WE@h
  61. ori r7,r7,MSR_EE
  62. msync
  63. mtmsr r7
  64. isync
  65. 2: b 2b
  66. #endif /* !E500MC */
  67. /*
  68. * Return from NAP/DOZE mode, restore some CPU specific registers,
  69. * r2 containing address of current.
  70. * r11 points to the exception frame.
  71. * We have to preserve r10.
  72. */
  73. _GLOBAL(power_save_ppc32_restore)
  74. lwz r9,_LINK(r11) /* interrupted in e500_idle */
  75. stw r9,_NIP(r11) /* make it do a blr */
  76. blr
  77. _ASM_NOKPROBE_SYMBOL(power_save_ppc32_restore)