idle_e500.S 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. #include <asm/feature-fixups.h>
  20. .text
  21. _GLOBAL(e500_idle)
  22. CURRENT_THREAD_INFO(r3, r1)
  23. lwz r4,TI_LOCAL_FLAGS(r3) /* set napping bit */
  24. ori r4,r4,_TLF_NAPPING /* so when we take an exception */
  25. stw r4,TI_LOCAL_FLAGS(r3) /* it will return to our caller */
  26. #ifdef CONFIG_PPC_E500MC
  27. wrteei 1
  28. 1: wait
  29. /*
  30. * Guard against spurious wakeups (e.g. from a hypervisor) --
  31. * any real interrupt will cause us to return to LR due to
  32. * _TLF_NAPPING.
  33. */
  34. b 1b
  35. #else
  36. /* Check if we can nap or doze, put HID0 mask in r3 */
  37. lis r3,0
  38. BEGIN_FTR_SECTION
  39. lis r3,HID0_DOZE@h
  40. END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
  41. BEGIN_FTR_SECTION
  42. /* Now check if user enabled NAP mode */
  43. lis r4,powersave_nap@ha
  44. lwz r4,powersave_nap@l(r4)
  45. cmpwi 0,r4,0
  46. beq 1f
  47. stwu r1,-16(r1)
  48. mflr r0
  49. stw r0,20(r1)
  50. bl flush_dcache_L1
  51. lwz r0,20(r1)
  52. addi r1,r1,16
  53. mtlr r0
  54. lis r3,HID0_NAP@h
  55. END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
  56. 1:
  57. /* Go to NAP or DOZE now */
  58. mfspr r4,SPRN_HID0
  59. rlwinm r4,r4,0,~(HID0_DOZE|HID0_NAP|HID0_SLEEP)
  60. or r4,r4,r3
  61. isync
  62. mtspr SPRN_HID0,r4
  63. isync
  64. mfmsr r7
  65. oris r7,r7,MSR_WE@h
  66. ori r7,r7,MSR_EE
  67. msync
  68. mtmsr r7
  69. isync
  70. 2: b 2b
  71. #endif /* !E500MC */
  72. /*
  73. * Return from NAP/DOZE mode, restore some CPU specific registers,
  74. * r2 containing physical address of current.
  75. * r11 points to the exception frame (physical address).
  76. * We have to preserve r10.
  77. */
  78. _GLOBAL(power_save_ppc32_restore)
  79. lwz r9,_LINK(r11) /* interrupted in e500_idle */
  80. stw r9,_NIP(r11) /* make it do a blr */
  81. #ifdef CONFIG_SMP
  82. CURRENT_THREAD_INFO(r12, r1)
  83. lwz r11,TI_CPU(r12) /* get cpu number * 4 */
  84. slwi r11,r11,2
  85. #else
  86. li r11,0
  87. #endif
  88. b transfer_to_handler_cont