start.S 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. #if defined(CONFIG_SPL_BUILD)
  25. addi r1, r0, CONFIG_SPL_STACK_ADDR
  26. mts rshr, r1
  27. addi r1, r1, -4 /* Decrement SP to top of memory */
  28. #else
  29. addi r1, r0, CONFIG_SYS_INIT_SP_OFFSET
  30. mts rshr, r1
  31. addi r1, r1, -4 /* Decrement SP to top of memory */
  32. /* Find-out if u-boot is running on BIG/LITTLE endian platform
  33. * There are some steps which is necessary to keep in mind:
  34. * 1. Setup offset value to r6
  35. * 2. Store word offset value to address 0x0
  36. * 3. Load just byte from address 0x0
  37. * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
  38. * value that's why is on address 0x0
  39. * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
  40. */
  41. addik r6, r0, 0x2 /* BIG/LITTLE endian offset */
  42. lwi r7, r0, 0x28
  43. swi r6, r0, 0x28 /* used first unused MB vector */
  44. lbui r10, r0, 0x28 /* used first unused MB vector */
  45. swi r7, r0, 0x28
  46. /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
  47. addi r2, r0, 0xb0000000 /* hex b000 opcode imm */
  48. addi r3, r0, 0xb8080000 /* hew b808 opcode brai */
  49. #ifdef CONFIG_SYS_RESET_ADDRESS
  50. /* reset address */
  51. swi r2, r0, 0x0 /* reset address - imm opcode */
  52. swi r3, r0, 0x4 /* reset address - brai opcode */
  53. addik r6, r0, CONFIG_SYS_RESET_ADDRESS
  54. sw r6, r1, r0
  55. lhu r7, r1, r10
  56. rsubi r8, r10, 0x2
  57. sh r7, r0, r8
  58. rsubi r8, r10, 0x6
  59. sh r6, r0, r8
  60. #endif
  61. #ifdef CONFIG_SYS_USR_EXCEP
  62. /* user_vector_exception */
  63. swi r2, r0, 0x8 /* user vector exception - imm opcode */
  64. swi r3, r0, 0xC /* user vector exception - brai opcode */
  65. addik r6, r0, _exception_handler
  66. sw r6, r1, r0
  67. /*
  68. * BIG ENDIAN memory map for user exception
  69. * 0x8: 0xB000XXXX
  70. * 0xC: 0xB808XXXX
  71. *
  72. * then it is necessary to count address for storing the most significant
  73. * 16bits from _exception_handler address and copy it to
  74. * 0xa address. Big endian use offset in r10=0 that's why is it just
  75. * 0xa address. The same is done for the least significant 16 bits
  76. * for 0xe address.
  77. *
  78. * LITTLE ENDIAN memory map for user exception
  79. * 0x8: 0xXXXX00B0
  80. * 0xC: 0xXXXX08B8
  81. *
  82. * Offset is for little endian setup to 0x2. rsubi instruction decrease
  83. * address value to ensure that points to proper place which is
  84. * 0x8 for the most significant 16 bits and
  85. * 0xC for the least significant 16 bits
  86. */
  87. lhu r7, r1, r10
  88. rsubi r8, r10, 0xa
  89. sh r7, r0, r8
  90. rsubi r8, r10, 0xe
  91. sh r6, r0, r8
  92. #endif
  93. /* interrupt_handler */
  94. swi r2, r0, 0x10 /* interrupt - imm opcode */
  95. swi r3, r0, 0x14 /* interrupt - brai opcode */
  96. addik r6, r0, _interrupt_handler
  97. sw r6, r1, r0
  98. lhu r7, r1, r10
  99. rsubi r8, r10, 0x12
  100. sh r7, r0, r8
  101. rsubi r8, r10, 0x16
  102. sh r6, r0, r8
  103. /* hardware exception */
  104. swi r2, r0, 0x20 /* hardware exception - imm opcode */
  105. swi r3, r0, 0x24 /* hardware exception - brai opcode */
  106. addik r6, r0, _hw_exception_handler
  107. sw r6, r1, r0
  108. lhu r7, r1, r10
  109. rsubi r8, r10, 0x22
  110. sh r7, r0, r8
  111. rsubi r8, r10, 0x26
  112. sh r6, r0, r8
  113. #endif /* BUILD_SPL */
  114. /* Flush cache before enable cache */
  115. addik r5, r0, 0
  116. addik r6, r0, XILINX_DCACHE_BYTE_SIZE
  117. bralid r15, flush_cache
  118. nop
  119. /* enable instruction and data cache */
  120. mfs r12, rmsr
  121. ori r12, r12, 0x1a0
  122. mts rmsr, r12
  123. clear_bss:
  124. /* clear BSS segments */
  125. addi r5, r0, __bss_start
  126. addi r4, r0, __bss_end
  127. cmp r6, r5, r4
  128. beqi r6, 3f
  129. 2:
  130. swi r0, r5, 0 /* write zero to loc */
  131. addi r5, r5, 4 /* increment to next loc */
  132. cmp r6, r5, r4 /* check if we have reach the end */
  133. bnei r6, 2b
  134. 3: /* jumping to board_init */
  135. #ifndef CONFIG_SPL_BUILD
  136. brai board_init_f
  137. #else
  138. brai board_init_r
  139. #endif
  140. 1: bri 1b
  141. #ifndef CONFIG_SPL_BUILD
  142. /*
  143. * Read 16bit little endian
  144. */
  145. .text
  146. .global in16
  147. .ent in16
  148. .align 2
  149. in16: lhu r3, r0, r5
  150. bslli r4, r3, 8
  151. bsrli r3, r3, 8
  152. andi r4, r4, 0xffff
  153. or r3, r3, r4
  154. rtsd r15, 8
  155. sext16 r3, r3
  156. .end in16
  157. /*
  158. * Write 16bit little endian
  159. * first parameter(r5) - address, second(r6) - short value
  160. */
  161. .text
  162. .global out16
  163. .ent out16
  164. .align 2
  165. out16: bslli r3, r6, 8
  166. bsrli r6, r6, 8
  167. andi r3, r3, 0xffff
  168. or r3, r3, r6
  169. sh r3, r0, r5
  170. rtsd r15, 8
  171. or r0, r0, r0
  172. .end out16
  173. #endif