idle_e500.S 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. rlwinm r3,r1,0,0,31-THREAD_SHIFT /* current thread_info */
  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. BEGIN_FTR_SECTION
  56. msync
  57. li r7,L2CSR0_L2FL@l
  58. mtspr SPRN_L2CSR0,r7
  59. 2:
  60. mfspr r7,SPRN_L2CSR0
  61. andi. r4,r7,L2CSR0_L2FL@l
  62. bne 2b
  63. END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
  64. 1:
  65. /* Go to NAP or DOZE now */
  66. mfspr r4,SPRN_HID0
  67. rlwinm r4,r4,0,~(HID0_DOZE|HID0_NAP|HID0_SLEEP)
  68. or r4,r4,r3
  69. isync
  70. mtspr SPRN_HID0,r4
  71. isync
  72. mfmsr r7
  73. oris r7,r7,MSR_WE@h
  74. ori r7,r7,MSR_EE
  75. msync
  76. mtmsr r7
  77. isync
  78. 2: b 2b
  79. #endif /* !E500MC */
  80. /*
  81. * Return from NAP/DOZE mode, restore some CPU specific registers,
  82. * r2 containing physical address of current.
  83. * r11 points to the exception frame (physical address).
  84. * We have to preserve r10.
  85. */
  86. _GLOBAL(power_save_ppc32_restore)
  87. lwz r9,_LINK(r11) /* interrupted in e500_idle */
  88. stw r9,_NIP(r11) /* make it do a blr */
  89. #ifdef CONFIG_SMP
  90. rlwinm r12,r1,0,0,31-THREAD_SHIFT
  91. lwz r11,TI_CPU(r12) /* get cpu number * 4 */
  92. slwi r11,r11,2
  93. #else
  94. li r11,0
  95. #endif
  96. b transfer_to_handler_cont