File size: 16,028 Bytes
829b19c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 | /*
* ARM Cortex-A8 (OMAP3530) Low-Level Startup
* Runs from SRAM before any C code β modeled on SH7734 lowlevel_init.S
*
* Responsibilities:
* 1. CPU mode + FPU + endianness (CP15)
* 2. Disable WDT2
* 3. Invalidate caches + TLB
* 4. Configure DPLL1 (MPU 600MHz) and DPLL3 (CORE)
* 5. Enable peripheral clocks (UART, GPIO, GPTIMER, GPMC, SDRC)
* 6. Initialize SDRC (JEDEC DDR sequence with wait timers)
* 7. Set up stack, zero BSS
* 8. Jump to C entry (reset_handler)
*/
#include "platform_offsets.h"
.text
.arm
.align 2
.global _start
.global lowlevel_init
/* ================================================================
* Exception Vector Table β placed at 0xFFF00000 or 0x00000000
* ================================================================ */
_start:
b reset_entry /* 0x00 Reset */
b undef_handler /* 0x04 Undefined instr */
b svc_handler /* 0x08 SVC */
b prefetch_handler /* 0x0C Prefetch abort */
b data_handler /* 0x10 Data abort */
nop /* 0x14 Reserved */
b irq_handler /* 0x18 IRQ */
b fiq_handler /* 0x1C FIQ */
undef_handler:
svc_handler:
prefetch_handler:
data_handler:
fiq_handler:
b .
irq_handler:
sub lr, lr, #4
stmfd sp!, {r0-r12, lr}
bl intc_handle_irq
ldmfd sp!, {r0-r12, pc}^
/* ================================================================
* RESET ENTRY β first code executed
* ================================================================ */
reset_entry:
/* ---- 1. Enter SVC mode, disable IRQ/FIQ ---- */
mrs r0, cpsr
bic r0, r0, #0x1F /* Clear mode bits */
orr r0, r0, #0xD3 /* SVC mode + IRQ/FIQ disabled */
msr cpsr, r0
/* ---- 2. Disable WDT2 (OMAP3530 WDT2 at 0x48314000) ---- */
ldr r1, =WDT2_WSPR
ldr r2, =0x0000AAAA
str r2, [r1]
ldr r2, =0x00005555
str r2, [r1]
/* ---- 3. Invalidate caches and TLB ---- */
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 /* Invalidate I-cache */
mcr p15, 0, r0, c7, c6, 0 /* Invalidate D-cache */
mcr p15, 0, r0, c8, c7, 0 /* Invalidate entire TLB */
/* Disable caches + MMU for clean state */
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #(1 << 0) /* MMU off */
bic r0, r0, #(1 << 2) /* D-cache off */
bic r0, r0, #(1 << 12) /* I-cache off */
bic r0, r0, #(1 << 11) /* Branch prediction off */
mcr p15, 0, r0, c1, c0, 0
dsb
isb
/* ---- 4. Set VBAR (vector base) to current location ---- */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 /* VBAR = _start */
/* ---- 5. Enable NEON/VFP ---- */
mrc p15, 0, r0, c1, c0, 2 /* CPACR */
orr r0, r0, #(0xF << 20) /* CP10 + CP11 full access */
mcr p15, 0, r0, c1, c0, 2
isb
mov r0, #0x40000000 /* FPEXC.EN = 1 */
vmsr FPEXC, r0
/* ---- 6. Jump to lowlevel_init ---- */
bl lowlevel_init
/* ---- 7. Set up stack and jump to C ---- */
ldr sp, =STACK_BASE_VAL
bl bss_zero
bl reset_handler
b . /* Should never reach here */
/* ================================================================
* LOWLEVEL INIT β OMAP3530 DPLL + Clock + SDRC
* Modeled on SH7734 lowlevel_init: WDT β MMU β FRQCR β CS β DBSC
* ================================================================ */
lowlevel_init:
/* ---- A. Wait for power sequencing (50ms from power-tree.json) ---- */
ldr r0, =POWER_SEQ_DELAY
bl wait_cycles
/* ---- B. Configure DPLL1 (MPU) β 600MHz from 26MHz ref ---- */
/* Read current DPLL1 state from CM_CLKSEL1_PLL_MPU */
ldr r1, =CM_CLKSEL1_PLL_MPU
ldr r0, [r1]
/* Check if DPLL1 is already at target (M=23, N=1) */
ldr r2, =DPLL1_MPU_TARGET
cmp r0, r2
beq dpll1_done
/* DPLL1 not at target β reconfigure */
/* Step 1: Put DPLL1 in bypass (low-power stop) */
ldr r1, =CM_CLKEN_PLL_MPU
ldr r0, [r1]
bic r0, r0, #0x07 /* Clear DPLL_EN bits */
orr r0, r0, #0x04 /* DPLL_EN = MN bypass */
str r0, [r1]
/* Wait for DPLL to enter bypass */
ldr r0, =DPLL_LOCK_DELAY
bl wait_cycles
/* Step 2: Set M and N dividers */
ldr r1, =CM_CLKSEL1_PLL_MPU
ldr r2, =DPLL1_MPU_TARGET
str r2, [r1]
/* Step 3: Re-lock DPLL1 */
ldr r1, =CM_CLKEN_PLL_MPU
ldr r0, [r1]
bic r0, r0, #0x07
orr r0, r0, #0x07 /* DPLL_EN = lock mode */
str r0, [r1]
/* Wait for DPLL1 lock (typically <100Β΅s) */
ldr r1, =CM_IDLEST_PLL_MPU
dpll1_lock_wait:
ldr r0, [r1]
ands r0, r0, #0x01 /* Check ST_MPU_CLK bit */
bne dpll1_lock_wait /* 0 = locked, keep polling */
dpll1_done:
/* ---- C. Configure DPLL3 (CORE) β leave at ROM default for now ---- */
/* DPLL3 drives L3 interconnect. ROM typically sets 166MHz L3. */
/* For bring-up, we accept ROM defaults. */
/* ---- D. Configure DPLL5 (DDR) β 266MHz ---- */
ldr r1, =CM_CLKSEL2_PLL
ldr r0, [r1]
ldr r2, =DPLL5_DDR_TARGET
cmp r0, r2
beq dpll5_done
/* Bypass DPLL5 */
ldr r1, =CM_CLKEN_PLL
ldr r0, [r1]
bic r0, r0, #(0x07 << 8)
orr r0, r0, #(0x04 << 8)
str r0, [r1]
ldr r0, =DPLL_LOCK_DELAY
bl wait_cycles
/* Set DPLL5 M/N */
ldr r1, =CM_CLKSEL2_PLL
ldr r2, =DPLL5_DDR_TARGET
str r2, [r1]
/* Lock DPLL5 */
ldr r1, =CM_CLKEN_PLL
ldr r0, [r1]
bic r0, r0, #(0x07 << 8)
orr r0, r0, #(0x07 << 8)
str r0, [r1]
/* Wait for lock */
ldr r1, =CM_IDLEST_CORE
dpll5_lock_wait:
ldr r0, [r1]
ands r0, r0, #0x02
bne dpll5_lock_wait
dpll5_done:
/* ---- E. Enable peripheral clocks ---- */
ldr r1, =CM_FCLKEN1_CORE_VAL
ldr r0, [r1]
ldr r1, =CM_FCLKEN1_CORE
str r0, [r1]
ldr r1, =CM_ICLKEN1_CORE_VAL
ldr r0, [r1]
ldr r1, =CM_ICLKEN1_CORE
str r0, [r1]
ldr r1, =CM_FCLKEN_WKUP_VAL
ldr r0, [r1]
ldr r1, =CM_FCLKEN_WKUP
str r0, [r1]
ldr r1, =CM_ICLKEN_WKUP_VAL
ldr r0, [r1]
ldr r1, =CM_ICLKEN_WKUP
str r0, [r1]
/* Wait for clocks to become active */
ldr r0, =CLOCK_SETTLE_DELAY
bl wait_cycles
/* ---- F. Initialize SDRC β JEDEC DDR init sequence ---- */
/* Modeled on SH7734 DBSC3 init: power pad β NOP β PRECHARGE β
REFRESH Γ2 β MRS β EMRS β normal, with wait timers */
bl sdrc_init_asm
/* ---- G. Initialize GPMC for NOR/NAND ---- */
bl gpmc_init_asm
/* ---- H. Return to caller ---- */
bx lr
/* ================================================================
* SDRC INIT β Assembly-level JEDEC DDR sequence
* OMAP3530 SDRC for MT48H32M16LF-7 (mobile SDR SDRAM)
* Mirrors SH7734 DBSC3 pattern: pad power β NOP β PRC β REF β MRS
* ================================================================ */
sdrc_init_asm:
/* Enable SDRC interface clock (should be on, but be safe) */
ldr r1, =SDRC_SYSCONFIG
ldr r0, =0x00000010 /* Smart idle, auto-wakeup */
str r0, [r1]
ldr r0, =WAIT_50US
bl wait_cycles
/* CS0 mapping: 256MB at 0x30000000 */
ldr r1, =SDRC_CS_CFG_REG
ldr r0, =0x00000030
str r0, [r1]
/* SDRC sharing */
ldr r1, =SDRC_SHARING_REG
ldr r0, =0x00000000
str r0, [r1]
/* MCFG0: Mobile SDRAM, 4 banks, 8K rows */
ldr r1, =SDRC_MCFG_0_REG
ldr r0, =SDRC_MCFG_0_VAL
str r0, [r1]
/* ACTIM_CTRLA0: tRFC=22, tXSR=22, tRP=2, tRCD=3 */
ldr r1, =SDRC_ACTIM_CTRLA_0_REG
ldr r0, =SDRC_ACTIM_CTRLA_0_VAL
str r0, [r1]
/* ACTIM_CTRLB0: tRAS=5, tRC=7, tWR=2, tRASMAX=9 */
ldr r1, =SDRC_ACTIM_CTRLB_0_REG
ldr r0, =SDRC_ACTIM_CTRLB_0_VAL
str r0, [r1]
/* RFR_CTRL0: Refresh rate β 7.8Β΅s @ 133MHz = 1040 cycles */
ldr r1, =SDRC_RFR_CTRL_0_REG
ldr r0, =SDRC_RFR_CTRL_0_VAL
str r0, [r1]
/* ---- JEDEC Init Sequence (mirrors SH7734 DBPDCNT sequence) ---- */
/* Step 1: NOP command (DBPDCNT3_D equivalent β first pad power-on) */
ldr r1, =SDRC_MR_0_REG
ldr r0, =0x00000000 /* CMD = NOP */
str r0, [r1]
ldr r0, =WAIT_200US /* 200Β΅s β matches SH7734 WAIT_200US_400 */
bl wait_cycles
/* Step 2: PRECHARGE-ALL */
ldr r1, =SDRC_MR_0_REG
ldr r0, =0x00000001 /* CMD = PRC */
str r0, [r1]
ldr r0, =WAIT_100US
bl wait_cycles
/* Step 3: AUTO-REFRESH #1 (SH7734 does 2Γ DBCMD_D1) */
ldr r1, =SDRC_MR_0_REG
ldr r0, =0x00000004 /* CMD = REF */
str r0, [r1]
ldr r0, =WAIT_32MCLK /* Wait 32 MCLK cycles */
bl wait_cycles
/* Step 4: AUTO-REFRESH #2 */
ldr r1, =SDRC_MR_0_REG
ldr r0, =0x00000004 /* CMD = REF */
str r0, [r1]
ldr r0, =WAIT_32MCLK
bl wait_cycles
/* Step 5: MRS β CAS latency 3, burst length 4, sequential */
ldr r1, =SDRC_MR_0_REG
ldr r0, =SDRC_MRS_VAL /* CMD=MRS | CL=3 | BL=4 | Sequential */
str r0, [r1]
ldr r0, =WAIT_16MCLK
bl wait_cycles
/* Step 6: EMRS β extended mode (drive strength, ODT if DDR2) */
ldr r1, =SDRC_MR_0_REG
ldr r0, =0x00000002 /* CMD = EMRS */
str r0, [r1]
ldr r0, =WAIT_16MCLK
bl wait_cycles
/* Step 7: Normal operation */
ldr r1, =SDRC_MR_0_REG
ldr r0, =0x00000000
str r0, [r1]
/* Dummy read from SDRAM (like SH7734 synco + mov.l @r1, r0) */
ldr r1, =SDRAM_BASE_ADDR
ldr r0, [r1]
dsb
ldr r0, =WAIT_10KMCLK /* Settle β matches SH7734 WAIT_10KMCLK */
bl wait_cycles
bx lr
/* ================================================================
* GPMC INIT β minimal NOR + NAND setup (SH7734 CS0CTRL/CSWCR)
* ================================================================ */
gpmc_init_asm:
/* Enable GPMC functional clock (should be on) */
/* GPMC SYSCONFIG: smart idle */
ldr r1, =GPMC_SYSCONFIG_REG
ldr r0, =0x00000010
str r0, [r1]
ldr r0, =WAIT_50US
bl wait_cycles
/* GPMC TIMEOUT: 16Γ timeout, enable */
ldr r1, =GPMC_TIMEOUT_CTRL_REG
ldr r0, =0x00010011
str r0, [r1]
/* CS0: NOR Flash 16-bit async at 0x08000000 */
ldr r1, =GPMC_CONFIG1_0_REG
ldr r0, =NOR_GPMC_CONFIG1
str r0, [r1]
ldr r1, =GPMC_CONFIG2_0_REG
ldr r0, =NOR_GPMC_CONFIG2
str r0, [r1]
ldr r1, =GPMC_CONFIG3_0_REG
ldr r0, =NOR_GPMC_CONFIG3
str r0, [r1]
ldr r1, =GPMC_CONFIG4_0_REG
ldr r0, =NOR_GPMC_CONFIG4
str r0, [r1]
ldr r1, =GPMC_CONFIG5_0_REG
ldr r0, =NOR_GPMC_CONFIG5
str r0, [r1]
ldr r1, =GPMC_CONFIG6_0_REG
ldr r0, =NOR_GPMC_CONFIG6
str r0, [r1]
/* CS0 base address + enable */
ldr r1, =GPMC_CONFIG7_0_REG
ldr r0, =NOR_GPMC_CONFIG7
str r0, [r1]
/* CS1: NAND Flash 8-bit at 0x40000000 */
ldr r1, =GPMC_CONFIG1_1_REG
ldr r0, =NAND_GPMC_CONFIG1
str r0, [r1]
ldr r1, =GPMC_CONFIG7_1_REG
ldr r0, =NAND_GPMC_CONFIG7
str r0, [r1]
/* Reset NAND device */
ldr r1, =GPMC_NAND_CMD_1
ldr r0, =0xFF /* NAND_CMD_RESET */
strb r0, [r1]
ldr r0, =WAIT_200US
bl wait_cycles
bx lr
/* ================================================================
* BSS ZERO β clear .bss section
* ================================================================ */
bss_zero:
ldr r0, =__bss_start
ldr r1, =__bss_end
mov r2, #0
bss_loop:
cmp r0, r1
bge bss_done
str r2, [r0], #4
b bss_loop
bss_done:
bx lr
/* ================================================================
* WAIT CYCLES β simple busy loop (SH7734 wait_timer pattern)
* ================================================================ */
wait_cycles:
subs r0, r0, #1
bne wait_cycles
bx lr
/* ================================================================
* LITERAL POOL β all constant addresses and values
* ================================================================ */
.align 2
/* ---- OMAP3530 PRCM (Power/Reset/Clock Management) ---- */
CM_CLKEN_PLL_MPU: .long 0x48004900
CM_IDLEST_PLL_MPU: .long 0x48004920
CM_CLKSEL1_PLL_MPU: .long 0x48004940
DPLL1_MPU_TARGET: .long 0x00170001 /* M=23, N=1 β 598MHz */
CM_CLKEN_PLL: .long 0x48004D00
CM_IDLEST_CORE: .long 0x48004A20
CM_CLKSEL2_PLL: .long 0x48004D44
DPLL5_DDR_TARGET: .long 0x000A0001 /* M=10, N=1 β 260MHz */
/* ---- Clock enable values ---- */
CM_FCLKEN1_CORE: .long 0x48004A00
CM_FCLKEN1_CORE_VAL: .long 0x04060026 /* EN_UART1|EN_UART2|EN_GPMC|EN_HSMMC1 */
CM_ICLKEN1_CORE: .long 0x48004A10
CM_ICLKEN1_CORE_VAL: .long 0x04068026 /* Interface clocks */
CM_FCLKEN_WKUP: .long 0x48004C00
CM_FCLKEN_WKUP_VAL: .long 0x00000014 /* EN_GPIO1 | EN_GPT1 */
CM_ICLKEN_WKUP: .long 0x48004C10
CM_ICLKEN_WKUP_VAL: .long 0x00000014
/* ---- WDT2 ---- */
WDT2_WSPR: .long 0x48314048
/* ---- SDRC registers ---- */
SDRC_SYSCONFIG: .long 0x6D000010
SDRC_CS_CFG_REG: .long 0x6D000040
SDRC_SHARING_REG: .long 0x6D000044
SDRC_MCFG_0_REG: .long 0x6D000080
SDRC_MR_0_REG: .long 0x6D000084
SDRC_ACTIM_CTRLA_0_REG: .long 0x6D00009C
SDRC_ACTIM_CTRLB_0_REG: .long 0x6D0000A0
SDRC_RFR_CTRL_0_REG: .long 0x6D0000A4
SDRC_MCFG_0_VAL: .long 0x02584011 /* DDR, 4 banks, 8K rows, 512 cols */
SDRC_ACTIM_CTRLA_0_VAL: .long 0x16A00902 /* tRFC=22, tXSR=22, tRP=2, tRCD=3 */
SDRC_ACTIM_CTRLB_0_VAL: .long 0x50290705 /* tRAS=5, tRC=7, tWR=2, tRASMAX=9 */
SDRC_RFR_CTRL_0_VAL: .long 0x00041001 /* 1040 cycles, enabled */
SDRC_MRS_VAL: .long 0x00000033 /* CMD=MRS, CL=3, BL=4, sequential */
SDRAM_BASE_ADDR: .long 0x30000000
/* ---- GPMC registers ---- */
GPMC_SYSCONFIG_REG: .long 0x6E000010
GPMC_TIMEOUT_CTRL_REG: .long 0x6E000040
GPMC_CONFIG1_0_REG: .long 0x6E000060
GPMC_CONFIG2_0_REG: .long 0x6E000064
GPMC_CONFIG3_0_REG: .long 0x6E000068
GPMC_CONFIG4_0_REG: .long 0x6E00006C
GPMC_CONFIG5_0_REG: .long 0x6E000070
GPMC_CONFIG6_0_REG: .long 0x6E000074
GPMC_CONFIG7_0_REG: .long 0x6E000078
GPMC_CONFIG1_1_REG: .long 0x6E000090
GPMC_CONFIG7_1_REG: .long 0x6E0000A8
GPMC_NAND_CMD_1: .long 0x6E0001D0
/* NOR Flash GPMC config (CS0: 16-bit async) */
NOR_GPMC_CONFIG1: .long 0x00001200 /* 16-bit, NOR async */
NOR_GPMC_CONFIG2: .long 0x001F1F08 /* CS on/off timing */
NOR_GPMC_CONFIG3: .long 0x00060602 /* ADV on/off */
NOR_GPMC_CONFIG4: .long 0x0C0C0303 /* OE/WE on/off */
NOR_GPMC_CONFIG5: .long 0x02020202 /* RD/WR cycle/access */
NOR_GPMC_CONFIG6: .long 0x00020200 /* WrDataMux, wr access */
NOR_GPMC_CONFIG7: .long 0x00000F4E /* Base=0x08, mask=0xF, CSVALID */
/* NAND Flash GPMC config (CS1: 8-bit NAND) */
NAND_GPMC_CONFIG1: .long 0x00000800 /* 8-bit, NAND */
NAND_GPMC_CONFIG7: .long 0x00000FCE /* Base=0x40, mask=0xF, CSVALID */
/* ---- Wait timer values (SH7734 pattern) ---- */
POWER_SEQ_DELAY: .long 30000000 /* ~50ms at 600MHz */
DPLL_LOCK_DELAY: .long 300000 /* ~0.5ms at 600MHz */
CLOCK_SETTLE_DELAY: .long 300000 /* ~0.5ms */
WAIT_200US: .long 120000 /* 200Β΅s at 600MHz */
WAIT_100US: .long 60000 /* 100Β΅s at 600MHz */
WAIT_50US: .long 30000
WAIT_32MCLK: .long 19200 /* 32 MCLK cycles at 133MHz β 240ns β ~144k CPU cycles */
WAIT_16MCLK: .long 9600
WAIT_10KMCLK: .long 6000000 /* 10000 MCLK at 133MHz β 75Β΅s β ~45000 CPU cycles; pad to 10ms */
WAIT_1MCLK: .long 600
/* ---- Stack ---- */
STACK_BASE_VAL: .long 0x20010000
/* ---- Linker symbols ---- */
.extern __bss_start
.extern __bss_end
|