start.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /*
  2. * Andesboot - Startup Code for Whitiger core
  3. *
  4. * Copyright (C) 2006 Andes Technology Corporation
  5. * Copyright (C) 2006 Shawn Lin <nobuhiro@andestech.com>
  6. * Copyright (C) 2011 Macpaul Lin <macpaul@andestech.com>
  7. * Greentime Hu <greentime@andestech.com>
  8. *
  9. * See file CREDITS for list of people who contributed to this
  10. * project.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License as
  14. * published by the Free Software Foundation; either version 2 of
  15. * the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25. * MA 02111-1307 USA
  26. */
  27. #include <asm-offsets.h>
  28. #include <config.h>
  29. #include <common.h>
  30. #include <asm/macro.h>
  31. #include <version.h>
  32. /*
  33. * Jump vector table for EVIC mode
  34. */
  35. #define ENA_DCAC 2UL
  36. #define DIS_DCAC ~ENA_DCAC
  37. #define ICAC_MEM_KBF_ISET (0x07) ! I Cache sets per way
  38. #define ICAC_MEM_KBF_IWAY (0x07<<3) ! I cache ways
  39. #define ICAC_MEM_KBF_ISZ (0x07<<6) ! I cache line size
  40. #define DCAC_MEM_KBF_DSET (0x07) ! D Cache sets per way
  41. #define DCAC_MEM_KBF_DWAY (0x07<<3) ! D cache ways
  42. #define DCAC_MEM_KBF_DSZ (0x07<<6) ! D cache line size
  43. #define PSW $ir0
  44. #define EIT_INTR_PSW $ir1 ! interruption $PSW
  45. #define EIT_PREV_IPSW $ir2 ! previous $IPSW
  46. #define EIT_IVB $ir3 ! intr vector base address
  47. #define EIT_EVA $ir4 ! MMU related Exception VA reg
  48. #define EIT_PREV_EVA $ir5 ! previous $eva
  49. #define EIT_ITYPE $ir6 ! interruption type
  50. #define EIT_PREV_ITYPE $ir7 ! prev intr type
  51. #define EIT_MACH_ERR $ir8 ! machine error log
  52. #define EIT_INTR_PC $ir9 ! Interruption PC
  53. #define EIT_PREV_IPC $ir10 ! previous $IPC
  54. #define EIT_OVL_INTR_PC $ir11 ! overflow interruption PC
  55. #define EIT_PREV_P0 $ir12 ! prev $P0
  56. #define EIT_PREV_P1 $ir13 ! prev $p1
  57. #define CR_ICAC_MEM $cr1 ! I-cache/memory config reg
  58. #define CR_DCAC_MEM $cr2 ! D-cache/memory config reg
  59. #define MR_CAC_CTL $mr8
  60. .globl _start
  61. _start: j reset
  62. j tlb_fill
  63. j tlb_not_present
  64. j tlb_misc
  65. j tlb_vlpt_miss
  66. j cache_parity_error
  67. j debug
  68. j general_exception
  69. j internal_interrupt ! H0I
  70. j internal_interrupt ! H1I
  71. j internal_interrupt ! H2I
  72. j internal_interrupt ! H3I
  73. j internal_interrupt ! H4I
  74. j internal_interrupt ! H5I
  75. .balign 16
  76. /*
  77. * Andesboot Startup Code (reset vector)
  78. *
  79. * 1. bootstrap
  80. * 1.1 reset - start of u-boot
  81. * 1.2 to superuser mode - as is when reset
  82. * 1.4 Do lowlevel_init
  83. * - (this will jump out to lowlevel_init.S in SoC)
  84. * - (lowlevel_init)
  85. * 1.3 Turn off watchdog timer
  86. * - (this will jump out to watchdog.S in SoC)
  87. * - (turnoff_watchdog)
  88. * 2. Do critical init when reboot (not from mem)
  89. * 3. Relocate andesboot to ram
  90. * 4. Setup stack
  91. * 5. Jump to second stage (board_init_r)
  92. */
  93. /* Note: TEXT_BASE is defined by the (board-dependent) linker script */
  94. .globl _TEXT_BASE
  95. _TEXT_BASE:
  96. .word CONFIG_SYS_TEXT_BASE
  97. /*
  98. * These are defined in the board-specific linker script.
  99. * Subtracting _start from them lets the linker put their
  100. * relative position in the executable instead of leaving
  101. * them null.
  102. */
  103. #ifdef CONFIG_USE_IRQ
  104. /* IRQ stack memory (calculated at run-time) */
  105. .globl IRQ_STACK_START
  106. IRQ_STACK_START:
  107. .word 0x0badc0de
  108. /* IRQ stack memory (calculated at run-time) */
  109. .globl FIQ_STACK_START
  110. FIQ_STACK_START:
  111. .word 0x0badc0de
  112. #endif
  113. /* IRQ stack memory (calculated at run-time) + 8 bytes */
  114. .globl IRQ_STACK_START_IN
  115. IRQ_STACK_START_IN:
  116. .word 0x0badc0de
  117. /*
  118. * The bootstrap code of nds32 core
  119. */
  120. reset:
  121. set_ivb:
  122. li $r0, 0x0
  123. /* turn on BTB */
  124. mtsr $r0, $misc_ctl
  125. /* set IVIC, vector size: 4 bytes, base: 0x0 */
  126. mtsr $r0, $ivb
  127. load_lli:
  128. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  129. jal load_lowlevel_init
  130. jral $p0
  131. #endif
  132. /*
  133. * Set the N1213 (Whitiger) core to superuser mode
  134. * According to spec, it is already when reset
  135. */
  136. turnoff_wtdog:
  137. #ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
  138. jal load_turnoff_watchdog
  139. jral $p0
  140. #endif
  141. /*
  142. * Do CPU critical regs init only at reboot,
  143. * not when booting from ram
  144. */
  145. #ifdef CONFIG_INIT_CRITICAL
  146. bal cpu_init_crit ! Do CPU critical regs init
  147. #endif
  148. /*
  149. * Set stackpointer in internal RAM to call board_init_f
  150. * $sp must be 8-byte alignment for ABI compliance.
  151. */
  152. call_board_init_f:
  153. li $sp, CONFIG_SYS_INIT_SP_ADDR
  154. li $r0, 0x00000000
  155. #ifdef __PIC__
  156. #ifdef __NDS32_N1213_43U1H__
  157. /* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */
  158. la $r15, board_init_f ! store function address into $r15
  159. #endif
  160. #endif
  161. j board_init_f ! jump to board_init_f() in lib/board.c
  162. /*
  163. * void relocate_code (addr_sp, gd, addr_moni)
  164. *
  165. * This "function" does not return, instead it continues in RAM
  166. * after relocating the monitor code.
  167. *
  168. */
  169. .globl relocate_code
  170. relocate_code:
  171. move $r4, $r0 /* save addr_sp */
  172. move $r5, $r1 /* save addr of gd */
  173. move $r6, $r2 /* save addr of destination */
  174. /* Set up the stack */
  175. stack_setup:
  176. move $sp, $r4
  177. la $r0, _start
  178. beq $r0, $r6, clear_bss /* skip relocation */
  179. move $r1, $r6 /* r1 <- scratch for copy_loop */
  180. la $r3, __bss_start
  181. sub $r3, $r3, $r0 /* r3 <- __bss_start_ofs */
  182. add $r2, $r0, $r3 /* r2 <- source end address */
  183. copy_loop:
  184. lwi.p $r7, [$r0], #4
  185. swi.p $r7, [$r1], #4
  186. blt $r0, $r2, copy_loop
  187. /*
  188. * fix relocations related issues
  189. */
  190. fix_relocations:
  191. l.w $r0, _TEXT_BASE /* r0 <- Text base */
  192. sub $r9, $r6, $r0 /* r9 <- relocation offset */
  193. fix_got:
  194. /*
  195. * Now we want to update GOT.
  196. *
  197. * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
  198. * generated by GNU ld. Skip these reserved entries from relocation.
  199. */
  200. la $r2, __got_start /* r2 <- rel __got_start in FLASH */
  201. add $r2, $r2, $r9 /* r2 <- rel __got_start in RAM */
  202. la $r3, __got_end /* r3 <- rel __got_end in FLASH */
  203. add $r3, $r3, $r9 /* r3 <- rel __got_end in RAM */
  204. addi $r2, $r2, #8 /* skipping first two entries */
  205. fix_got_loop:
  206. lwi $r0, [$r2] /* r0 <- location in FLASH to fix up */
  207. add $r0, $r0, $r9 /* r0 <- location fix up to RAM */
  208. swi.p $r0, [$r2], #4 /* r0 <- store fix into .got in RAM */
  209. blt $r2, $r3, fix_got_loop
  210. clear_bss:
  211. la $r0, __bss_start /* r0 <- rel __bss_start in FLASH */
  212. add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */
  213. la $r1, __bss_end__ /* r1 <- rel __bss_end in RAM */
  214. add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */
  215. li $r2, 0x00000000 /* clear */
  216. clbss_l:
  217. sw $r2, [$r0] /* clear loop... */
  218. addi $r0, $r0, #4
  219. bne $r0, $r1, clbss_l
  220. /*
  221. * We are done. Do not return, instead branch to second part of board
  222. * initialization, now running from RAM.
  223. */
  224. call_board_init_r:
  225. la $r0, board_init_r
  226. move $lp, $r0 /* offset of board_init_r() */
  227. add $lp, $lp, $r9 /* real address of board_init_r() */
  228. /* setup parameters for board_init_r */
  229. move $r0, $r5 /* gd_t */
  230. move $r1, $r6 /* dest_addr */
  231. #ifdef __PIC__
  232. #ifdef __NDS32_N1213_43U1H__ /* NDS32 V0 ISA */
  233. move $r15, $lp /* store function address into $r15 */
  234. #endif
  235. #endif
  236. /* jump to it ... */
  237. jr $lp /* jump to board_init_r() */
  238. /*
  239. * Initialize CPU critical registers
  240. *
  241. * 1. Setup control registers
  242. * 1.1 Mask all IRQs
  243. * 1.2 Flush cache and TLB
  244. * 1.3 Disable MMU and cache
  245. * 2. Setup memory timing
  246. */
  247. cpu_init_crit:
  248. move $r0, $lp /* push ra */
  249. /* Disable Interrupts by clear GIE in $PSW reg */
  250. setgie.d
  251. /* Flush caches and TLB */
  252. /* Invalidate caches */
  253. bal invalidate_icac
  254. bal invalidate_dcac
  255. /* Flush TLB */
  256. mfsr $p0, $MMU_CFG
  257. andi $p0, $p0, 0x3 ! MMPS
  258. li $p1, 0x2 ! TLB MMU
  259. bne $p0, $p1, 1f
  260. tlbop flushall ! Flush TLB
  261. 1:
  262. ! Disable MMU, Dcache
  263. ! Whitiger is MMU disabled when reset
  264. ! Disable the D$
  265. mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg
  266. li $p1, DIS_DCAC
  267. and $p0, $p0, $p1 ! Set DC_EN bit
  268. mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg
  269. isb
  270. move $lp, $r0
  271. 2:
  272. ret
  273. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  274. load_lowlevel_init:
  275. la $r6, lowlevel_init
  276. la $r7, load_lli + 4
  277. sub $p0, $r6, $r7
  278. add $p0, $p0, $lp
  279. ret
  280. #endif
  281. #ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
  282. load_turnoff_watchdog:
  283. la $r6, turnoff_watchdog
  284. la $r7, turnoff_wtdog + 4
  285. sub $p0, $r6, $r7
  286. add $p0, $p0, $lp
  287. ret
  288. #endif
  289. /*
  290. * Invalidate I$
  291. */
  292. invalidate_icac:
  293. ! read $cr1(I CAC/MEM cfg. reg.) configuration
  294. mfsr $t0, CR_ICAC_MEM
  295. ! Get the ISZ field
  296. andi $p0, $t0, ICAC_MEM_KBF_ISZ
  297. ! if $p0=0, then no I CAC existed
  298. beqz $p0, end_flush_icache
  299. ! get $p0 the index of I$ block
  300. srli $p0, $p0, 6
  301. ! $t1= bit width of I cache line size(ISZ)
  302. addi $t1, $p0, 2
  303. li $t4, 1
  304. sll $t5, $t4, $t1 ! get $t5 cache line size
  305. andi $p1, $t0, ICAC_MEM_KBF_ISET ! get the ISET field
  306. addi $t2, $p1, 6 ! $t2= bit width of ISET
  307. andi $p1, $t0, ICAC_MEM_KBF_IWAY ! get bitfield of Iway
  308. srli $p1, $p1, 3
  309. addi $p1, $p1, 1 ! then $p1 is I way number
  310. add $t3, $t2, $t1 ! SHIFT
  311. sll $p1, $p1, $t3 ! GET the total cache size
  312. ICAC_LOOP:
  313. sub $p1, $p1, $t5
  314. cctl $p1, L1I_IX_INVAL
  315. bnez $p1, ICAC_LOOP
  316. end_flush_icache:
  317. ret
  318. /*
  319. * Invalidate D$
  320. */
  321. invalidate_dcac:
  322. ! read $cr2(D CAC/MEM cfg. reg.) configuration
  323. mfsr $t0, CR_DCAC_MEM
  324. ! Get the DSZ field
  325. andi $p0, $t0, DCAC_MEM_KBF_DSZ
  326. ! if $p0=0, then no D CAC existed
  327. beqz $p0, end_flush_dcache
  328. ! get $p0 the index of D$ block
  329. srli $p0, $p0, 6
  330. ! $t1= bit width of D cache line size(DSZ)
  331. addi $t1, $p0, 2
  332. li $t4, 1
  333. sll $t5, $t4, $t1 ! get $t5 cache line size
  334. andi $p1, $t0, DCAC_MEM_KBF_DSET ! get the DSET field
  335. addi $t2, $p1, 6 ! $t2= bit width of DSET
  336. andi $p1, $t0, DCAC_MEM_KBF_DWAY ! get bitfield of D way
  337. srli $p1, $p1, 3
  338. addi $p1, $p1, 1 ! then $p1 is D way number
  339. add $t3, $t2, $t1 ! SHIFT
  340. sll $p1, $p1, $t3 ! GET the total cache size
  341. DCAC_LOOP:
  342. sub $p1, $p1, $t5
  343. cctl $p1, L1D_IX_INVAL
  344. bnez $p1, DCAC_LOOP
  345. end_flush_dcache:
  346. ret
  347. /*
  348. * Interrupt handling
  349. */
  350. /*
  351. * exception handlers
  352. */
  353. .align 5
  354. .macro SAVE_ALL
  355. ! FIXME: Other way to get PC?
  356. ! FIXME: Update according to the newest spec!!
  357. 1:
  358. la $r28, 1
  359. push $r28
  360. mfsr $r28, PSW ! $PSW
  361. push $r28
  362. mfsr $r28, EIT_EVA ! $ir1 $EVA
  363. push $r28
  364. mfsr $r28, EIT_ITYPE ! $ir2 $ITYPE
  365. push $r28
  366. mfsr $r28, EIT_MACH_ERR ! $ir3 Mach Error
  367. push $r28
  368. mfsr $r28, EIT_INTR_PSW ! $ir5 $IPSW
  369. push $r28
  370. mfsr $r28, EIT_PREV_IPSW ! $ir6 prev $IPSW
  371. push $r28
  372. mfsr $r28, EIT_PREV_EVA ! $ir7 prev $EVA
  373. push $r28
  374. mfsr $r28, EIT_PREV_ITYPE ! $ir8 prev $ITYPE
  375. push $r28
  376. mfsr $r28, EIT_INTR_PC ! $ir9 Interruption PC
  377. push $r28
  378. mfsr $r28, EIT_PREV_IPC ! $ir10 prev INTR_PC
  379. push $r28
  380. mfsr $r28, EIT_OVL_INTR_PC ! $ir11 Overflowed INTR_PC
  381. push $r28
  382. mfusr $r28, $d1.lo
  383. push $r28
  384. mfusr $r28, $d1.hi
  385. push $r28
  386. mfusr $r28, $d0.lo
  387. push $r28
  388. mfusr $r28, $d0.hi
  389. push $r28
  390. pushm $r0, $r30 ! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp
  391. addi $sp, $sp, -4 ! make room for implicit pt_regs parameters
  392. .endm
  393. .align 5
  394. tlb_fill:
  395. SAVE_ALL
  396. move $r0, $sp ! To get the kernel stack
  397. li $r1, 1 ! Determine interruption type
  398. bal do_interruption
  399. .align 5
  400. tlb_not_present:
  401. SAVE_ALL
  402. move $r0, $sp ! To get the kernel stack
  403. li $r1, 2 ! Determine interruption type
  404. bal do_interruption
  405. .align 5
  406. tlb_misc:
  407. SAVE_ALL
  408. move $r0, $sp ! To get the kernel stack
  409. li $r1, 3 ! Determine interruption type
  410. bal do_interruption
  411. .align 5
  412. tlb_vlpt_miss:
  413. SAVE_ALL
  414. move $r0, $sp ! To get the kernel stack
  415. li $r1, 4 ! Determine interruption type
  416. bal do_interruption
  417. .align 5
  418. cache_parity_error:
  419. SAVE_ALL
  420. move $r0, $sp ! To get the kernel stack
  421. li $r1, 5 ! Determine interruption type
  422. bal do_interruption
  423. .align 5
  424. debug:
  425. SAVE_ALL
  426. move $r0, $sp ! To get the kernel stack
  427. li $r1, 6 ! Determine interruption type
  428. bal do_interruption
  429. .align 5
  430. general_exception:
  431. SAVE_ALL
  432. move $r0, $sp ! To get the kernel stack
  433. li $r1, 7 ! Determine interruption type
  434. bal do_interruption
  435. .align 5
  436. internal_interrupt:
  437. SAVE_ALL
  438. move $r0, $sp ! To get the kernel stack
  439. li $r1, 8 ! Determine interruption type
  440. bal do_interruption
  441. .align 5
  442. /*
  443. * void reset_cpu(ulong addr);
  444. * $r0: input address to jump to
  445. */
  446. .globl reset_cpu
  447. reset_cpu:
  448. /* No need to disable MMU because we never enable it */
  449. bal invalidate_icac
  450. bal invalidate_dcac
  451. mfsr $p0, $MMU_CFG
  452. andi $p0, $p0, 0x3 ! MMPS
  453. li $p1, 0x2 ! TLB MMU
  454. bne $p0, $p1, 1f
  455. tlbop flushall ! Flush TLB
  456. 1:
  457. mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg
  458. li $p1, DIS_DCAC
  459. and $p0, $p0, $p1 ! Clear the DC_EN bit
  460. mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg
  461. br $r0 ! Jump to the input address