start.S 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * Copyright (C) 2005-2008 Atmel Corporation
  3. *
  4. * See file CREDITS for list of people who contributed to this
  5. * project.
  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 as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include <config.h>
  23. #include <asm/ptrace.h>
  24. #include <asm/sysreg.h>
  25. #define SYSREG_MMUCR_I_OFFSET 2
  26. #define SYSREG_MMUCR_S_OFFSET 4
  27. #define SR_INIT (SYSREG_BIT(GM) | SYSREG_BIT(EM) | SYSREG_BIT(M0))
  28. /* due to errata (unreliable branch folding) clear FE bit explicitly */
  29. #define CPUCR_INIT ((SYSREG_BIT(BI) | SYSREG_BIT(BE) \
  30. | SYSREG_BIT(RE) | SYSREG_BIT(IBE) \
  31. | SYSREG_BIT(IEE)) & ~SYSREG_BIT(FE))
  32. /*
  33. * To save some space, we use the same entry point for
  34. * exceptions and reset. This avoids lots of alignment padding
  35. * since the reset vector is always suitably aligned.
  36. */
  37. .section .exception.text, "ax", @progbits
  38. .global _start
  39. .global _evba
  40. .type _start, @function
  41. .type _evba, @function
  42. _start:
  43. .size _start, 0
  44. _evba:
  45. .org 0x00
  46. rjmp unknown_exception /* Unrecoverable exception */
  47. .org 0x04
  48. rjmp unknown_exception /* TLB multiple hit */
  49. .org 0x08
  50. rjmp unknown_exception /* Bus error data fetch */
  51. .org 0x0c
  52. rjmp unknown_exception /* Bus error instruction fetch */
  53. .org 0x10
  54. rjmp unknown_exception /* NMI */
  55. .org 0x14
  56. rjmp unknown_exception /* Instruction address */
  57. .org 0x18
  58. rjmp unknown_exception /* ITLB protection */
  59. .org 0x1c
  60. rjmp unknown_exception /* Breakpoint */
  61. .org 0x20
  62. rjmp unknown_exception /* Illegal opcode */
  63. .org 0x24
  64. rjmp unknown_exception /* Unimplemented instruction */
  65. .org 0x28
  66. rjmp unknown_exception /* Privilege violation */
  67. .org 0x2c
  68. rjmp unknown_exception /* Floating-point */
  69. .org 0x30
  70. rjmp unknown_exception /* Coprocessor absent */
  71. .org 0x34
  72. rjmp unknown_exception /* Data Address (read) */
  73. .org 0x38
  74. rjmp unknown_exception /* Data Address (write) */
  75. .org 0x3c
  76. rjmp unknown_exception /* DTLB Protection (read) */
  77. .org 0x40
  78. rjmp unknown_exception /* DTLB Protection (write) */
  79. .org 0x44
  80. rjmp unknown_exception /* DTLB Modified */
  81. .org 0x50 /* ITLB Miss */
  82. pushm r8-r12,lr
  83. rjmp 1f
  84. .org 0x60 /* DTLB Miss (read) */
  85. pushm r8-r12,lr
  86. rjmp 1f
  87. .org 0x70 /* DTLB Miss (write) */
  88. pushm r8-r12,lr
  89. 1: mov r12, sp
  90. rcall mmu_handle_tlb_miss
  91. popm r8-r12,lr
  92. brne unknown_exception
  93. rete
  94. .size _evba, . - _evba
  95. .align 2
  96. .type unknown_exception, @function
  97. unknown_exception:
  98. /* Figure out whether we're handling an exception (Exception
  99. * mode) or just booting (Supervisor mode). */
  100. csrfcz SYSREG_M1_OFFSET
  101. brcc at32ap_cpu_bootstrap
  102. /* This is an exception. Complain. */
  103. pushm r0-r12
  104. sub r8, sp, REG_R12 - REG_R0 - 4
  105. mov r9, lr
  106. mfsr r10, SYSREG_RAR_EX
  107. mfsr r11, SYSREG_RSR_EX
  108. pushm r8-r11
  109. mfsr r12, SYSREG_ECR
  110. mov r11, sp
  111. rcall do_unknown_exception
  112. 1: rjmp 1b
  113. /* The COUNT/COMPARE timer interrupt handler */
  114. .global timer_interrupt_handler
  115. .type timer_interrupt_handler,@function
  116. .align 2
  117. timer_interrupt_handler:
  118. /*
  119. * Increment timer_overflow and re-write COMPARE with 0xffffffff.
  120. *
  121. * We're running at interrupt level 3, so we don't need to save
  122. * r8-r12 or lr to the stack.
  123. */
  124. lda.w r8, timer_overflow
  125. ld.w r9, r8[0]
  126. mov r10, -1
  127. mtsr SYSREG_COMPARE, r10
  128. sub r9, -1
  129. st.w r8[0], r9
  130. rete
  131. /*
  132. * CPU bootstrap after reset is handled here. SoC code may
  133. * override this in case they need to initialize oscillators,
  134. * etc.
  135. */
  136. .section .text.at32ap_cpu_bootstrap, "ax", @progbits
  137. .global at32ap_cpu_bootstrap
  138. .weak at32ap_cpu_bootstrap
  139. .type at32ap_cpu_bootstrap, @function
  140. .align 2
  141. at32ap_cpu_bootstrap:
  142. /* Reset the Status Register */
  143. mov r0, lo(SR_INIT)
  144. orh r0, hi(SR_INIT)
  145. mtsr SYSREG_SR, r0
  146. /* Reset CPUCR and invalidate the BTB */
  147. mov r2, CPUCR_INIT
  148. mtsr SYSREG_CPUCR, r2
  149. /* Flush the caches */
  150. mov r1, 0
  151. cache r1[4], 8
  152. cache r1[0], 0
  153. sync 0
  154. /* Reset the MMU to default settings */
  155. mov r0, SYSREG_BIT(MMUCR_S) | SYSREG_BIT(MMUCR_I)
  156. mtsr SYSREG_MMUCR, r0
  157. /* Internal RAM should not need any initialization. We might
  158. have to initialize external RAM here if the part doesn't
  159. have internal RAM (or we may use the data cache) */
  160. /* Jump to cacheable segment */
  161. lddpc pc, 1f
  162. .align 2
  163. 1: .long at32ap_low_level_init
  164. .size _start, . - _start
  165. /* Common CPU bootstrap code after oscillator/cache/etc. init */
  166. .section .text.avr32ap_low_level_init, "ax", @progbits
  167. .global at32ap_low_level_init
  168. .type at32ap_low_level_init, @function
  169. .align 2
  170. at32ap_low_level_init:
  171. lddpc sp, sp_init
  172. /* Initialize the GOT pointer */
  173. lddpc r6, got_init
  174. 3: rsub r6, pc
  175. /* Let's go */
  176. rjmp board_init_f
  177. .align 2
  178. .type sp_init,@object
  179. sp_init:
  180. .long CONFIG_SYS_INIT_SP_ADDR
  181. got_init:
  182. .long 3b - _GLOBAL_OFFSET_TABLE_
  183. /*
  184. * void relocate_code(new_sp, new_gd, monitor_addr)
  185. *
  186. * Relocate the u-boot image into RAM and continue from there.
  187. * Does not return.
  188. */
  189. .section .text.relocate_code,"ax",@progbits
  190. .global relocate_code
  191. .type relocate_code,@function
  192. relocate_code:
  193. mov sp, r12 /* use new stack */
  194. mov r12, r11 /* save new_gd */
  195. mov r11, r10 /* save destination address */
  196. /* copy .text section and flush the cache along the way */
  197. lda.w r8, _text
  198. lda.w r9, _etext
  199. sub lr, r10, r8 /* relocation offset */
  200. 1: ldm r8++, r0-r3
  201. stm r10, r0-r3
  202. sub r10, -16
  203. ldm r8++, r0-r3
  204. stm r10, r0-r3
  205. sub r10, -16
  206. cp.w r8, r9
  207. cache r10[-4], 0x0d /* dcache clean/invalidate */
  208. cache r10[-4], 0x01 /* icache invalidate */
  209. brlt 1b
  210. /* flush write buffer */
  211. sync 0
  212. /* copy data sections */
  213. lda.w r9, _edata
  214. 1: ld.d r0, r8++
  215. st.d r10++, r0
  216. cp.w r8, r9
  217. brlt 1b
  218. /* zero out .bss */
  219. mov r0, 0
  220. mov r1, 0
  221. lda.w r9, _end
  222. sub r9, r8
  223. 1: st.d r10++, r0
  224. sub r9, 8
  225. brgt 1b
  226. /* jump to RAM */
  227. sub r0, pc, . - in_ram
  228. add pc, r0, lr
  229. .align 2
  230. in_ram:
  231. /* find the new GOT and relocate it */
  232. lddpc r6, got_init_reloc
  233. 3: rsub r6, pc
  234. mov r8, r6
  235. lda.w r9, _egot
  236. lda.w r10, _got
  237. sub r9, r10
  238. 1: ld.w r0, r8[0]
  239. add r0, lr
  240. st.w r8++, r0
  241. sub r9, 4
  242. brgt 1b
  243. /* Move the exception handlers */
  244. mfsr r2, SYSREG_EVBA
  245. add r2, lr
  246. mtsr SYSREG_EVBA, r2
  247. /* Do the rest of the initialization sequence */
  248. call board_init_r
  249. .align 2
  250. got_init_reloc:
  251. .long 3b - _GLOBAL_OFFSET_TABLE_
  252. .size relocate_code, . - relocate_code