idle_e500.S 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. /* Check if we can nap or doze, put HID0 mask in r3 */
  26. lis r3,0
  27. BEGIN_FTR_SECTION
  28. lis r3,HID0_DOZE@h
  29. END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
  30. BEGIN_FTR_SECTION
  31. /* Now check if user enabled NAP mode */
  32. lis r4,powersave_nap@ha
  33. lwz r4,powersave_nap@l(r4)
  34. cmpwi 0,r4,0
  35. beq 1f
  36. stwu r1,-16(r1)
  37. mflr r0
  38. stw r0,20(r1)
  39. bl flush_dcache_L1
  40. lwz r0,20(r1)
  41. addi r1,r1,16
  42. mtlr r0
  43. lis r3,HID0_NAP@h
  44. END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
  45. BEGIN_FTR_SECTION
  46. msync
  47. li r7,L2CSR0_L2FL@l
  48. mtspr SPRN_L2CSR0,r7
  49. 2:
  50. mfspr r7,SPRN_L2CSR0
  51. andi. r4,r7,L2CSR0_L2FL@l
  52. bne 2b
  53. END_FTR_SECTION_IFSET(CPU_FTR_L2CSR|CPU_FTR_CAN_NAP)
  54. 1:
  55. /* Go to NAP or DOZE now */
  56. mfspr r4,SPRN_HID0
  57. rlwinm r4,r4,0,~(HID0_DOZE|HID0_NAP|HID0_SLEEP)
  58. or r4,r4,r3
  59. isync
  60. mtspr SPRN_HID0,r4
  61. isync
  62. mfmsr r7
  63. oris r7,r7,MSR_WE@h
  64. ori r7,r7,MSR_EE
  65. msync
  66. mtmsr r7
  67. isync
  68. 2: b 2b
  69. /*
  70. * Return from NAP/DOZE mode, restore some CPU specific registers,
  71. * r2 containing physical address of current.
  72. * r11 points to the exception frame (physical address).
  73. * We have to preserve r10.
  74. */
  75. _GLOBAL(power_save_ppc32_restore)
  76. lwz r9,_LINK(r11) /* interrupted in e500_idle */
  77. stw r9,_NIP(r11) /* make it do a blr */
  78. #ifdef CONFIG_SMP
  79. rlwinm r12,r1,0,0,31-THREAD_SHIFT
  80. lwz r11,TI_CPU(r12) /* get cpu number * 4 */
  81. slwi r11,r11,2
  82. #else
  83. li r11,0
  84. #endif
  85. b transfer_to_handler_cont