start.S 13 KB

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