start.S 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * armboot - Startup Code for OMP2420/ARM1136 CPU-core
  3. *
  4. * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
  5. *
  6. * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
  7. * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
  8. * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
  9. * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
  10. * Copyright (c) 2003 Kshitij <kshitij@ti.com>
  11. *
  12. * SPDX-License-Identifier: GPL-2.0+
  13. */
  14. #include <asm-offsets.h>
  15. #include <config.h>
  16. #include <version.h>
  17. .globl _start
  18. _start: b reset
  19. #ifdef CONFIG_SPL_BUILD
  20. ldr pc, _hang
  21. ldr pc, _hang
  22. ldr pc, _hang
  23. ldr pc, _hang
  24. ldr pc, _hang
  25. ldr pc, _hang
  26. ldr pc, _hang
  27. _hang:
  28. .word do_hang
  29. .word 0x12345678
  30. .word 0x12345678
  31. .word 0x12345678
  32. .word 0x12345678
  33. .word 0x12345678
  34. .word 0x12345678
  35. .word 0x12345678 /* now 16*4=64 */
  36. #else
  37. ldr pc, _undefined_instruction
  38. ldr pc, _software_interrupt
  39. ldr pc, _prefetch_abort
  40. ldr pc, _data_abort
  41. ldr pc, _not_used
  42. ldr pc, _irq
  43. ldr pc, _fiq
  44. _undefined_instruction: .word undefined_instruction
  45. _software_interrupt: .word software_interrupt
  46. _prefetch_abort: .word prefetch_abort
  47. _data_abort: .word data_abort
  48. _not_used: .word not_used
  49. _irq: .word irq
  50. _fiq: .word fiq
  51. _pad: .word 0x12345678 /* now 16*4=64 */
  52. #endif /* CONFIG_SPL_BUILD */
  53. .global _end_vect
  54. _end_vect:
  55. .balignl 16,0xdeadbeef
  56. /*
  57. *************************************************************************
  58. *
  59. * Startup Code (reset vector)
  60. *
  61. * do important init only if we don't start from memory!
  62. * setup Memory and board specific bits prior to relocation.
  63. * relocate armboot to ram
  64. * setup stack
  65. *
  66. *************************************************************************
  67. */
  68. #ifdef CONFIG_USE_IRQ
  69. /* IRQ stack memory (calculated at run-time) */
  70. .globl IRQ_STACK_START
  71. IRQ_STACK_START:
  72. .word 0x0badc0de
  73. /* IRQ stack memory (calculated at run-time) */
  74. .globl FIQ_STACK_START
  75. FIQ_STACK_START:
  76. .word 0x0badc0de
  77. #endif
  78. /* IRQ stack memory (calculated at run-time) + 8 bytes */
  79. .globl IRQ_STACK_START_IN
  80. IRQ_STACK_START_IN:
  81. .word 0x0badc0de
  82. /*
  83. * the actual reset code
  84. */
  85. reset:
  86. /*
  87. * set the cpu to SVC32 mode
  88. */
  89. mrs r0,cpsr
  90. bic r0,r0,#0x1f
  91. orr r0,r0,#0xd3
  92. msr cpsr,r0
  93. /* the mask ROM code should have PLL and others stable */
  94. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  95. bl cpu_init_crit
  96. #endif
  97. bl _main
  98. /*------------------------------------------------------------------------------*/
  99. .globl c_runtime_cpu_setup
  100. c_runtime_cpu_setup:
  101. bx lr
  102. /*
  103. *************************************************************************
  104. *
  105. * CPU_init_critical registers
  106. *
  107. * setup important registers
  108. * setup memory timing
  109. *
  110. *************************************************************************
  111. */
  112. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  113. cpu_init_crit:
  114. /*
  115. * flush v4 I/D caches
  116. */
  117. mov r0, #0
  118. mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */
  119. mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */
  120. /*
  121. * disable MMU stuff and caches
  122. */
  123. mrc p15, 0, r0, c1, c0, 0
  124. bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
  125. bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
  126. orr r0, r0, #0x00000002 @ set bit 2 (A) Align
  127. orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
  128. mcr p15, 0, r0, c1, c0, 0
  129. /*
  130. * Jump to board specific initialization... The Mask ROM will have already initialized
  131. * basic memory. Go here to bump up clock rate and handle wake up conditions.
  132. */
  133. mov ip, lr /* persevere link reg across call */
  134. bl lowlevel_init /* go setup pll,mux,memory */
  135. mov lr, ip /* restore link */
  136. mov pc, lr /* back to my caller */
  137. #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
  138. #ifndef CONFIG_SPL_BUILD
  139. /*
  140. *************************************************************************
  141. *
  142. * Interrupt handling
  143. *
  144. *************************************************************************
  145. */
  146. @
  147. @ IRQ stack frame.
  148. @
  149. #define S_FRAME_SIZE 72
  150. #define S_OLD_R0 68
  151. #define S_PSR 64
  152. #define S_PC 60
  153. #define S_LR 56
  154. #define S_SP 52
  155. #define S_IP 48
  156. #define S_FP 44
  157. #define S_R10 40
  158. #define S_R9 36
  159. #define S_R8 32
  160. #define S_R7 28
  161. #define S_R6 24
  162. #define S_R5 20
  163. #define S_R4 16
  164. #define S_R3 12
  165. #define S_R2 8
  166. #define S_R1 4
  167. #define S_R0 0
  168. #define MODE_SVC 0x13
  169. #define I_BIT 0x80
  170. /*
  171. * use bad_save_user_regs for abort/prefetch/undef/swi ...
  172. * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
  173. */
  174. .macro bad_save_user_regs
  175. sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack
  176. stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
  177. ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort stack
  178. ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs)
  179. add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
  180. add r5, sp, #S_SP
  181. mov r1, lr
  182. stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
  183. mov r0, sp @ save current stack into r0 (param register)
  184. .endm
  185. .macro irq_save_user_regs
  186. sub sp, sp, #S_FRAME_SIZE
  187. stmia sp, {r0 - r12} @ Calling r0-r12
  188. add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
  189. stmdb r8, {sp, lr}^ @ Calling SP, LR
  190. str lr, [r8, #0] @ Save calling PC
  191. mrs r6, spsr
  192. str r6, [r8, #4] @ Save CPSR
  193. str r0, [r8, #8] @ Save OLD_R0
  194. mov r0, sp
  195. .endm
  196. .macro irq_restore_user_regs
  197. ldmia sp, {r0 - lr}^ @ Calling r0 - lr
  198. mov r0, r0
  199. ldr lr, [sp, #S_PC] @ Get PC
  200. add sp, sp, #S_FRAME_SIZE
  201. subs pc, lr, #4 @ return & move spsr_svc into cpsr
  202. .endm
  203. .macro get_bad_stack
  204. ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode)
  205. str lr, [r13] @ save caller lr in position 0 of saved stack
  206. mrs lr, spsr @ get the spsr
  207. str lr, [r13, #4] @ save spsr in position 1 of saved stack
  208. mov r13, #MODE_SVC @ prepare SVC-Mode
  209. @ msr spsr_c, r13
  210. msr spsr, r13 @ switch modes, make sure moves will execute
  211. mov lr, pc @ capture return pc
  212. movs pc, lr @ jump to next instruction & switch modes.
  213. .endm
  214. .macro get_bad_stack_swi
  215. sub r13, r13, #4 @ space on current stack for scratch reg.
  216. str r0, [r13] @ save R0's value.
  217. ldr r0, IRQ_STACK_START_IN @ get data regions start
  218. str lr, [r0] @ save caller lr in position 0 of saved stack
  219. mrs lr, spsr @ get the spsr
  220. str lr, [r0, #4] @ save spsr in position 1 of saved stack
  221. ldr lr, [r0] @ restore lr
  222. ldr r0, [r13] @ restore r0
  223. add r13, r13, #4 @ pop stack entry
  224. .endm
  225. .macro get_irq_stack @ setup IRQ stack
  226. ldr sp, IRQ_STACK_START
  227. .endm
  228. .macro get_fiq_stack @ setup FIQ stack
  229. ldr sp, FIQ_STACK_START
  230. .endm
  231. #endif /* CONFIG_SPL_BUILD */
  232. /*
  233. * exception handlers
  234. */
  235. #ifdef CONFIG_SPL_BUILD
  236. .align 5
  237. do_hang:
  238. bl hang /* hang and never return */
  239. #else /* !CONFIG_SPL_BUILD */
  240. .align 5
  241. undefined_instruction:
  242. get_bad_stack
  243. bad_save_user_regs
  244. bl do_undefined_instruction
  245. .align 5
  246. software_interrupt:
  247. get_bad_stack_swi
  248. bad_save_user_regs
  249. bl do_software_interrupt
  250. .align 5
  251. prefetch_abort:
  252. get_bad_stack
  253. bad_save_user_regs
  254. bl do_prefetch_abort
  255. .align 5
  256. data_abort:
  257. get_bad_stack
  258. bad_save_user_regs
  259. bl do_data_abort
  260. .align 5
  261. not_used:
  262. get_bad_stack
  263. bad_save_user_regs
  264. bl do_not_used
  265. #ifdef CONFIG_USE_IRQ
  266. .align 5
  267. irq:
  268. get_irq_stack
  269. irq_save_user_regs
  270. bl do_irq
  271. irq_restore_user_regs
  272. .align 5
  273. fiq:
  274. get_fiq_stack
  275. /* someone ought to write a more effiction fiq_save_user_regs */
  276. irq_save_user_regs
  277. bl do_fiq
  278. irq_restore_user_regs
  279. #else
  280. .align 5
  281. irq:
  282. get_bad_stack
  283. bad_save_user_regs
  284. bl do_irq
  285. .align 5
  286. fiq:
  287. get_bad_stack
  288. bad_save_user_regs
  289. bl do_fiq
  290. #endif
  291. .align 5
  292. .global arm1136_cache_flush
  293. arm1136_cache_flush:
  294. #if !defined(CONFIG_SYS_ICACHE_OFF)
  295. mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache
  296. #endif
  297. #if !defined(CONFIG_SYS_DCACHE_OFF)
  298. mcr p15, 0, r1, c7, c14, 0 @ invalidate D cache
  299. #endif
  300. mov pc, lr @ back to caller
  301. #endif /* CONFIG_SPL_BUILD */