start.S 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * (C) Copyright 2007 Michal Simek
  3. * (C) Copyright 2004 Atmark Techno, Inc.
  4. *
  5. * Michal SIMEK <monstr@monstr.eu>
  6. * Yasushi SHOJI <yashi@atmark-techno.com>
  7. *
  8. * SPDX-License-Identifier: GPL-2.0+
  9. */
  10. #include <asm-offsets.h>
  11. #include <config.h>
  12. .text
  13. .global _start
  14. _start:
  15. /*
  16. * reserve registers:
  17. * r10: Stores little/big endian offset for vectors
  18. * r2: Stores imm opcode
  19. * r3: Stores brai opcode
  20. */
  21. mts rmsr, r0 /* disable cache */
  22. addi r8, r0, __end
  23. mts rslr, r8
  24. /* TODO: Redo this code to call board_init_f_*() */
  25. #if defined(CONFIG_SPL_BUILD)
  26. addi r1, r0, CONFIG_SPL_STACK_ADDR
  27. mts rshr, r1
  28. addi r1, r1, -4 /* Decrement SP to top of memory */
  29. #else
  30. #if defined(CONFIG_SYS_MALLOC_F_LEN)
  31. addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
  32. #else
  33. addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
  34. #endif
  35. mts rshr, r1
  36. addi r1, r1, -4 /* Decrement SP to top of memory */
  37. /* Find-out if u-boot is running on BIG/LITTLE endian platform
  38. * There are some steps which is necessary to keep in mind:
  39. * 1. Setup offset value to r6
  40. * 2. Store word offset value to address 0x0
  41. * 3. Load just byte from address 0x0
  42. * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
  43. * value that's why is on address 0x0
  44. * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
  45. */
  46. addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
  47. lwi r7, r0, 0x28
  48. swi r6, r0, 0x28 /* used first unused MB vector */
  49. lbui r10, r0, 0x28 /* used first unused MB vector */
  50. swi r7, r0, 0x28
  51. /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
  52. addi r2, r0, 0xb0000000 /* hex b000 opcode imm */
  53. addi r3, r0, 0xb8080000 /* hew b808 opcode brai */
  54. #ifdef CONFIG_SYS_RESET_ADDRESS
  55. /* reset address */
  56. swi r2, r0, 0x0 /* reset address - imm opcode */
  57. swi r3, r0, 0x4 /* reset address - brai opcode */
  58. addik r6, r0, CONFIG_SYS_RESET_ADDRESS
  59. sw r6, r1, r0
  60. lhu r7, r1, r10
  61. rsubi r8, r10, 0x2
  62. sh r7, r0, r8
  63. rsubi r8, r10, 0x6
  64. sh r6, r0, r8
  65. #endif
  66. #ifdef CONFIG_SYS_USR_EXCEP
  67. /* user_vector_exception */
  68. swi r2, r0, 0x8 /* user vector exception - imm opcode */
  69. swi r3, r0, 0xC /* user vector exception - brai opcode */
  70. addik r6, r0, _exception_handler
  71. sw r6, r1, r0
  72. /*
  73. * BIG ENDIAN memory map for user exception
  74. * 0x8: 0xB000XXXX
  75. * 0xC: 0xB808XXXX
  76. *
  77. * then it is necessary to count address for storing the most significant
  78. * 16bits from _exception_handler address and copy it to
  79. * 0xa address. Big endian use offset in r10=0 that's why is it just
  80. * 0xa address. The same is done for the least significant 16 bits
  81. * for 0xe address.
  82. *
  83. * LITTLE ENDIAN memory map for user exception
  84. * 0x8: 0xXXXX00B0
  85. * 0xC: 0xXXXX08B8
  86. *
  87. * Offset is for little endian setup to 0x2. rsubi instruction decrease
  88. * address value to ensure that points to proper place which is
  89. * 0x8 for the most significant 16 bits and
  90. * 0xC for the least significant 16 bits
  91. */
  92. lhu r7, r1, r10
  93. rsubi r8, r10, 0xa
  94. sh r7, r0, r8
  95. rsubi r8, r10, 0xe
  96. sh r6, r0, r8
  97. #endif
  98. /* interrupt_handler */
  99. swi r2, r0, 0x10 /* interrupt - imm opcode */
  100. swi r3, r0, 0x14 /* interrupt - brai opcode */
  101. addik r6, r0, _interrupt_handler
  102. sw r6, r1, r0
  103. lhu r7, r1, r10
  104. rsubi r8, r10, 0x12
  105. sh r7, r0, r8
  106. rsubi r8, r10, 0x16
  107. sh r6, r0, r8
  108. /* hardware exception */
  109. swi r2, r0, 0x20 /* hardware exception - imm opcode */
  110. swi r3, r0, 0x24 /* hardware exception - brai opcode */
  111. addik r6, r0, _hw_exception_handler
  112. sw r6, r1, r0
  113. lhu r7, r1, r10
  114. rsubi r8, r10, 0x22
  115. sh r7, r0, r8
  116. rsubi r8, r10, 0x26
  117. sh r6, r0, r8
  118. #endif /* BUILD_SPL */
  119. /* Flush cache before enable cache */
  120. addik r5, r0, 0
  121. addik r6, r0, XILINX_DCACHE_BYTE_SIZE
  122. bralid r15, flush_cache
  123. nop
  124. /* enable instruction and data cache */
  125. mfs r12, rmsr
  126. ori r12, r12, 0x1a0
  127. mts rmsr, r12
  128. /* TODO: Redo this code to call board_init_f_*() */
  129. clear_bss:
  130. /* clear BSS segments */
  131. addi r5, r0, __bss_start
  132. addi r4, r0, __bss_end
  133. cmp r6, r5, r4
  134. beqi r6, 3f
  135. 2:
  136. swi r0, r5, 0 /* write zero to loc */
  137. addi r5, r5, 4 /* increment to next loc */
  138. cmp r6, r5, r4 /* check if we have reach the end */
  139. bnei r6, 2b
  140. 3: /* jumping to board_init */
  141. #ifdef CONFIG_DEBUG_UART
  142. bralid r15, debug_uart_init
  143. nop
  144. #endif
  145. #ifndef CONFIG_SPL_BUILD
  146. or r5, r0, r0 /* flags - empty */
  147. addi r31, r0, _gd
  148. #if defined(CONFIG_SYS_MALLOC_F_LEN)
  149. addi r6, r0, CONFIG_SYS_INIT_SP_OFFSET
  150. swi r6, r31, GD_MALLOC_BASE
  151. #endif
  152. brai board_init_f
  153. #else
  154. addi r31, r0, _gd
  155. #if defined(CONFIG_SYS_MALLOC_F_LEN)
  156. addi r6, r0, CONFIG_SPL_STACK_ADDR
  157. swi r6, r31, GD_MALLOC_BASE
  158. #endif
  159. brai board_init_r
  160. #endif
  161. 1: bri 1b
  162. .section .bss
  163. .align 4
  164. _gd:
  165. .space GENERATED_GBL_DATA_SIZE
  166. #ifndef CONFIG_SPL_BUILD
  167. /*
  168. * Read 16bit little endian
  169. */
  170. .text
  171. .global in16
  172. .ent in16
  173. .align 2
  174. in16: lhu r3, r0, r5
  175. bslli r4, r3, 8
  176. bsrli r3, r3, 8
  177. andi r4, r4, 0xffff
  178. or r3, r3, r4
  179. rtsd r15, 8
  180. sext16 r3, r3
  181. .end in16
  182. /*
  183. * Write 16bit little endian
  184. * first parameter(r5) - address, second(r6) - short value
  185. */
  186. .text
  187. .global out16
  188. .ent out16
  189. .align 2
  190. out16: bslli r3, r6, 8
  191. bsrli r6, r6, 8
  192. andi r3, r3, 0xffff
  193. or r3, r3, r6
  194. sh r3, r0, r5
  195. rtsd r15, 8
  196. or r0, r0, r0
  197. .end out16
  198. /*
  199. * Relocate u-boot
  200. */
  201. .text
  202. .global relocate_code
  203. .ent relocate_code
  204. .align 2
  205. relocate_code:
  206. /*
  207. * r5 - start_addr_sp
  208. * r6 - new_gd
  209. * r7 - reloc_addr
  210. */
  211. addi r1, r5, 0 /* Start to use new SP */
  212. addi r31, r6, 0 /* Start to use new GD */
  213. add r23, r0, r7 /* Move reloc addr to r23 */
  214. /* Relocate text and data - r12 temp value */
  215. addi r21, r0, _start
  216. addi r22, r0, __end - 4 /* Include BSS too */
  217. rsub r6, r21, r22
  218. or r5, r0, r0
  219. 1: lw r12, r21, r5 /* Load u-boot data */
  220. sw r12, r23, r5 /* Write zero to loc */
  221. cmp r12, r5, r6 /* Check if we have reach the end */
  222. bneid r12, 1b
  223. addi r5, r5, 4 /* Increment to next loc - relocate code */
  224. /* R23 points to the base address. */
  225. add r23, r0, r7 /* Move reloc addr to r23 */
  226. addi r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
  227. rsub r23, r24, r23 /* keep - this is already here gd->reloc_off */
  228. addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
  229. lwi r7, r0, 0x28
  230. swi r6, r0, 0x28 /* used first unused MB vector */
  231. lbui r10, r0, 0x28 /* used first unused MB vector */
  232. swi r7, r0, 0x28
  233. #ifdef CONFIG_SYS_USR_EXCEP
  234. addik r6, r0, _exception_handler
  235. addk r6, r6, r23 /* add offset */
  236. sw r6, r1, r0
  237. lhu r7, r1, r10
  238. rsubi r8, r10, 0xa
  239. sh r7, r0, r8
  240. rsubi r8, r10, 0xe
  241. sh r6, r0, r8
  242. #endif
  243. addik r6, r0, _hw_exception_handler
  244. addk r6, r6, r23 /* add offset */
  245. sw r6, r1, r0
  246. lhu r7, r1, r10
  247. rsubi r8, r10, 0x22
  248. sh r7, r0, r8
  249. rsubi r8, r10, 0x26
  250. sh r6, r0, r8
  251. addik r6, r0, _interrupt_handler
  252. addk r6, r6, r23 /* add offset */
  253. sw r6, r1, r0
  254. lhu r7, r1, r10
  255. rsubi r8, r10, 0x12
  256. sh r7, r0, r8
  257. rsubi r8, r10, 0x16
  258. sh r6, r0, r8
  259. /* Check if GOT exist */
  260. addik r21, r23, _got_start
  261. addik r22, r23, _got_end
  262. cmpu r12, r21, r22
  263. beqi r12, 2f /* No GOT table - jump over */
  264. /* Skip last 3 entries plus 1 because of loop boundary below */
  265. addik r22, r22, -0x10
  266. /* Relocate the GOT. */
  267. 3: lw r12, r21, r0 /* Load entry */
  268. addk r12, r12, r23 /* Add reloc offset */
  269. sw r12, r21, r0 /* Save entry back */
  270. cmpu r12, r21, r22 /* Check if this cross boundary */
  271. bneid r12, 3b
  272. addik r21. r21, 4
  273. /* Update pointer to GOT */
  274. mfs r20, rpc
  275. addik r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
  276. addk r20, r20, r23
  277. /* Flush caches to ensure consistency */
  278. addik r5, r0, 0
  279. addik r6, r0, XILINX_DCACHE_BYTE_SIZE
  280. bralid r15, flush_cache
  281. nop
  282. 2: addi r5, r31, 0 /* gd is initialized in board_r.c */
  283. addi r6, r0, CONFIG_SYS_TEXT_BASE
  284. addi r12, r23, board_init_r
  285. bra r12 /* Jump to relocated code */
  286. .end relocate_code
  287. #endif