sleep.S 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. .arch armv5te
  34. /*
  35. * Move DaVinci into deep sleep state
  36. *
  37. * Note: This code is copied to internal SRAM by PM code. When the DaVinci
  38. * wakes up it continues execution at the point it went to sleep.
  39. * Register Usage:
  40. * r0: contains virtual base for DDR2 controller
  41. * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
  42. * r2: contains PSC number for DDR2
  43. * r3: contains virtual base DDR2 PLL controller
  44. * r4: contains virtual address of the DEEPSLEEP register
  45. */
  46. ENTRY(davinci_cpu_suspend)
  47. stmfd sp!, {r0-r12, lr} @ save registers on stack
  48. ldr ip, CACHE_FLUSH
  49. blx ip
  50. ldmia r0, {r0-r4}
  51. /*
  52. * Switch DDR to self-refresh mode.
  53. */
  54. /* calculate SDRCR address */
  55. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  56. bic ip, ip, #DDR2_SRPD_BIT
  57. orr ip, ip, #DDR2_LPMODEN_BIT
  58. str ip, [r0, #DDR2_SDRCR_OFFSET]
  59. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  60. orr ip, ip, #DDR2_MCLKSTOPEN_BIT
  61. str ip, [r0, #DDR2_SDRCR_OFFSET]
  62. mov ip, #PHYRDY_CYCLES
  63. 1: subs ip, ip, #0x1
  64. bne 1b
  65. /* Disable DDR2 LPSC */
  66. mov r7, r0
  67. mov r0, #0x2
  68. bl davinci_ddr_psc_config
  69. mov r0, r7
  70. /* Disable clock to DDR PHY */
  71. ldr ip, [r3, #PLLDIV1]
  72. bic ip, ip, #PLLDIV_EN
  73. str ip, [r3, #PLLDIV1]
  74. /* Put the DDR PLL in bypass and power down */
  75. ldr ip, [r3, #PLLCTL]
  76. bic ip, ip, #PLLCTL_PLLENSRC
  77. bic ip, ip, #PLLCTL_PLLEN
  78. str ip, [r3, #PLLCTL]
  79. /* Wait for PLL to switch to bypass */
  80. mov ip, #PLL_BYPASS_CYCLES
  81. 2: subs ip, ip, #0x1
  82. bne 2b
  83. /* Power down the PLL */
  84. ldr ip, [r3, #PLLCTL]
  85. orr ip, ip, #PLLCTL_PLLPWRDN
  86. str ip, [r3, #PLLCTL]
  87. /* Go to deep sleep */
  88. ldr ip, [r4]
  89. orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
  90. /* System goes to sleep beyond after this instruction */
  91. str ip, [r4]
  92. /* Wake up from sleep */
  93. /* Clear sleep enable */
  94. ldr ip, [r4]
  95. bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
  96. str ip, [r4]
  97. /* initialize the DDR PLL controller */
  98. /* Put PLL in reset */
  99. ldr ip, [r3, #PLLCTL]
  100. bic ip, ip, #PLLCTL_PLLRST
  101. str ip, [r3, #PLLCTL]
  102. /* Clear PLL power down */
  103. ldr ip, [r3, #PLLCTL]
  104. bic ip, ip, #PLLCTL_PLLPWRDN
  105. str ip, [r3, #PLLCTL]
  106. mov ip, #PLL_RESET_CYCLES
  107. 3: subs ip, ip, #0x1
  108. bne 3b
  109. /* Bring PLL out of reset */
  110. ldr ip, [r3, #PLLCTL]
  111. orr ip, ip, #PLLCTL_PLLRST
  112. str ip, [r3, #PLLCTL]
  113. /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
  114. mov ip, #PLL_LOCK_CYCLES
  115. 4: subs ip, ip, #0x1
  116. bne 4b
  117. /* Remove PLL from bypass mode */
  118. ldr ip, [r3, #PLLCTL]
  119. bic ip, ip, #PLLCTL_PLLENSRC
  120. orr ip, ip, #PLLCTL_PLLEN
  121. str ip, [r3, #PLLCTL]
  122. /* Start 2x clock to DDR2 */
  123. ldr ip, [r3, #PLLDIV1]
  124. orr ip, ip, #PLLDIV_EN
  125. str ip, [r3, #PLLDIV1]
  126. /* Enable VCLK */
  127. /* Enable DDR2 LPSC */
  128. mov r7, r0
  129. mov r0, #0x3
  130. bl davinci_ddr_psc_config
  131. mov r0, r7
  132. /* clear MCLKSTOPEN */
  133. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  134. bic ip, ip, #DDR2_MCLKSTOPEN_BIT
  135. str ip, [r0, #DDR2_SDRCR_OFFSET]
  136. ldr ip, [r0, #DDR2_SDRCR_OFFSET]
  137. bic ip, ip, #DDR2_LPMODEN_BIT
  138. str ip, [r0, #DDR2_SDRCR_OFFSET]
  139. /* Restore registers and return */
  140. ldmfd sp!, {r0-r12, pc}
  141. ENDPROC(davinci_cpu_suspend)
  142. /*
  143. * Disables or Enables DDR2 LPSC
  144. * Register Usage:
  145. * r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
  146. * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
  147. * r2: contains PSC number for DDR2
  148. */
  149. ENTRY(davinci_ddr_psc_config)
  150. /* Set next state in mdctl for DDR2 */
  151. mov r6, #MDCTL
  152. add r6, r6, r2, lsl #2
  153. ldr ip, [r1, r6]
  154. bic ip, ip, #MDSTAT_STATE_MASK
  155. orr ip, ip, r0
  156. str ip, [r1, r6]
  157. /* Enable the Power Domain Transition Command */
  158. ldr ip, [r1, #PTCMD]
  159. orr ip, ip, #0x1
  160. str ip, [r1, #PTCMD]
  161. /* Check for Transition Complete (PTSTAT) */
  162. ptstat_done:
  163. ldr ip, [r1, #PTSTAT]
  164. and ip, ip, #0x1
  165. cmp ip, #0x0
  166. bne ptstat_done
  167. /* Check for DDR2 clock disable completion; */
  168. mov r6, #MDSTAT
  169. add r6, r6, r2, lsl #2
  170. ddr2clk_stop_done:
  171. ldr ip, [r1, r6]
  172. and ip, ip, #MDSTAT_STATE_MASK
  173. cmp ip, r0
  174. bne ddr2clk_stop_done
  175. ret lr
  176. ENDPROC(davinci_ddr_psc_config)
  177. CACHE_FLUSH:
  178. #ifdef CONFIG_CPU_V6
  179. .word v6_flush_kern_cache_all
  180. #else
  181. .word arm926_flush_kern_cache_all
  182. #endif
  183. ENTRY(davinci_cpu_suspend_sz)
  184. .word . - davinci_cpu_suspend
  185. ENDPROC(davinci_cpu_suspend_sz)