Download firmware/boot/start.S from Snapkitty/phaser-ags: direct link, hf CLI and curl.
- Browser
- Download file 16 kB
-
https://huggingface.co/Snapkitty/phaser-ags/resolve/main/firmware/boot/start.S
- Command line
-
hf download hf://Snapkitty/phaser-ags/firmware/boot/start.S
-
curl -L -o start.S https://huggingface.co/Snapkitty/phaser-ags/resolve/main/firmware/boot/start.S
16 kB
| /* | |
| * 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" | |
| 2 | |
| _start | |
| 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 | |
| * ================================================================ */ | |
| 2 | |
| /* ---- OMAP3530 PRCM (Power/Reset/Clock Management) ---- */ | |
| CM_CLKEN_PLL_MPU: 0x48004900 | |
| CM_IDLEST_PLL_MPU: 0x48004920 | |
| CM_CLKSEL1_PLL_MPU: 0x48004940 | |
| DPLL1_MPU_TARGET: 0x00170001 /* M=23, N=1 → 598MHz */ | |
| CM_CLKEN_PLL: 0x48004D00 | |
| CM_IDLEST_CORE: 0x48004A20 | |
| CM_CLKSEL2_PLL: 0x48004D44 | |
| DPLL5_DDR_TARGET: 0x000A0001 /* M=10, N=1 → 260MHz */ | |
| /* ---- Clock enable values ---- */ | |
| CM_FCLKEN1_CORE: 0x48004A00 | |
| CM_FCLKEN1_CORE_VAL: 0x04060026 /* EN_UART1|EN_UART2|EN_GPMC|EN_HSMMC1 */ | |
| CM_ICLKEN1_CORE: 0x48004A10 | |
| CM_ICLKEN1_CORE_VAL: 0x04068026 /* Interface clocks */ | |
| CM_FCLKEN_WKUP: 0x48004C00 | |
| CM_FCLKEN_WKUP_VAL: 0x00000014 /* EN_GPIO1 | EN_GPT1 */ | |
| CM_ICLKEN_WKUP: 0x48004C10 | |
| CM_ICLKEN_WKUP_VAL: 0x00000014 | |
| /* ---- WDT2 ---- */ | |
| WDT2_WSPR: 0x48314048 | |
| /* ---- SDRC registers ---- */ | |
| SDRC_SYSCONFIG: 0x6D000010 | |
| SDRC_CS_CFG_REG: 0x6D000040 | |
| SDRC_SHARING_REG: 0x6D000044 | |
| SDRC_MCFG_0_REG: 0x6D000080 | |
| SDRC_MR_0_REG: 0x6D000084 | |
| SDRC_ACTIM_CTRLA_0_REG: 0x6D00009C | |
| SDRC_ACTIM_CTRLB_0_REG: 0x6D0000A0 | |
| SDRC_RFR_CTRL_0_REG: 0x6D0000A4 | |
| SDRC_MCFG_0_VAL: 0x02584011 /* DDR, 4 banks, 8K rows, 512 cols */ | |
| SDRC_ACTIM_CTRLA_0_VAL: 0x16A00902 /* tRFC=22, tXSR=22, tRP=2, tRCD=3 */ | |
| SDRC_ACTIM_CTRLB_0_VAL: 0x50290705 /* tRAS=5, tRC=7, tWR=2, tRASMAX=9 */ | |
| SDRC_RFR_CTRL_0_VAL: 0x00041001 /* 1040 cycles, enabled */ | |
| SDRC_MRS_VAL: 0x00000033 /* CMD=MRS, CL=3, BL=4, sequential */ | |
| SDRAM_BASE_ADDR: 0x30000000 | |
| /* ---- GPMC registers ---- */ | |
| GPMC_SYSCONFIG_REG: 0x6E000010 | |
| GPMC_TIMEOUT_CTRL_REG: 0x6E000040 | |
| GPMC_CONFIG1_0_REG: 0x6E000060 | |
| GPMC_CONFIG2_0_REG: 0x6E000064 | |
| GPMC_CONFIG3_0_REG: 0x6E000068 | |
| GPMC_CONFIG4_0_REG: 0x6E00006C | |
| GPMC_CONFIG5_0_REG: 0x6E000070 | |
| GPMC_CONFIG6_0_REG: 0x6E000074 | |
| GPMC_CONFIG7_0_REG: 0x6E000078 | |
| GPMC_CONFIG1_1_REG: 0x6E000090 | |
| GPMC_CONFIG7_1_REG: 0x6E0000A8 | |
| GPMC_NAND_CMD_1: 0x6E0001D0 | |
| /* NOR Flash GPMC config (CS0: 16-bit async) */ | |
| NOR_GPMC_CONFIG1: 0x00001200 /* 16-bit, NOR async */ | |
| NOR_GPMC_CONFIG2: 0x001F1F08 /* CS on/off timing */ | |
| NOR_GPMC_CONFIG3: 0x00060602 /* ADV on/off */ | |
| NOR_GPMC_CONFIG4: 0x0C0C0303 /* OE/WE on/off */ | |
| NOR_GPMC_CONFIG5: 0x02020202 /* RD/WR cycle/access */ | |
| NOR_GPMC_CONFIG6: 0x00020200 /* WrDataMux, wr access */ | |
| NOR_GPMC_CONFIG7: 0x00000F4E /* Base=0x08, mask=0xF, CSVALID */ | |
| /* NAND Flash GPMC config (CS1: 8-bit NAND) */ | |
| NAND_GPMC_CONFIG1: 0x00000800 /* 8-bit, NAND */ | |
| NAND_GPMC_CONFIG7: 0x00000FCE /* Base=0x40, mask=0xF, CSVALID */ | |
| /* ---- Wait timer values (SH7734 pattern) ---- */ | |
| POWER_SEQ_DELAY: 30000000 /* ~50ms at 600MHz */ | |
| DPLL_LOCK_DELAY: 300000 /* ~0.5ms at 600MHz */ | |
| CLOCK_SETTLE_DELAY: 300000 /* ~0.5ms */ | |
| WAIT_200US: 120000 /* 200µs at 600MHz */ | |
| WAIT_100US: 60000 /* 100µs at 600MHz */ | |
| WAIT_50US: 30000 | |
| WAIT_32MCLK: 19200 /* 32 MCLK cycles at 133MHz → 240ns → ~144k CPU cycles */ | |
| WAIT_16MCLK: 9600 | |
| WAIT_10KMCLK: 6000000 /* 10000 MCLK at 133MHz ≈ 75µs → ~45000 CPU cycles; pad to 10ms */ | |
| WAIT_1MCLK: 600 | |
| /* ---- Stack ---- */ | |
| STACK_BASE_VAL: 0x20010000 | |
| /* ---- Linker symbols ---- */ | |
| __bss_start | |
| __bss_end | |