idle_e500.S 2.2 KB

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