sleep.S 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * SA11x0 Assembler Sleep/WakeUp Management Routines
  3. *
  4. * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License.
  8. *
  9. * History:
  10. *
  11. * 2001-02-06: Cliff Brake Initial code
  12. *
  13. * 2001-08-29: Nicolas Pitre Simplified.
  14. *
  15. * 2002-05-27: Nicolas Pitre Revisited, more cleanup and simplification.
  16. * Storage is on the stack now.
  17. */
  18. #include <linux/linkage.h>
  19. #include <asm/assembler.h>
  20. #include <mach/hardware.h>
  21. .text
  22. /*
  23. * sa1100_cpu_suspend()
  24. *
  25. * Causes sa11x0 to enter sleep state
  26. *
  27. */
  28. ENTRY(sa1100_cpu_suspend)
  29. stmfd sp!, {r4 - r12, lr} @ save registers on stack
  30. mov r1, r0
  31. ldr r3, =sa1100_cpu_resume @ return function
  32. bl cpu_suspend
  33. @ disable clock switching
  34. mcr p15, 0, r1, c15, c2, 2
  35. @ Adjust memory timing before lowering CPU clock
  36. @ Clock speed adjustment without changing memory timing makes
  37. @ CPU hang in some cases
  38. ldr r0, =MDREFR
  39. ldr r1, [r0]
  40. orr r1, r1, #MDREFR_K1DB2
  41. str r1, [r0]
  42. @ delay 90us and set CPU PLL to lowest speed
  43. @ fixes resume problem on high speed SA1110
  44. mov r0, #90
  45. bl __udelay
  46. ldr r0, =PPCR
  47. mov r1, #0
  48. str r1, [r0]
  49. mov r0, #90
  50. bl __udelay
  51. /*
  52. * SA1110 SDRAM controller workaround. register values:
  53. *
  54. * r0 = &MSC0
  55. * r1 = &MSC1
  56. * r2 = &MSC2
  57. * r3 = MSC0 value
  58. * r4 = MSC1 value
  59. * r5 = MSC2 value
  60. * r6 = &MDREFR
  61. * r7 = first MDREFR value
  62. * r8 = second MDREFR value
  63. * r9 = &MDCNFG
  64. * r10 = MDCNFG value
  65. * r11 = third MDREFR value
  66. * r12 = &PMCR
  67. * r13 = PMCR value (1)
  68. */
  69. ldr r0, =MSC0
  70. ldr r1, =MSC1
  71. ldr r2, =MSC2
  72. ldr r3, [r0]
  73. bic r3, r3, #FMsk(MSC_RT)
  74. bic r3, r3, #FMsk(MSC_RT)<<16
  75. ldr r4, [r1]
  76. bic r4, r4, #FMsk(MSC_RT)
  77. bic r4, r4, #FMsk(MSC_RT)<<16
  78. ldr r5, [r2]
  79. bic r5, r5, #FMsk(MSC_RT)
  80. bic r5, r5, #FMsk(MSC_RT)<<16
  81. ldr r6, =MDREFR
  82. ldr r7, [r6]
  83. bic r7, r7, #0x0000FF00
  84. bic r7, r7, #0x000000F0
  85. orr r8, r7, #MDREFR_SLFRSH
  86. ldr r9, =MDCNFG
  87. ldr r10, [r9]
  88. bic r10, r10, #(MDCNFG_DE0+MDCNFG_DE1)
  89. bic r10, r10, #(MDCNFG_DE2+MDCNFG_DE3)
  90. bic r11, r8, #MDREFR_SLFRSH
  91. bic r11, r11, #MDREFR_E1PIN
  92. ldr r12, =PMCR
  93. mov r13, #PMCR_SF
  94. b sa1110_sdram_controller_fix
  95. .align 5
  96. sa1110_sdram_controller_fix:
  97. @ Step 1 clear RT field of all MSCx registers
  98. str r3, [r0]
  99. str r4, [r1]
  100. str r5, [r2]
  101. @ Step 2 clear DRI field in MDREFR
  102. str r7, [r6]
  103. @ Step 3 set SLFRSH bit in MDREFR
  104. str r8, [r6]
  105. @ Step 4 clear DE bis in MDCNFG
  106. str r10, [r9]
  107. @ Step 5 clear DRAM refresh control register
  108. str r11, [r6]
  109. @ Wow, now the hardware suspend request pins can be used, that makes them functional for
  110. @ about 7 ns out of the entire time that the CPU is running!
  111. @ Step 6 set force sleep bit in PMCR
  112. str r13, [r12]
  113. 20: b 20b @ loop waiting for sleep
  114. /*
  115. * cpu_sa1100_resume()
  116. *
  117. * entry point from bootloader into kernel during resume
  118. */
  119. .align 5
  120. sa1100_cpu_resume:
  121. mcr p15, 0, r1, c15, c1, 2 @ enable clock switching
  122. ldmfd sp!, {r4 - r12, pc} @ return to caller