1/* 2 * Common Blackfin startup code 3 * 4 * Copyright 2004-2008 Analog Devices Inc. 5 * 6 * Enter bugs at http://blackfin.uclinux.org/ 7 * 8 * Licensed under the GPL-2 or later. 9 */ 10 11#include <linux/linkage.h> 12#include <linux/init.h> 13#include <asm/blackfin.h> 14#include <asm/thread_info.h> 15#include <asm/trace.h> 16#include <asm/asm-offsets.h> 17 18__INIT 19 20ENTRY(__init_clear_bss) 21 r2 = r2 - r1; 22 cc = r2 == 0; 23 if cc jump .L_bss_done; 24 r2 >>= 2; 25 p1 = r1; 26 p2 = r2; 27 lsetup (1f, 1f) lc0 = p2; 281: [p1++] = r0; 29.L_bss_done: 30 rts; 31ENDPROC(__init_clear_bss) 32 33#define INITIAL_STACK (L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12) 34 35ENTRY(__start) 36 /* R0: argument of command line string, passed from uboot, save it */ 37 R7 = R0; 38 /* Enable Cycle Counter and Nesting Of Interrupts */ 39#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES 40 R0 = SYSCFG_SNEN; 41#else 42 R0 = SYSCFG_SNEN | SYSCFG_CCEN; 43#endif 44 SYSCFG = R0; 45 R0 = 0; 46 47 /* Clear Out All the data and pointer Registers */ 48 R1 = R0; 49 R2 = R0; 50 R3 = R0; 51 R4 = R0; 52 R5 = R0; 53 R6 = R0; 54 55 P0 = R0; 56 P1 = R0; 57 P2 = R0; 58 P3 = R0; 59 P4 = R0; 60 P5 = R0; 61 62 LC0 = r0; 63 LC1 = r0; 64 L0 = r0; 65 L1 = r0; 66 L2 = r0; 67 L3 = r0; 68 69 /* Clear Out All the DAG Registers */ 70 B0 = r0; 71 B1 = r0; 72 B2 = r0; 73 B3 = r0; 74 75 I0 = r0; 76 I1 = r0; 77 I2 = r0; 78 I3 = r0; 79 80 M0 = r0; 81 M1 = r0; 82 M2 = r0; 83 M3 = r0; 84 85 /* 86 * Clear ITEST_COMMAND and DTEST_COMMAND registers, 87 * Leaving these as non-zero can confuse the emulator 88 */ 89 p0.L = LO(DTEST_COMMAND); 90 p0.H = HI(DTEST_COMMAND); 91 [p0] = R0; 92 [p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0; 93 CSYNC; 94 95 trace_buffer_init(p0,r0); 96 P0 = R1; 97 R0 = R1; 98 99 /* Turn off the icache */ 100 p0.l = LO(IMEM_CONTROL); 101 p0.h = HI(IMEM_CONTROL); 102 R1 = [p0]; 103 R0 = ~ENICPLB; 104 R0 = R0 & R1; 105 [p0] = R0; 106 SSYNC; 107 108 /* Turn off the dcache */ 109 p0.l = LO(DMEM_CONTROL); 110 p0.h = HI(DMEM_CONTROL); 111 R1 = [p0]; 112 R0 = ~ENDCPLB; 113 R0 = R0 & R1; 114 [p0] = R0; 115 SSYNC; 116 117 /* in case of double faults, save a few things */ 118 p0.l = _init_retx; 119 p0.h = _init_retx; 120 R0 = RETX; 121 [P0] = R0; 122 123#ifdef CONFIG_DEBUG_DOUBLEFAULT 124 /* Only save these if we are storing them, 125 * This happens here, since L1 gets clobbered 126 * below 127 */ 128 GET_PDA(p0, r0); 129 r7 = [p0 + PDA_RETX]; 130 p1.l = _init_saved_retx; 131 p1.h = _init_saved_retx; 132 [p1] = r7; 133 134 r7 = [p0 + PDA_DCPLB]; 135 p1.l = _init_saved_dcplb_fault_addr; 136 p1.h = _init_saved_dcplb_fault_addr; 137 [p1] = r7; 138 139 r7 = [p0 + PDA_ICPLB]; 140 p1.l = _init_saved_icplb_fault_addr; 141 p1.h = _init_saved_icplb_fault_addr; 142 [p1] = r7; 143 144 r7 = [p0 + PDA_SEQSTAT]; 145 p1.l = _init_saved_seqstat; 146 p1.h = _init_saved_seqstat; 147 [p1] = r7; 148#endif 149 150 /* Initialize stack pointer */ 151 sp.l = lo(INITIAL_STACK); 152 sp.h = hi(INITIAL_STACK); 153 fp = sp; 154 usp = sp; 155 156#ifdef CONFIG_EARLY_PRINTK 157 call _init_early_exception_vectors; 158#endif 159 160 r0 = 0 (x); 161 /* Zero out all of the fun bss regions */ 162#if L1_DATA_A_LENGTH > 0 163 r1.l = __sbss_l1; 164 r1.h = __sbss_l1; 165 r2.l = __ebss_l1; 166 r2.h = __ebss_l1; 167 call __init_clear_bss 168#endif 169#if L1_DATA_B_LENGTH > 0 170 r1.l = __sbss_b_l1; 171 r1.h = __sbss_b_l1; 172 r2.l = __ebss_b_l1; 173 r2.h = __ebss_b_l1; 174 call __init_clear_bss 175#endif 176#if L2_LENGTH > 0 177 r1.l = __sbss_l2; 178 r1.h = __sbss_l2; 179 r2.l = __ebss_l2; 180 r2.h = __ebss_l2; 181 call __init_clear_bss 182#endif 183 r1.l = ___bss_start; 184 r1.h = ___bss_start; 185 r2.l = ___bss_stop; 186 r2.h = ___bss_stop; 187 call __init_clear_bss 188 189 /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */ 190 call _bfin_relocate_l1_mem; 191#ifdef CONFIG_BFIN_KERNEL_CLOCK 192 call _init_clocks; 193#endif 194 195 /* This section keeps the processor in supervisor mode 196 * during kernel boot. Switches to user mode at end of boot. 197 * See page 3-9 of Hardware Reference manual for documentation. 198 */ 199 200 /* EVT15 = _real_start */ 201 202 p0.l = lo(EVT15); 203 p0.h = hi(EVT15); 204 p1.l = _real_start; 205 p1.h = _real_start; 206 [p0] = p1; 207 csync; 208 209 r0 = EVT_IVG15 (z); 210 sti r0; 211 212 raise 15; 213 p0.l = .LWAIT_HERE; 214 p0.h = .LWAIT_HERE; 215 reti = p0; 216#if ANOMALY_05000281 217 nop; nop; nop; 218#endif 219 rti; 220 221.LWAIT_HERE: 222 jump .LWAIT_HERE; 223ENDPROC(__start) 224 225/* A little BF561 glue ... */ 226#ifndef WDOG_CTL 227# define WDOG_CTL WDOGA_CTL 228#endif 229 230ENTRY(_real_start) 231 /* Enable nested interrupts */ 232 [--sp] = reti; 233 234 /* watchdog off for now */ 235 p0.l = lo(WDOG_CTL); 236 p0.h = hi(WDOG_CTL); 237 r0 = 0xAD6(z); 238 w[p0] = r0; 239 ssync; 240 241 /* Pass the u-boot arguments to the global value command line */ 242 R0 = R7; 243 call _cmdline_init; 244 245 /* Load the current thread pointer and stack */ 246 sp.l = _init_thread_union; 247 sp.h = _init_thread_union; 248 p1 = THREAD_SIZE (z); 249 sp = sp + p1; 250 usp = sp; 251 fp = sp; 252 sp += -12; 253 call _init_pda 254 sp += 12; 255 jump.l _start_kernel; 256ENDPROC(_real_start) 257 258__FINIT 259