start.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /*
  2. * armboot - Startup Code for ARM920 CPU-core
  3. *
  4. * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
  5. * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
  6. * Copyright (c) 2002 Gary Jennejohn <gj@denx.de>
  7. *
  8. * See file CREDITS for list of people who contributed to this
  9. * project.
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License as
  13. * published by the Free Software Foundation; either version 2 of
  14. * the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24. * MA 02111-1307 USA
  25. */
  26. #include <config.h>
  27. #include <version.h>
  28. #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
  29. #include <led.h>
  30. #endif
  31. /*
  32. *************************************************************************
  33. *
  34. * Jump vector table as in table 3.1 in [1]
  35. *
  36. *************************************************************************
  37. */
  38. .globl _start
  39. _start: b reset
  40. ldr pc, _undefined_instruction
  41. ldr pc, _software_interrupt
  42. ldr pc, _prefetch_abort
  43. ldr pc, _data_abort
  44. ldr pc, _not_used
  45. ldr pc, _irq
  46. ldr pc, _fiq
  47. _undefined_instruction: .word undefined_instruction
  48. _software_interrupt: .word software_interrupt
  49. _prefetch_abort: .word prefetch_abort
  50. _data_abort: .word data_abort
  51. _not_used: .word not_used
  52. _irq: .word irq
  53. _fiq: .word fiq
  54. .balignl 16,0xdeadbeef
  55. /*
  56. *************************************************************************
  57. *
  58. * Startup Code (reset vector)
  59. *
  60. * do important init only if we don't start from memory!
  61. * relocate armboot to ram
  62. * setup stack
  63. * jump to second stage
  64. *
  65. *************************************************************************
  66. */
  67. _TEXT_BASE:
  68. .word TEXT_BASE
  69. .globl _armboot_start
  70. _armboot_start:
  71. .word _start
  72. /*
  73. * These are defined in the board-specific linker script.
  74. */
  75. .globl _bss_start
  76. _bss_start:
  77. .word __bss_start
  78. .globl _bss_end
  79. _bss_end:
  80. .word _end
  81. #ifdef CONFIG_USE_IRQ
  82. /* IRQ stack memory (calculated at run-time) */
  83. .globl IRQ_STACK_START
  84. IRQ_STACK_START:
  85. .word 0x0badc0de
  86. /* IRQ stack memory (calculated at run-time) */
  87. .globl FIQ_STACK_START
  88. FIQ_STACK_START:
  89. .word 0x0badc0de
  90. #endif
  91. /*
  92. * the actual reset code
  93. */
  94. reset:
  95. /*
  96. * set the cpu to SVC32 mode
  97. */
  98. mrs r0,cpsr
  99. bic r0,r0,#0x1f
  100. orr r0,r0,#0xd3
  101. msr cpsr,r0
  102. #if CONFIG_AT91RM9200
  103. #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
  104. bl LED_init
  105. bl red_LED_on
  106. #endif
  107. #ifdef CONFIG_BOOTBINFUNC
  108. /* code based on entry.S from ATMEL */
  109. #define AT91C_BASE_CKGR 0xFFFFFC20
  110. #define CKGR_MOR 0
  111. /* Get the CKGR Base Address */
  112. ldr r1, =AT91C_BASE_CKGR
  113. /* Main oscillator Enable register APMC_MOR : Enable main oscillator , OSCOUNT = 0xFF */
  114. /* ldr r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT */
  115. ldr r0, =0x0000FF01
  116. str r0, [r1, #CKGR_MOR]
  117. /* Add loop to compensate Main Oscillator startup time */
  118. ldr r0, =0x00000010
  119. LoopOsc:
  120. subs r0, r0, #1
  121. bhi LoopOsc
  122. /* scratch stack */
  123. ldr r1, =0x00204000
  124. /* Insure word alignment */
  125. bic r1, r1, #3
  126. /* Init stack SYS */
  127. mov sp, r1
  128. /*
  129. * This does a lot more than just set up the memory, which
  130. * is why it's called lowlevelinit
  131. */
  132. bl lowlevelinit /* in memsetup.S */
  133. bl icache_enable;
  134. /* ------------------------------------
  135. * Read/modify/write CP15 control register
  136. * -------------------------------------
  137. * read cp15 control register (cp15 r1) in r0
  138. * ------------------------------------
  139. */
  140. mrc p15, 0, r0, c1, c0, 0
  141. /* Reset bit :Little Endian end fast bus mode */
  142. ldr r3, =0xC0000080
  143. /* Set bit :Asynchronous clock mode, Not Fast Bus */
  144. ldr r4, =0xC0000000
  145. bic r0, r0, r3
  146. orr r0, r0, r4
  147. /* write r0 in cp15 control register (cp15 r1) */
  148. mcr p15, 0, r0, c1, c0, 0
  149. #endif /* CONFIG_BOOTBINFUNC */
  150. /*
  151. * relocate exeception table
  152. */
  153. ldr r0, =_start
  154. ldr r1, =0x0
  155. mov r2, #16
  156. copyex:
  157. subs r2, r2, #1
  158. ldr r3, [r0], #4
  159. str r3, [r1], #4
  160. bne copyex
  161. #endif
  162. /* turn off the watchdog */
  163. #if defined(CONFIG_S3C2400)
  164. # define pWTCON 0x15300000
  165. # define INTMSK 0x14400008 /* Interupt-Controller base addresses */
  166. # define CLKDIVN 0x14800014 /* clock divisor register */
  167. #elif defined(CONFIG_S3C2410)
  168. # define pWTCON 0x53000000
  169. # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
  170. # define INTSUBMSK 0x4A00001C
  171. # define CLKDIVN 0x4C000014 /* clock divisor register */
  172. #endif
  173. #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
  174. ldr r0, =pWTCON
  175. mov r1, #0x0
  176. str r1, [r0]
  177. /*
  178. * mask all IRQs by setting all bits in the INTMR - default
  179. */
  180. mov r1, #0xffffffff
  181. ldr r0, =INTMSK
  182. str r1, [r0]
  183. # if defined(CONFIG_S3C2410)
  184. ldr r1, =0x3ff
  185. ldr r0, =INTSUBMSK
  186. str r1, [r0]
  187. # endif
  188. /* FCLK:HCLK:PCLK = 1:2:4 */
  189. /* default FCLK is 120 MHz ! */
  190. ldr r0, =CLKDIVN
  191. mov r1, #3
  192. str r1, [r0]
  193. #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
  194. /*
  195. * we do sys-critical inits only at reboot,
  196. * not when booting from ram!
  197. */
  198. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  199. bl cpu_init_crit
  200. #endif
  201. #ifdef CONFIG_AT91RM9200
  202. #ifdef CONFIG_BOOTBINFUNC
  203. relocate: /* relocate U-Boot to RAM */
  204. adr r0, _start /* r0 <- current position of code */
  205. ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
  206. cmp r0, r1 /* don't reloc during debug */
  207. beq stack_setup
  208. ldr r2, _armboot_start
  209. ldr r3, _bss_start
  210. sub r2, r3, r2 /* r2 <- size of armboot */
  211. add r2, r0, r2 /* r2 <- source end address */
  212. copy_loop:
  213. ldmia r0!, {r3-r10} /* copy from source address [r0] */
  214. stmia r1!, {r3-r10} /* copy to target address [r1] */
  215. cmp r0, r2 /* until source end addreee [r2] */
  216. ble copy_loop
  217. #endif /* CONFIG_BOOTBINFUNC */
  218. #else
  219. #ifndef CONFIG_SKIP_RELOCATE_UBOOT
  220. relocate: /* relocate U-Boot to RAM */
  221. adr r0, _start /* r0 <- current position of code */
  222. ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
  223. cmp r0, r1 /* don't reloc during debug */
  224. beq stack_setup
  225. ldr r2, _armboot_start
  226. ldr r3, _bss_start
  227. sub r2, r3, r2 /* r2 <- size of armboot */
  228. add r2, r0, r2 /* r2 <- source end address */
  229. copy_loop:
  230. ldmia r0!, {r3-r10} /* copy from source address [r0] */
  231. stmia r1!, {r3-r10} /* copy to target address [r1] */
  232. cmp r0, r2 /* until source end addreee [r2] */
  233. ble copy_loop
  234. #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
  235. #endif
  236. /* Set up the stack */
  237. stack_setup:
  238. ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
  239. sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
  240. sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
  241. #ifdef CONFIG_USE_IRQ
  242. sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
  243. #endif
  244. sub sp, r0, #12 /* leave 3 words for abort-stack */
  245. clear_bss:
  246. ldr r0, _bss_start /* find start of bss segment */
  247. ldr r1, _bss_end /* stop here */
  248. mov r2, #0x00000000 /* clear */
  249. clbss_l:str r2, [r0] /* clear loop... */
  250. add r0, r0, #4
  251. cmp r0, r1
  252. ble clbss_l
  253. #if 0
  254. /* try doing this stuff after the relocation */
  255. ldr r0, =pWTCON
  256. mov r1, #0x0
  257. str r1, [r0]
  258. /*
  259. * mask all IRQs by setting all bits in the INTMR - default
  260. */
  261. mov r1, #0xffffffff
  262. ldr r0, =INTMR
  263. str r1, [r0]
  264. /* FCLK:HCLK:PCLK = 1:2:4 */
  265. /* default FCLK is 120 MHz ! */
  266. ldr r0, =CLKDIVN
  267. mov r1, #3
  268. str r1, [r0]
  269. /* END stuff after relocation */
  270. #endif
  271. ldr pc, _start_armboot
  272. _start_armboot: .word start_armboot
  273. /*
  274. *************************************************************************
  275. *
  276. * CPU_init_critical registers
  277. *
  278. * setup important registers
  279. * setup memory timing
  280. *
  281. *************************************************************************
  282. */
  283. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  284. cpu_init_crit:
  285. /*
  286. * flush v4 I/D caches
  287. */
  288. mov r0, #0
  289. mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
  290. mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
  291. /*
  292. * disable MMU stuff and caches
  293. */
  294. mrc p15, 0, r0, c1, c0, 0
  295. bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
  296. bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
  297. orr r0, r0, #0x00000002 @ set bit 2 (A) Align
  298. orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
  299. mcr p15, 0, r0, c1, c0, 0
  300. /*
  301. * before relocating, we have to setup RAM timing
  302. * because memory timing is board-dependend, you will
  303. * find a lowlevel_init.S in your board directory.
  304. */
  305. mov ip, lr
  306. #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
  307. #else
  308. bl lowlevel_init
  309. #endif
  310. mov lr, ip
  311. mov pc, lr
  312. #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
  313. /*
  314. *************************************************************************
  315. *
  316. * Interrupt handling
  317. *
  318. *************************************************************************
  319. */
  320. @
  321. @ IRQ stack frame.
  322. @
  323. #define S_FRAME_SIZE 72
  324. #define S_OLD_R0 68
  325. #define S_PSR 64
  326. #define S_PC 60
  327. #define S_LR 56
  328. #define S_SP 52
  329. #define S_IP 48
  330. #define S_FP 44
  331. #define S_R10 40
  332. #define S_R9 36
  333. #define S_R8 32
  334. #define S_R7 28
  335. #define S_R6 24
  336. #define S_R5 20
  337. #define S_R4 16
  338. #define S_R3 12
  339. #define S_R2 8
  340. #define S_R1 4
  341. #define S_R0 0
  342. #define MODE_SVC 0x13
  343. #define I_BIT 0x80
  344. /*
  345. * use bad_save_user_regs for abort/prefetch/undef/swi ...
  346. * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
  347. */
  348. .macro bad_save_user_regs
  349. sub sp, sp, #S_FRAME_SIZE
  350. stmia sp, {r0 - r12} @ Calling r0-r12
  351. ldr r2, _armboot_start
  352. sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
  353. sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
  354. ldmia r2, {r2 - r3} @ get pc, cpsr
  355. add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
  356. add r5, sp, #S_SP
  357. mov r1, lr
  358. stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
  359. mov r0, sp
  360. .endm
  361. .macro irq_save_user_regs
  362. sub sp, sp, #S_FRAME_SIZE
  363. stmia sp, {r0 - r12} @ Calling r0-r12
  364. add r8, sp, #S_PC
  365. stmdb r8, {sp, lr}^ @ Calling SP, LR
  366. str lr, [r8, #0] @ Save calling PC
  367. mrs r6, spsr
  368. str r6, [r8, #4] @ Save CPSR
  369. str r0, [r8, #8] @ Save OLD_R0
  370. mov r0, sp
  371. .endm
  372. .macro irq_restore_user_regs
  373. ldmia sp, {r0 - lr}^ @ Calling r0 - lr
  374. mov r0, r0
  375. ldr lr, [sp, #S_PC] @ Get PC
  376. add sp, sp, #S_FRAME_SIZE
  377. subs pc, lr, #4 @ return & move spsr_svc into cpsr
  378. .endm
  379. .macro get_bad_stack
  380. ldr r13, _armboot_start @ setup our mode stack
  381. sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
  382. sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
  383. str lr, [r13] @ save caller lr / spsr
  384. mrs lr, spsr
  385. str lr, [r13, #4]
  386. mov r13, #MODE_SVC @ prepare SVC-Mode
  387. @ msr spsr_c, r13
  388. msr spsr, r13
  389. mov lr, pc
  390. movs pc, lr
  391. .endm
  392. .macro get_irq_stack @ setup IRQ stack
  393. ldr sp, IRQ_STACK_START
  394. .endm
  395. .macro get_fiq_stack @ setup FIQ stack
  396. ldr sp, FIQ_STACK_START
  397. .endm
  398. /*
  399. * exception handlers
  400. */
  401. .align 5
  402. undefined_instruction:
  403. get_bad_stack
  404. bad_save_user_regs
  405. bl do_undefined_instruction
  406. .align 5
  407. software_interrupt:
  408. get_bad_stack
  409. bad_save_user_regs
  410. bl do_software_interrupt
  411. .align 5
  412. prefetch_abort:
  413. get_bad_stack
  414. bad_save_user_regs
  415. bl do_prefetch_abort
  416. .align 5
  417. data_abort:
  418. get_bad_stack
  419. bad_save_user_regs
  420. bl do_data_abort
  421. .align 5
  422. not_used:
  423. get_bad_stack
  424. bad_save_user_regs
  425. bl do_not_used
  426. #ifdef CONFIG_USE_IRQ
  427. .align 5
  428. irq:
  429. get_irq_stack
  430. irq_save_user_regs
  431. bl do_irq
  432. irq_restore_user_regs
  433. .align 5
  434. fiq:
  435. get_fiq_stack
  436. /* someone ought to write a more effiction fiq_save_user_regs */
  437. irq_save_user_regs
  438. bl do_fiq
  439. irq_restore_user_regs
  440. #else
  441. .align 5
  442. irq:
  443. get_bad_stack
  444. bad_save_user_regs
  445. bl do_irq
  446. .align 5
  447. fiq:
  448. get_bad_stack
  449. bad_save_user_regs
  450. bl do_fiq
  451. #endif