pm_slowclock.S 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * arch/arm/mach-at91/pm_slow_clock.S
  3. *
  4. * Copyright (C) 2006 Savin Zlobec
  5. *
  6. * AT91SAM9 support:
  7. * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. *
  13. */
  14. #include <linux/linkage.h>
  15. #include <mach/hardware.h>
  16. #include <mach/at91_pmc.h>
  17. #ifdef CONFIG_ARCH_AT91RM9200
  18. #include <mach/at91rm9200_mc.h>
  19. #elif defined(CONFIG_ARCH_AT91CAP9)
  20. #include <mach/at91cap9_ddrsdr.h>
  21. #else
  22. #include <mach/at91sam9_sdramc.h>
  23. #endif
  24. #ifdef CONFIG_ARCH_AT91SAM9263
  25. /*
  26. * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
  27. * handle those cases both here and in the Suspend-To-RAM support.
  28. */
  29. #define AT91_SDRAMC AT91_SDRAMC0
  30. #warning Assuming EB1 SDRAM controller is *NOT* used
  31. #endif
  32. /*
  33. * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
  34. * clock during suspend by adjusting its prescalar and divisor.
  35. * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
  36. * are errata regarding adjusting the prescalar and divisor.
  37. */
  38. #undef SLOWDOWN_MASTER_CLOCK
  39. #define MCKRDY_TIMEOUT 1000
  40. #define MOSCRDY_TIMEOUT 1000
  41. #define PLLALOCK_TIMEOUT 1000
  42. #define PLLBLOCK_TIMEOUT 1000
  43. /*
  44. * Wait until master clock is ready (after switching master clock source)
  45. */
  46. .macro wait_mckrdy
  47. mov r4, #MCKRDY_TIMEOUT
  48. 1: sub r4, r4, #1
  49. cmp r4, #0
  50. beq 2f
  51. ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
  52. tst r3, #AT91_PMC_MCKRDY
  53. beq 1b
  54. 2:
  55. .endm
  56. /*
  57. * Wait until master oscillator has stabilized.
  58. */
  59. .macro wait_moscrdy
  60. mov r4, #MOSCRDY_TIMEOUT
  61. 1: sub r4, r4, #1
  62. cmp r4, #0
  63. beq 2f
  64. ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
  65. tst r3, #AT91_PMC_MOSCS
  66. beq 1b
  67. 2:
  68. .endm
  69. /*
  70. * Wait until PLLA has locked.
  71. */
  72. .macro wait_pllalock
  73. mov r4, #PLLALOCK_TIMEOUT
  74. 1: sub r4, r4, #1
  75. cmp r4, #0
  76. beq 2f
  77. ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
  78. tst r3, #AT91_PMC_LOCKA
  79. beq 1b
  80. 2:
  81. .endm
  82. /*
  83. * Wait until PLLB has locked.
  84. */
  85. .macro wait_pllblock
  86. mov r4, #PLLBLOCK_TIMEOUT
  87. 1: sub r4, r4, #1
  88. cmp r4, #0
  89. beq 2f
  90. ldr r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
  91. tst r3, #AT91_PMC_LOCKB
  92. beq 1b
  93. 2:
  94. .endm
  95. .text
  96. ENTRY(at91_slow_clock)
  97. /* Save registers on stack */
  98. stmfd sp!, {r0 - r12, lr}
  99. /*
  100. * Register usage:
  101. * R1 = Base address of AT91_PMC
  102. * R2 = Base address of AT91_SDRAMC (or AT91_SYS on AT91RM9200)
  103. * R3 = temporary register
  104. * R4 = temporary register
  105. */
  106. ldr r1, .at91_va_base_pmc
  107. ldr r2, .at91_va_base_sdramc
  108. /* Drain write buffer */
  109. mcr p15, 0, r0, c7, c10, 4
  110. #ifdef CONFIG_ARCH_AT91RM9200
  111. /* Put SDRAM in self-refresh mode */
  112. mov r3, #1
  113. str r3, [r2, #AT91_SDRAMC_SRR]
  114. #elif defined(CONFIG_ARCH_AT91CAP9)
  115. /* Enable SDRAM self-refresh mode */
  116. ldr r3, [r2, #AT91_DDRSDRC_LPR - AT91_DDRSDRC]
  117. str r3, .saved_sam9_lpr
  118. mov r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
  119. str r3, [r2, #AT91_DDRSDRC_LPR - AT91_DDRSDRC]
  120. #else
  121. /* Enable SDRAM self-refresh mode */
  122. ldr r3, [r2, #AT91_SDRAMC_LPR - AT91_SDRAMC]
  123. str r3, .saved_sam9_lpr
  124. mov r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
  125. str r3, [r2, #AT91_SDRAMC_LPR - AT91_SDRAMC]
  126. #endif
  127. /* Save Master clock setting */
  128. ldr r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
  129. str r3, .saved_mckr
  130. /*
  131. * Set the Master clock source to slow clock
  132. */
  133. bic r3, r3, #AT91_PMC_CSS
  134. str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
  135. wait_mckrdy
  136. #ifdef SLOWDOWN_MASTER_CLOCK
  137. /*
  138. * Set the Master Clock PRES and MDIV fields.
  139. *
  140. * See AT91RM9200 errata #27 and #28 for details.
  141. */
  142. mov r3, #0
  143. str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
  144. wait_mckrdy
  145. #endif
  146. /* Save PLLA setting and disable it */
  147. ldr r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
  148. str r3, .saved_pllar
  149. mov r3, #AT91_PMC_PLLCOUNT
  150. orr r3, r3, #(1 << 29) /* bit 29 always set */
  151. str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
  152. wait_pllalock
  153. /* Save PLLB setting and disable it */
  154. ldr r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
  155. str r3, .saved_pllbr
  156. mov r3, #AT91_PMC_PLLCOUNT
  157. str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
  158. wait_pllblock
  159. /* Turn off the main oscillator */
  160. ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
  161. bic r3, r3, #AT91_PMC_MOSCEN
  162. str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
  163. /* Wait for interrupt */
  164. mcr p15, 0, r0, c7, c0, 4
  165. /* Turn on the main oscillator */
  166. ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
  167. orr r3, r3, #AT91_PMC_MOSCEN
  168. str r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
  169. wait_moscrdy
  170. /* Restore PLLB setting */
  171. ldr r3, .saved_pllbr
  172. str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
  173. tst r3, #(AT91_PMC_MUL & 0xff0000)
  174. bne 1f
  175. tst r3, #(AT91_PMC_MUL & ~0xff0000)
  176. beq 2f
  177. 1:
  178. wait_pllblock
  179. 2:
  180. /* Restore PLLA setting */
  181. ldr r3, .saved_pllar
  182. str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
  183. tst r3, #(AT91_PMC_MUL & 0xff0000)
  184. bne 3f
  185. tst r3, #(AT91_PMC_MUL & ~0xff0000)
  186. beq 4f
  187. 3:
  188. wait_pllalock
  189. 4:
  190. #ifdef SLOWDOWN_MASTER_CLOCK
  191. /*
  192. * First set PRES if it was not 0,
  193. * than set CSS and MDIV fields.
  194. *
  195. * See AT91RM9200 errata #27 and #28 for details.
  196. */
  197. ldr r3, .saved_mckr
  198. tst r3, #AT91_PMC_PRES
  199. beq 2f
  200. and r3, r3, #AT91_PMC_PRES
  201. str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
  202. wait_mckrdy
  203. #endif
  204. /*
  205. * Restore master clock setting
  206. */
  207. 2: ldr r3, .saved_mckr
  208. str r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
  209. wait_mckrdy
  210. #ifdef CONFIG_ARCH_AT91RM9200
  211. /* Do nothing - self-refresh is automatically disabled. */
  212. #elif defined(CONFIG_ARCH_AT91CAP9)
  213. /* Restore LPR on AT91CAP9 */
  214. ldr r3, .saved_sam9_lpr
  215. str r3, [r2, #AT91_DDRSDRC_LPR - AT91_DDRSDRC]
  216. #else
  217. /* Restore LPR on AT91SAM9 */
  218. ldr r3, .saved_sam9_lpr
  219. str r3, [r2, #AT91_SDRAMC_LPR - AT91_SDRAMC]
  220. #endif
  221. /* Restore registers, and return */
  222. ldmfd sp!, {r0 - r12, pc}
  223. .saved_mckr:
  224. .word 0
  225. .saved_pllar:
  226. .word 0
  227. .saved_pllbr:
  228. .word 0
  229. .saved_sam9_lpr:
  230. .word 0
  231. .at91_va_base_pmc:
  232. .word AT91_VA_BASE_SYS + AT91_PMC
  233. #ifdef CONFIG_ARCH_AT91RM9200
  234. .at91_va_base_sdramc:
  235. .word AT91_VA_BASE_SYS
  236. #elif defined(CONFIG_ARCH_AT91CAP9)
  237. .at91_va_base_sdramc:
  238. .word AT91_VA_BASE_SYS + AT91_DDRSDRC
  239. #else
  240. .at91_va_base_sdramc:
  241. .word AT91_VA_BASE_SYS + AT91_SDRAMC
  242. #endif
  243. ENTRY(at91_slow_clock_sz)
  244. .word .-at91_slow_clock