sleep.S 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * (C) Copyright 2009, Texas Instruments, Inc. http://www.ti.com/
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  16. * MA 02111-1307 USA
  17. */
  18. /* replicated define because linux/bitops.h cannot be included in assembly */
  19. #define BIT(nr) (1 << (nr))
  20. #include <linux/linkage.h>
  21. #include <asm/assembler.h>
  22. #include "psc.h"
  23. #include "ddr2.h"
  24. #include "clock.h"
  25. /* Arbitrary, hardware currently does not update PHYRDY correctly */
  26. #define PHYRDY_CYCLES 0x1000
  27. /* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
  28. #define PLL_BYPASS_CYCLES (PLL_BYPASS_TIME * 25)
  29. #define PLL_RESET_CYCLES (PLL_RESET_TIME * 25)
  30. #define PLL_LOCK_CYCLES (PLL_LOCK_TIME * 25)
  31. #define DEEPSLEEP_SLEEPENABLE_BIT BIT(31)
  32. .text
  33. /*
  34. * Move DaVinci into deep sleep state
  35. *
  36. * Note: This code is copied to internal SRAM by PM code. When the DaVinci
  37. * wakes up it continues execution at the point it went to sleep.
  38. * Register Usage:
  39. * r0: contains virtual base for DDR2 controller
  40. * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
  41. * r2: contains PSC number for DDR2
  42. * r3: contains virtual base DDR2 PLL controller
  43. * r4: contains virtual address of the DEEPSLEEP register
  44. */
  45. ENTRY(davinci_cpu_suspend)
  46. stmfd sp!, {r0-r12, lr} @ save registers on stack
  47. ldr ip, CACHE_FLUSH
  48. blx ip
  49. ldmia r0, {r0-r4}
  50. /*
  51. * Switch DDR to self-refresh mode.
  52. */
  53. /* calculate SDRCR address */
  54. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  55. bic ip, ip, #DDR2_SRPD_BIT
  56. orr ip, ip, #DDR2_LPMODEN_BIT
  57. str ip, [r0, #DDR2_SDRCR_OFFSET]
  58. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  59. orr ip, ip, #DDR2_MCLKSTOPEN_BIT
  60. str ip, [r0, #DDR2_SDRCR_OFFSET]
  61. mov ip, #PHYRDY_CYCLES
  62. 1: subs ip, ip, #0x1
  63. bne 1b
  64. /* Disable DDR2 LPSC */
  65. mov r7, r0
  66. mov r0, #0x2
  67. bl davinci_ddr_psc_config
  68. mov r0, r7
  69. /* Disable clock to DDR PHY */
  70. ldr ip, [r3, #PLLDIV1]
  71. bic ip, ip, #PLLDIV_EN
  72. str ip, [r3, #PLLDIV1]
  73. /* Put the DDR PLL in bypass and power down */
  74. ldr ip, [r3, #PLLCTL]
  75. bic ip, ip, #PLLCTL_PLLENSRC
  76. bic ip, ip, #PLLCTL_PLLEN
  77. str ip, [r3, #PLLCTL]
  78. /* Wait for PLL to switch to bypass */
  79. mov ip, #PLL_BYPASS_CYCLES
  80. 2: subs ip, ip, #0x1
  81. bne 2b
  82. /* Power down the PLL */
  83. ldr ip, [r3, #PLLCTL]
  84. orr ip, ip, #PLLCTL_PLLPWRDN
  85. str ip, [r3, #PLLCTL]
  86. /* Go to deep sleep */
  87. ldr ip, [r4]
  88. orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
  89. /* System goes to sleep beyond after this instruction */
  90. str ip, [r4]
  91. /* Wake up from sleep */
  92. /* Clear sleep enable */
  93. ldr ip, [r4]
  94. bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
  95. str ip, [r4]
  96. /* initialize the DDR PLL controller */
  97. /* Put PLL in reset */
  98. ldr ip, [r3, #PLLCTL]
  99. bic ip, ip, #PLLCTL_PLLRST
  100. str ip, [r3, #PLLCTL]
  101. /* Clear PLL power down */
  102. ldr ip, [r3, #PLLCTL]
  103. bic ip, ip, #PLLCTL_PLLPWRDN
  104. str ip, [r3, #PLLCTL]
  105. mov ip, #PLL_RESET_CYCLES
  106. 3: subs ip, ip, #0x1
  107. bne 3b
  108. /* Bring PLL out of reset */
  109. ldr ip, [r3, #PLLCTL]
  110. orr ip, ip, #PLLCTL_PLLRST
  111. str ip, [r3, #PLLCTL]
  112. /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
  113. mov ip, #PLL_LOCK_CYCLES
  114. 4: subs ip, ip, #0x1
  115. bne 4b
  116. /* Remove PLL from bypass mode */
  117. ldr ip, [r3, #PLLCTL]
  118. bic ip, ip, #PLLCTL_PLLENSRC
  119. orr ip, ip, #PLLCTL_PLLEN
  120. str ip, [r3, #PLLCTL]
  121. /* Start 2x clock to DDR2 */
  122. ldr ip, [r3, #PLLDIV1]
  123. orr ip, ip, #PLLDIV_EN
  124. str ip, [r3, #PLLDIV1]
  125. /* Enable VCLK */
  126. /* Enable DDR2 LPSC */
  127. mov r7, r0
  128. mov r0, #0x3
  129. bl davinci_ddr_psc_config
  130. mov r0, r7
  131. /* clear MCLKSTOPEN */
  132. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  133. bic ip, ip, #DDR2_MCLKSTOPEN_BIT
  134. str ip, [r0, #DDR2_SDRCR_OFFSET]
  135. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  136. bic ip, ip, #DDR2_LPMODEN_BIT
  137. str ip, [r0, #DDR2_SDRCR_OFFSET]
  138. /* Restore registers and return */
  139. ldmfd sp!, {r0-r12, pc}
  140. ENDPROC(davinci_cpu_suspend)
  141. /*
  142. * Disables or Enables DDR2 LPSC
  143. * Register Usage:
  144. * r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
  145. * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
  146. * r2: contains PSC number for DDR2
  147. */
  148. ENTRY(davinci_ddr_psc_config)
  149. /* Set next state in mdctl for DDR2 */
  150. mov r6, #MDCTL
  151. add r6, r6, r2, lsl #2
  152. ldr ip, [r1, r6]
  153. bic ip, ip, #MDSTAT_STATE_MASK
  154. orr ip, ip, r0
  155. str ip, [r1, r6]
  156. /* Enable the Power Domain Transition Command */
  157. ldr ip, [r1, #PTCMD]
  158. orr ip, ip, #0x1
  159. str ip, [r1, #PTCMD]
  160. /* Check for Transition Complete (PTSTAT) */
  161. ptstat_done:
  162. ldr ip, [r1, #PTSTAT]
  163. and ip, ip, #0x1
  164. cmp ip, #0x0
  165. bne ptstat_done
  166. /* Check for DDR2 clock disable completion; */
  167. mov r6, #MDSTAT
  168. add r6, r6, r2, lsl #2
  169. ddr2clk_stop_done:
  170. ldr ip, [r1, r6]
  171. and ip, ip, #MDSTAT_STATE_MASK
  172. cmp ip, r0
  173. bne ddr2clk_stop_done
  174. ret lr
  175. ENDPROC(davinci_ddr_psc_config)
  176. CACHE_FLUSH:
  177. #ifdef CONFIG_CPU_V6
  178. .word v6_flush_kern_cache_all
  179. #else
  180. .word arm926_flush_kern_cache_all
  181. #endif
  182. ENTRY(davinci_cpu_suspend_sz)
  183. .word . - davinci_cpu_suspend
  184. ENDPROC(davinci_cpu_suspend_sz)