1/* 2 * BF561 coreB bootstrap file 3 * 4 * Copyright 2007-2009 Analog Devices Inc. 5 * Philippe Gerum <rpm@xenomai.org> 6 * 7 * Licensed under the GPL-2 or later. 8 */ 9 10#include <linux/linkage.h> 11#include <linux/init.h> 12#include <asm/blackfin.h> 13#include <asm/asm-offsets.h> 14 15__INIT 16 17/* Lay the initial stack into the L1 scratch area of Core B */ 18#define INITIAL_STACK (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12) 19 20ENTRY(_coreb_trampoline_start) 21 /* Set the SYSCFG register */ 22 R0 = 0x36; 23 SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/ 24 R0 = 0; 25 26 /*Clear Out All the data and pointer Registers*/ 27 R1 = R0; 28 R2 = R0; 29 R3 = R0; 30 R4 = R0; 31 R5 = R0; 32 R6 = R0; 33 R7 = R0; 34 35 P0 = R0; 36 P1 = R0; 37 P2 = R0; 38 P3 = R0; 39 P4 = R0; 40 P5 = R0; 41 42 LC0 = r0; 43 LC1 = r0; 44 L0 = r0; 45 L1 = r0; 46 L2 = r0; 47 L3 = r0; 48 49 /* Clear Out All the DAG Registers*/ 50 B0 = r0; 51 B1 = r0; 52 B2 = r0; 53 B3 = r0; 54 55 I0 = r0; 56 I1 = r0; 57 I2 = r0; 58 I3 = r0; 59 60 M0 = r0; 61 M1 = r0; 62 M2 = r0; 63 M3 = r0; 64 65 /* Turn off the icache */ 66 p0.l = LO(IMEM_CONTROL); 67 p0.h = HI(IMEM_CONTROL); 68 R1 = [p0]; 69 R0 = ~ENICPLB; 70 R0 = R0 & R1; 71 72 /* Disabling of CPLBs should be proceeded by a CSYNC */ 73 CSYNC; 74 [p0] = R0; 75 SSYNC; 76 77 /* Turn off the dcache */ 78 p0.l = LO(DMEM_CONTROL); 79 p0.h = HI(DMEM_CONTROL); 80 R1 = [p0]; 81 R0 = ~ENDCPLB; 82 R0 = R0 & R1; 83 84 /* Disabling of CPLBs should be proceeded by a CSYNC */ 85 CSYNC; 86 [p0] = R0; 87 SSYNC; 88 89 /* in case of double faults, save a few things */ 90 p0.l = _init_retx_coreb; 91 p0.h = _init_retx_coreb; 92 R0 = RETX; 93 [P0] = R0; 94 95#ifdef CONFIG_DEBUG_DOUBLEFAULT 96 /* Only save these if we are storing them, 97 * This happens here, since L1 gets clobbered 98 * below 99 */ 100 GET_PDA(p0, r0); 101 r7 = [p0 + PDA_DF_RETX]; 102 p1.l = _init_saved_retx_coreb; 103 p1.h = _init_saved_retx_coreb; 104 [p1] = r7; 105 106 r7 = [p0 + PDA_DF_DCPLB]; 107 p1.l = _init_saved_dcplb_fault_addr_coreb; 108 p1.h = _init_saved_dcplb_fault_addr_coreb; 109 [p1] = r7; 110 111 r7 = [p0 + PDA_DF_ICPLB]; 112 p1.l = _init_saved_icplb_fault_addr_coreb; 113 p1.h = _init_saved_icplb_fault_addr_coreb; 114 [p1] = r7; 115 116 r7 = [p0 + PDA_DF_SEQSTAT]; 117 p1.l = _init_saved_seqstat_coreb; 118 p1.h = _init_saved_seqstat_coreb; 119 [p1] = r7; 120#endif 121 122 /* Initialize stack pointer */ 123 sp.l = lo(INITIAL_STACK); 124 sp.h = hi(INITIAL_STACK); 125 fp = sp; 126 usp = sp; 127 128 /* This section keeps the processor in supervisor mode 129 * during core B startup. Branches to the idle task. 130 */ 131 132 /* EVT15 = _real_start */ 133 134 p0.l = lo(EVT15); 135 p0.h = hi(EVT15); 136 p1.l = _coreb_start; 137 p1.h = _coreb_start; 138 [p0] = p1; 139 csync; 140 141 p0.l = lo(IMASK); 142 p0.h = hi(IMASK); 143 p1.l = IMASK_IVG15; 144 p1.h = 0x0; 145 [p0] = p1; 146 csync; 147 148 raise 15; 149 p0.l = .LWAIT_HERE; 150 p0.h = .LWAIT_HERE; 151 reti = p0; 152#if defined(ANOMALY_05000281) 153 nop; nop; nop; 154#endif 155 rti; 156 157.LWAIT_HERE: 158 jump .LWAIT_HERE; 159ENDPROC(_coreb_trampoline_start) 160ENTRY(_coreb_trampoline_end) 161 162ENTRY(_coreb_start) 163 [--sp] = reti; 164 165 p0.l = lo(WDOGB_CTL); 166 p0.h = hi(WDOGB_CTL); 167 r0 = 0xAD6(z); 168 w[p0] = r0; /* Clear the watchdog. */ 169 ssync; 170 171 /* 172 * switch to IDLE stack. 173 */ 174 p0.l = _secondary_stack; 175 p0.h = _secondary_stack; 176 sp = [p0]; 177 usp = sp; 178 fp = sp; 179 sp += -12; 180 call _init_pda 181 sp += 12; 182 call _secondary_start_kernel; 183.L_exit: 184 jump.s .L_exit; 185ENDPROC(_coreb_start) 186 187__FINIT 188