start.S 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. * armboot - Startup Code for XScale
  3. *
  4. * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
  5. * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
  6. * Copyright (C) 2000 Wolfgang Denk <wd@denx.de>
  7. * Copyright (C) 2001 Alex Zuepke <azu@sysgo.de>
  8. * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net>
  9. * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
  10. * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de>
  11. * Copyright (c) 2010 Marek Vasut <marek.vasut@gmail.com>
  12. *
  13. * See file CREDITS for list of people who contributed to this
  14. * project.
  15. *
  16. * This program is free software; you can redistribute it and/or
  17. * modify it under the terms of the GNU General Public License as
  18. * published by the Free Software Foundation; either version 2 of
  19. * the License, or (at your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software
  28. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  29. * MA 02111-1307 USA
  30. */
  31. #include <asm-offsets.h>
  32. #include <config.h>
  33. #include <version.h>
  34. #include <asm/arch/pxa-regs.h>
  35. /* takes care the CP15 update has taken place */
  36. .macro CPWAIT reg
  37. mrc p15,0,\reg,c2,c0,0
  38. mov \reg,\reg
  39. sub pc,pc,#4
  40. .endm
  41. .globl _start
  42. _start: b reset
  43. #ifdef CONFIG_SPL_BUILD
  44. ldr pc, _hang
  45. ldr pc, _hang
  46. ldr pc, _hang
  47. ldr pc, _hang
  48. ldr pc, _hang
  49. ldr pc, _hang
  50. ldr pc, _hang
  51. _hang:
  52. .word do_hang
  53. .word 0x12345678
  54. .word 0x12345678
  55. .word 0x12345678
  56. .word 0x12345678
  57. .word 0x12345678
  58. .word 0x12345678
  59. .word 0x12345678 /* now 16*4=64 */
  60. #else
  61. ldr pc, _undefined_instruction
  62. ldr pc, _software_interrupt
  63. ldr pc, _prefetch_abort
  64. ldr pc, _data_abort
  65. ldr pc, _not_used
  66. ldr pc, _irq
  67. ldr pc, _fiq
  68. _undefined_instruction: .word undefined_instruction
  69. _software_interrupt: .word software_interrupt
  70. _prefetch_abort: .word prefetch_abort
  71. _data_abort: .word data_abort
  72. _not_used: .word not_used
  73. _irq: .word irq
  74. _fiq: .word fiq
  75. #endif /* CONFIG_SPL_BUILD */
  76. .balignl 16,0xdeadbeef
  77. /*
  78. * Startup Code (reset vector)
  79. *
  80. * do important init only if we don't start from RAM!
  81. * - relocate armboot to RAM
  82. * - setup stack
  83. * - jump to second stage
  84. */
  85. .globl _TEXT_BASE
  86. _TEXT_BASE:
  87. .word CONFIG_SYS_TEXT_BASE
  88. /*
  89. * These are defined in the board-specific linker script.
  90. */
  91. .globl _bss_start_ofs
  92. _bss_start_ofs:
  93. .word __bss_start - _start
  94. .globl _bss_end_ofs
  95. _bss_end_ofs:
  96. .word __bss_end__ - _start
  97. .globl _end_ofs
  98. _end_ofs:
  99. .word _end - _start
  100. #ifdef CONFIG_USE_IRQ
  101. /* IRQ stack memory (calculated at run-time) */
  102. .globl IRQ_STACK_START
  103. IRQ_STACK_START:
  104. .word 0x0badc0de
  105. /* IRQ stack memory (calculated at run-time) */
  106. .globl FIQ_STACK_START
  107. FIQ_STACK_START:
  108. .word 0x0badc0de
  109. #endif /* CONFIG_USE_IRQ */
  110. #ifndef CONFIG_SPL_BUILD
  111. /* IRQ stack memory (calculated at run-time) + 8 bytes */
  112. .globl IRQ_STACK_START_IN
  113. IRQ_STACK_START_IN:
  114. .word 0x0badc0de
  115. /*
  116. * the actual reset code
  117. */
  118. reset:
  119. /*
  120. * set the cpu to SVC32 mode
  121. */
  122. mrs r0,cpsr
  123. bic r0,r0,#0x1f
  124. orr r0,r0,#0xd3
  125. msr cpsr,r0
  126. /*
  127. * Enable MMU to use DCache as DRAM
  128. */
  129. /* Domain access -- enable for all CPs */
  130. ldr r0, =0x0000ffff
  131. mcr p15, 0, r0, c3, c0, 0
  132. /* Point TTBR to MMU table */
  133. ldr r0, =mmu_table
  134. adr r2, _start
  135. orr r0, r2
  136. mcr p15, 0, r0, c2, c0, 0
  137. /* !!! Hereby, check if the code is running from SRAM !!! */
  138. /* If the code is running from SRAM, alias SRAM to 0x0 to simulate NOR. The code
  139. * is linked to 0x0 too, so this makes things easier. */
  140. cmp r2, #0x5c000000
  141. ldreq r1, [r0]
  142. orreq r1, r2
  143. streq r1, [r0]
  144. /* Kick in MMU, ICache, DCache, BTB */
  145. mrc p15, 0, r0, c1, c0, 0
  146. bic r0, #0x1b00
  147. bic r0, #0x0087
  148. orr r0, #0x1800
  149. orr r0, #0x0005
  150. mcr p15, 0, r0, c1, c0, 0
  151. CPWAIT r0
  152. /* Unlock Icache, Dcache */
  153. mcr p15, 0, r0, c9, c1, 1
  154. mcr p15, 0, r0, c9, c2, 1
  155. /* Flush Icache, Dcache, BTB */
  156. mcr p15, 0, r0, c7, c7, 0
  157. /* Unlock I-TLB, D-TLB */
  158. mcr p15, 0, r0, c10, c4, 1
  159. mcr p15, 0, r0, c10, c8, 1
  160. /* Flush TLB */
  161. mcr p15, 0, r0, c8, c7, 0
  162. /* Allocate 4096 bytes of Dcache as RAM */
  163. /* Drain pending loads and stores */
  164. mcr p15, 0, r0, c7, c10, 4
  165. mov r4, #0x00
  166. mov r5, #0x00
  167. mov r2, #0x01
  168. mcr p15, 0, r0, c9, c2, 0
  169. CPWAIT r0
  170. /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */
  171. mov r0, #128
  172. mov r1, #0xa0000000
  173. alloc:
  174. mcr p15, 0, r1, c7, c2, 5
  175. /* Drain pending loads and stores */
  176. mcr p15, 0, r0, c7, c10, 4
  177. strd r4, [r1], #8
  178. strd r4, [r1], #8
  179. strd r4, [r1], #8
  180. strd r4, [r1], #8
  181. subs r0, #0x01
  182. bne alloc
  183. /* Drain pending loads and stores */
  184. mcr p15, 0, r0, c7, c10, 4
  185. mov r2, #0x00
  186. mcr p15, 0, r2, c9, c2, 0
  187. CPWAIT r0
  188. /* Jump to 0x0 ( + offset) if running from SRAM */
  189. adr r0, zerojmp
  190. bic r0, #0x5c000000
  191. mov pc, r0
  192. zerojmp:
  193. /* Set stackpointer in internal RAM to call board_init_f */
  194. call_board_init_f:
  195. ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
  196. bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
  197. ldr r0,=0x00000000
  198. bl board_init_f
  199. /*------------------------------------------------------------------------------*/
  200. /*
  201. * void relocate_code (addr_sp, gd, addr_moni)
  202. *
  203. * This "function" does not return, instead it continues in RAM
  204. * after relocating the monitor code.
  205. *
  206. */
  207. .globl relocate_code
  208. relocate_code:
  209. mov r4, r0 /* save addr_sp */
  210. mov r5, r1 /* save addr of gd */
  211. mov r6, r2 /* save addr of destination */
  212. /* Set up the stack */
  213. stack_setup:
  214. mov sp, r4
  215. adr r0, _start
  216. cmp r0, r6
  217. beq clear_bss /* skip relocation */
  218. mov r1, r6 /* r1 <- scratch for copy_loop */
  219. ldr r3, _bss_start_ofs
  220. add r2, r0, r3 /* r2 <- source end address */
  221. stmfd sp!, {r0-r12}
  222. copy_loop:
  223. ldmia r0!, {r3-r5, r7-r11} /* copy from source address [r0] */
  224. stmia r1!, {r3-r5, r7-r11} /* copy to target address [r1] */
  225. cmp r0, r2 /* until source end address [r2] */
  226. blo copy_loop
  227. ldmfd sp!, {r0-r12}
  228. #ifndef CONFIG_SPL_BUILD
  229. /*
  230. * fix .rel.dyn relocations
  231. */
  232. ldr r0, _TEXT_BASE /* r0 <- Text base */
  233. sub r9, r6, r0 /* r9 <- relocation offset */
  234. ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
  235. add r10, r10, r0 /* r10 <- sym table in FLASH */
  236. ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
  237. add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
  238. ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
  239. add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
  240. fixloop:
  241. ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
  242. add r0, r9 /* r0 <- location to fix up in RAM */
  243. ldr r1, [r2, #4]
  244. and r7, r1, #0xff
  245. cmp r7, #23 /* relative fixup? */
  246. beq fixrel
  247. cmp r7, #2 /* absolute fixup? */
  248. beq fixabs
  249. /* ignore unknown type of fixup */
  250. b fixnext
  251. fixabs:
  252. /* absolute fix: set location to (offset) symbol value */
  253. mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
  254. add r1, r10, r1 /* r1 <- address of symbol in table */
  255. ldr r1, [r1, #4] /* r1 <- symbol value */
  256. add r1, r1, r9 /* r1 <- relocated sym addr */
  257. b fixnext
  258. fixrel:
  259. /* relative fix: increase location by offset */
  260. ldr r1, [r0]
  261. add r1, r1, r9
  262. fixnext:
  263. str r1, [r0]
  264. add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
  265. cmp r2, r3
  266. blo fixloop
  267. #endif /* #ifndef CONFIG_SPL_BUILD */
  268. clear_bss:
  269. #ifndef CONFIG_SPL_BUILD
  270. ldr r0, _bss_start_ofs
  271. ldr r1, _bss_end_ofs
  272. mov r4, r6 /* reloc addr */
  273. add r0, r0, r4
  274. add r1, r1, r4
  275. mov r2, #0x00000000 /* clear */
  276. clbss_l:str r2, [r0] /* clear loop... */
  277. add r0, r0, #4
  278. cmp r0, r1
  279. bne clbss_l
  280. #endif /* #ifndef CONFIG_SPL_BUILD */
  281. /*
  282. * We are done. Do not return, instead branch to second part of board
  283. * initialization, now running from RAM.
  284. */
  285. #ifdef CONFIG_ONENAND_IPL
  286. ldr r0, _start_oneboot_ofs
  287. mov pc, r0
  288. _start_oneboot_ofs
  289. : .word start_oneboot
  290. #else
  291. ldr r0, _board_init_r_ofs
  292. adr r1, _start
  293. add lr, r0, r1
  294. add lr, lr, r9
  295. /* setup parameters for board_init_r */
  296. mov r0, r5 /* gd_t */
  297. mov r1, r6 /* dest_addr */
  298. /* jump to it ... */
  299. mov pc, lr
  300. _board_init_r_ofs:
  301. .word board_init_r - _start
  302. #endif /* CONFIG_ONENAND_IPL */
  303. _rel_dyn_start_ofs:
  304. .word __rel_dyn_start - _start
  305. _rel_dyn_end_ofs:
  306. .word __rel_dyn_end - _start
  307. _dynsym_start_ofs:
  308. .word __dynsym_start - _start
  309. #else /* CONFIG_SPL_BUILD */
  310. /****************************************************************************/
  311. /* */
  312. /* the actual reset code for OneNAND IPL */
  313. /* */
  314. /****************************************************************************/
  315. #ifndef CONFIG_PXA27X
  316. #error OneNAND IPL is not supported on PXA25x and 26x due to lack of SRAM
  317. #endif
  318. reset:
  319. /* Set CPU to SVC32 mode */
  320. mrs r0,cpsr
  321. bic r0,r0,#0x1f
  322. orr r0,r0,#0x13
  323. msr cpsr,r0
  324. /* Point stack at the end of SRAM and leave 32 words for abort-stack */
  325. ldr sp, =0x5c03ff80
  326. /* Start OneNAND IPL */
  327. ldr pc, =start_oneboot
  328. #endif /* CONFIG_SPL_BUILD */
  329. #ifndef CONFIG_SPL_BUILD
  330. /****************************************************************************/
  331. /* */
  332. /* Interrupt handling */
  333. /* */
  334. /****************************************************************************/
  335. /* IRQ stack frame */
  336. #define S_FRAME_SIZE 72
  337. #define S_OLD_R0 68
  338. #define S_PSR 64
  339. #define S_PC 60
  340. #define S_LR 56
  341. #define S_SP 52
  342. #define S_IP 48
  343. #define S_FP 44
  344. #define S_R10 40
  345. #define S_R9 36
  346. #define S_R8 32
  347. #define S_R7 28
  348. #define S_R6 24
  349. #define S_R5 20
  350. #define S_R4 16
  351. #define S_R3 12
  352. #define S_R2 8
  353. #define S_R1 4
  354. #define S_R0 0
  355. #define MODE_SVC 0x13
  356. /* use bad_save_user_regs for abort/prefetch/undef/swi ... */
  357. .macro bad_save_user_regs
  358. sub sp, sp, #S_FRAME_SIZE
  359. stmia sp, {r0 - r12} /* Calling r0-r12 */
  360. add r8, sp, #S_PC
  361. ldr r2, IRQ_STACK_START_IN
  362. ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */
  363. add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */
  364. add r5, sp, #S_SP
  365. mov r1, lr
  366. stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */
  367. mov r0, sp
  368. .endm
  369. /* use irq_save_user_regs / irq_restore_user_regs for */
  370. /* IRQ/FIQ handling */
  371. .macro irq_save_user_regs
  372. sub sp, sp, #S_FRAME_SIZE
  373. stmia sp, {r0 - r12} /* Calling r0-r12 */
  374. add r8, sp, #S_PC
  375. stmdb r8, {sp, lr}^ /* Calling SP, LR */
  376. str lr, [r8, #0] /* Save calling PC */
  377. mrs r6, spsr
  378. str r6, [r8, #4] /* Save CPSR */
  379. str r0, [r8, #8] /* Save OLD_R0 */
  380. mov r0, sp
  381. .endm
  382. .macro irq_restore_user_regs
  383. ldmia sp, {r0 - lr}^ @ Calling r0 - lr
  384. mov r0, r0
  385. ldr lr, [sp, #S_PC] @ Get PC
  386. add sp, sp, #S_FRAME_SIZE
  387. subs pc, lr, #4 @ return & move spsr_svc into cpsr
  388. .endm
  389. .macro get_bad_stack
  390. ldr r13, IRQ_STACK_START_IN @ setup our mode stack
  391. str lr, [r13] @ save caller lr / spsr
  392. mrs lr, spsr
  393. str lr, [r13, #4]
  394. mov r13, #MODE_SVC @ prepare SVC-Mode
  395. msr spsr_c, r13
  396. mov lr, pc
  397. movs pc, lr
  398. .endm
  399. .macro get_irq_stack @ setup IRQ stack
  400. ldr sp, IRQ_STACK_START
  401. .endm
  402. .macro get_fiq_stack @ setup FIQ stack
  403. ldr sp, FIQ_STACK_START
  404. .endm
  405. #endif /* CONFIG_SPL_BUILD
  406. /****************************************************************************/
  407. /* */
  408. /* exception handlers */
  409. /* */
  410. /****************************************************************************/
  411. #ifdef CONFIG_SPL_BUILD
  412. .align 5
  413. do_hang:
  414. ldr sp, _TEXT_BASE /* use 32 words abort stack */
  415. bl hang /* hang and never return */
  416. #else
  417. .align 5
  418. undefined_instruction:
  419. get_bad_stack
  420. bad_save_user_regs
  421. bl do_undefined_instruction
  422. .align 5
  423. software_interrupt:
  424. get_bad_stack
  425. bad_save_user_regs
  426. bl do_software_interrupt
  427. .align 5
  428. prefetch_abort:
  429. get_bad_stack
  430. bad_save_user_regs
  431. bl do_prefetch_abort
  432. .align 5
  433. data_abort:
  434. get_bad_stack
  435. bad_save_user_regs
  436. bl do_data_abort
  437. .align 5
  438. not_used:
  439. get_bad_stack
  440. bad_save_user_regs
  441. bl do_not_used
  442. #ifdef CONFIG_USE_IRQ
  443. .align 5
  444. irq:
  445. get_irq_stack
  446. irq_save_user_regs
  447. bl do_irq
  448. irq_restore_user_regs
  449. .align 5
  450. fiq:
  451. get_fiq_stack
  452. irq_save_user_regs /* someone ought to write a more */
  453. bl do_fiq /* effiction fiq_save_user_regs */
  454. irq_restore_user_regs
  455. #else /* !CONFIG_USE_IRQ */
  456. .align 5
  457. irq:
  458. get_bad_stack
  459. bad_save_user_regs
  460. bl do_irq
  461. .align 5
  462. fiq:
  463. get_bad_stack
  464. bad_save_user_regs
  465. bl do_fiq
  466. #endif /* CONFIG_SPL_BUILD */
  467. #endif /* CONFIG_USE_IRQ */
  468. /****************************************************************************/
  469. /* */
  470. /* Reset function: the PXA250 doesn't have a reset function, so we have to */
  471. /* perform a watchdog timeout for a soft reset. */
  472. /* */
  473. /****************************************************************************/
  474. /* Operating System Timer */
  475. .align 5
  476. .globl reset_cpu
  477. /* FIXME: this code is PXA250 specific. How is this handled on */
  478. /* other XScale processors? */
  479. reset_cpu:
  480. /* We set OWE:WME (watchdog enable) and wait until timeout happens */
  481. ldr r0, =OWER
  482. ldr r1, [r0]
  483. orr r1, r1, #0x0001 /* bit0: WME */
  484. str r1, [r0]
  485. /* OS timer does only wrap every 1165 seconds, so we have to set */
  486. /* the match register as well. */
  487. ldr r0, =OSCR
  488. ldr r1, [r0] /* read OS timer */
  489. add r1, r1, #0x800 /* let OSMR3 match after */
  490. add r1, r1, #0x800 /* 4096*(1/3.6864MHz)=1ms */
  491. ldr r0, =OSMR3
  492. str r1, [r0]
  493. reset_endless:
  494. b reset_endless
  495. #ifndef CONFIG_SPL_BUILD
  496. .section .mmudata, "a"
  497. .align 14
  498. .globl mmu_table
  499. mmu_table:
  500. /* 0x00000000 - 0xa0000000 : 1:1, uncached mapping */
  501. .set __base, 0
  502. .rept 0xa00
  503. .word (__base << 20) | 0xc12
  504. .set __base, __base + 1
  505. .endr
  506. /* 0xa0000000 - 0xa0100000 : 1:1, cached mapping */
  507. .word (0xa00 << 20) | 0x1c1e
  508. .set __base, 0xa01
  509. .rept 0x1000 - 0xa01
  510. .word (__base << 20) | 0xc12
  511. .set __base, __base + 1
  512. .endr
  513. #endif /* CONFIG_SPL_BUILD */