start.S 6.0 KB

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