|
1 /* |
|
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * ne1_tb\nktest\hw_init.cpp |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <arm.h> |
|
22 #include <nkutils.h> |
|
23 #include <diag.h> |
|
24 #include "kernboot.h" |
|
25 //#include <naviengine.h> |
|
26 |
|
27 #ifdef __SMP__ |
|
28 #include <arm_gic.h> |
|
29 #endif |
|
30 |
|
31 |
|
32 const TUint KHwBaseMPcorePrivatePhys = 0xC0000000u; |
|
33 |
|
34 extern void DumpExcInfo(TArmExcInfo&); |
|
35 extern void DumpFullRegSet(SFullArmRegSet& a); |
|
36 |
|
37 extern "C" void Interrupt_Init1(); |
|
38 extern "C" void Interrupt_Init2AP(); |
|
39 extern "C" void Interrupt_Init3(); |
|
40 |
|
41 extern "C" TLinAddr DebugPortBase(); |
|
42 |
|
43 extern "C" TUint KernCoreStats_EnterIdle(TUint); |
|
44 extern "C" void KernCoreStats_LeaveIdle(TInt,TUint); |
|
45 |
|
46 extern "C" { |
|
47 extern TLinAddr RomHeaderAddress; |
|
48 extern TLinAddr SuperPageAddress; |
|
49 } |
|
50 |
|
51 #ifdef __SMP__ |
|
52 TSpinLock DbgSpinLock(TSpinLock::EOrderGenericIrqLow1); |
|
53 #endif |
|
54 |
|
55 |
|
56 struct NETimer |
|
57 { |
|
58 static inline NETimer& Timer(TUint a) { return *(NETimer*)(0x18036000u + (a<<10)); } |
|
59 volatile TUint32 iTimerCount; |
|
60 volatile TUint32 iTimerCtrl; |
|
61 volatile TUint32 iTimerReset; |
|
62 volatile TUint32 iGTOPulseStart; |
|
63 volatile TUint32 iGTOPulseEnd; |
|
64 volatile TUint32 iGTICtrl; |
|
65 volatile TUint32 iGTIRisingEdgeCapture; |
|
66 volatile TUint32 iGTIFallingEdgeCapture; |
|
67 volatile TUint32 iGTInterrupt; |
|
68 volatile TUint32 iGTInterruptEnable; |
|
69 volatile TUint32 iPrescaler; |
|
70 }; |
|
71 |
|
72 class ArmGic |
|
73 { |
|
74 public: |
|
75 static void Dump(); |
|
76 static void DumpCpuIfc(); |
|
77 }; |
|
78 |
|
79 #ifdef __SMP__ |
|
80 |
|
81 extern "C" void ApMainGeneric(volatile SAPBootInfo* aInfo); |
|
82 |
|
83 extern "C" { |
|
84 SVariantInterfaceBlock TheVIB; |
|
85 |
|
86 SVariantInterfaceBlock* InitVIB() |
|
87 { |
|
88 SVariantInterfaceBlock* v = &TheVIB; |
|
89 v->iVer = 0; |
|
90 v->iSize = sizeof(TheVIB); |
|
91 v->iMaxCpuClock = UI64LIT(400000000); // 400MHz |
|
92 v->iMaxTimerClock = 200000000u; // 200MHz = CPU CLK / 2 |
|
93 v->iScuAddr = KHwBaseMPcorePrivatePhys + 0x0; |
|
94 v->iGicDistAddr = KHwBaseMPcorePrivatePhys + 0x1000; |
|
95 v->iGicCpuIfcAddr = KHwBaseMPcorePrivatePhys + 0x100; |
|
96 v->iLocalTimerAddr = KHwBaseMPcorePrivatePhys + 0x600; |
|
97 return v; |
|
98 } |
|
99 } |
|
100 |
|
101 #endif |
|
102 |
|
103 static TInt SystemTimerInterruptHandle = -1; |
|
104 |
|
105 extern "C" { |
|
106 |
|
107 void TimerIsr(TAny* aPtr) |
|
108 { |
|
109 NETimer& NET = NETimer::Timer(0); |
|
110 NET.iGTInterrupt = 0x1fu; |
|
111 __e32_io_completion_barrier(); |
|
112 ((NTimerQ*)aPtr)->Tick(); |
|
113 } |
|
114 |
|
115 void StartSystemTimer() |
|
116 { |
|
117 __KTRACE_OPT(KBOOT,DEBUGPRINT(">StartSystemTimer()")); |
|
118 |
|
119 NETimer& NET = NETimer::Timer(0); |
|
120 NET.iTimerCtrl = 0; |
|
121 NET.iGTICtrl = 0; |
|
122 __e32_io_completion_barrier(); |
|
123 NET.iTimerCtrl = 2; |
|
124 __e32_io_completion_barrier(); |
|
125 NET.iTimerReset = 66666; |
|
126 // NET.iTimerReset = 66666666; |
|
127 __e32_io_completion_barrier(); |
|
128 NET.iGTInterrupt = 0x1fu; |
|
129 __e32_io_completion_barrier(); |
|
130 |
|
131 NTimerQ& m=*(NTimerQ*)NTimerQ::TimerAddress(); |
|
132 TUint32 flags = NKern::EIrqBind_Count; |
|
133 TInt r = NKern::InterruptBind(36-32, &TimerIsr, &m, flags, 0); |
|
134 DEBUGPRINT("r=%08x", r); |
|
135 __NK_ASSERT_ALWAYS(r>=0); |
|
136 SystemTimerInterruptHandle = r; |
|
137 |
|
138 NKern::InterruptEnable(r); |
|
139 DEBUGPRINT("r=%08x", r); |
|
140 |
|
141 NET.iGTInterruptEnable = 0x10u; |
|
142 __e32_io_completion_barrier(); |
|
143 NET.iTimerCtrl = 3; |
|
144 __e32_io_completion_barrier(); |
|
145 |
|
146 // NTimerQ& m=*(NTimerQ*)NTimerQ::TimerAddress(); |
|
147 // TInt r=Interrupt::Bind(EIntIdTimer,&MsTimerTick,&m); |
|
148 // __NK_ASSERT_ALWAYS(r>=0); |
|
149 // initTimer(PIT_COUNT_FOR_1MS); |
|
150 // r=Interrupt::Enable(r); |
|
151 // KPrintf("r=%d",r); |
|
152 // __NK_ASSERT_ALWAYS(r>=0); |
|
153 __KTRACE_OPT(KBOOT,DEBUGPRINT("<StartSystemTimer()")); |
|
154 |
|
155 TInt i; |
|
156 for (i=0; i<50; ++i) |
|
157 { |
|
158 DEBUGPRINT("Count %8d IRQ %02x", NET.iTimerCount, NET.iGTInterrupt); |
|
159 } |
|
160 |
|
161 ArmGic::Dump(); |
|
162 ArmGic::DumpCpuIfc(); |
|
163 } |
|
164 |
|
165 void HijackSystemTimer(NSchedulable* aTieTo) |
|
166 { |
|
167 TInt r = NKern::InterruptUnbind(SystemTimerInterruptHandle); |
|
168 // need to accept KErrArgument because if the tied thread/group |
|
169 // has gone away the interrupt will be unbound already and the |
|
170 // handle is not valid |
|
171 __NK_ASSERT_ALWAYS(r==KErrNone || r==KErrArgument); |
|
172 |
|
173 NTimerQ& m=*(NTimerQ*)NTimerQ::TimerAddress(); |
|
174 TUint32 flags = NKern::EIrqBind_Count; |
|
175 if (aTieTo) |
|
176 flags |= NKern::EIrqBind_Tied; |
|
177 r = NKern::InterruptBind(36-32, &TimerIsr, &m, flags, aTieTo); |
|
178 __NK_ASSERT_ALWAYS(r>=0); |
|
179 SystemTimerInterruptHandle = r; |
|
180 NKern::InterruptEnable(r); |
|
181 } |
|
182 |
|
183 static int debug_uart_data_available() |
|
184 { |
|
185 TUint32 base = DebugPortBase(); |
|
186 volatile TUint8& LSR = *(volatile TUint8*)(base + 0x14); |
|
187 return LSR & 0x01; |
|
188 } |
|
189 |
|
190 static int debug_uart_poll() |
|
191 { |
|
192 TUint32 base = DebugPortBase(); |
|
193 volatile TUint8& LSR = *(volatile TUint8*)(base + 0x14); |
|
194 volatile TUint8& RXHR = *(volatile TUint8*)(base + 0x00); |
|
195 if (LSR & 0x01) |
|
196 return RXHR; |
|
197 return -1; |
|
198 } |
|
199 |
|
200 static void write_debug_uart(char aChar) |
|
201 { |
|
202 TUint32 base = DebugPortBase(); |
|
203 volatile TUint8& LSR = *(volatile TUint8*)(base + 0x14); |
|
204 volatile TUint8& TXHR = *(volatile TUint8*)(base + 0x00); |
|
205 |
|
206 while (!(LSR & 0x20)) |
|
207 {} |
|
208 |
|
209 TXHR = (TUint8)aChar; |
|
210 } |
|
211 |
|
212 const DiagIO DebugUartIO = |
|
213 { |
|
214 &debug_uart_data_available, |
|
215 &debug_uart_poll, |
|
216 &write_debug_uart |
|
217 }; |
|
218 |
|
219 static void init_debug_uart() |
|
220 { |
|
221 write_debug_uart('*'); |
|
222 TheIoFunctions = &DebugUartIO; |
|
223 } |
|
224 |
|
225 // have DFAR DFSR IFSR R13 R14 CPSR ExcCode R5-R11 R0-R4 R12 PC saved |
|
226 struct X |
|
227 { |
|
228 TUint32 iDFAR; |
|
229 TUint32 iDFSR; |
|
230 TUint32 iIFSR; |
|
231 TUint32 iR13; |
|
232 TUint32 iR14; |
|
233 TUint32 iCPSR; |
|
234 TUint32 iExcCode; |
|
235 TUint32 iR5; |
|
236 TUint32 iR6; |
|
237 TUint32 iR7; |
|
238 TUint32 iR8; |
|
239 TUint32 iR9; |
|
240 TUint32 iR10; |
|
241 TUint32 iR11; |
|
242 TUint32 iR0; |
|
243 TUint32 iR1; |
|
244 TUint32 iR2; |
|
245 TUint32 iR3; |
|
246 TUint32 iR4; |
|
247 TUint32 iR12; |
|
248 TUint32 iR15; |
|
249 }; |
|
250 |
|
251 extern "C" { |
|
252 void hw_init_exc(TUint32* a) |
|
253 { |
|
254 X& x = *(X*)a; |
|
255 TInt irq = DbgSpinLock.LockIrqSave(); |
|
256 DumpStruct( |
|
257 "-------------------------------------\n" |
|
258 "DFAR %w DFSR %w IFSR %w\n" |
|
259 "R13 %w R14 %w CPSR %w ExcCode %w\n" |
|
260 "R5 %w R6 %w R7 %w R8 %w\n" |
|
261 "R9 %w R10 %w R11 %w\n" |
|
262 "R0 %w R1 %w R2 %w R3 %w\n" |
|
263 "R4 %w R12 %w PC %w\n", |
|
264 a); |
|
265 if (x.iExcCode==2) |
|
266 { |
|
267 TUint32* p = (TUint32*)x.iR15; |
|
268 TUint32 inst = *p; |
|
269 if (inst>=0xe7ffdef0u && inst<0xe7ffdeffu) |
|
270 { |
|
271 PrtHex8(inst); |
|
272 NewLine(); |
|
273 x.iR15 += 4; |
|
274 DbgSpinLock.UnlockIrqRestore(irq); |
|
275 return; |
|
276 } |
|
277 } |
|
278 RunCrashDebugger(); |
|
279 } |
|
280 } |
|
281 |
|
282 extern "C" void __DebugMsgGlobalCtor(TUint addr, TUint cpsr) |
|
283 { |
|
284 PrtHex8(cpsr); PutSpc(); PrtHex8(addr); NewLine(); |
|
285 } |
|
286 |
|
287 extern "C" TUint64 fast_counter_x(TUint32*); |
|
288 extern "C" void HwInit0() |
|
289 { |
|
290 init_debug_uart(); |
|
291 |
|
292 NETimer& T1 = NETimer::Timer(1); |
|
293 NETimer& T2 = NETimer::Timer(2); |
|
294 |
|
295 T1.iTimerCtrl = 0; // stop and reset timer 1 |
|
296 T1.iGTICtrl = 0; // disable timer 1 capture modes |
|
297 T2.iTimerCtrl = 0; // stop and reset timer 2 |
|
298 T2.iGTICtrl = 0; // disable timer 2 capture modes |
|
299 __e32_io_completion_barrier(); |
|
300 T1.iPrescaler = 1; // Timer 1 prescaled by 1 (=66.667MHz) |
|
301 T2.iPrescaler = 1; // Timer 2 prescaled by 1 |
|
302 // T1.iPrescaler = 4; // Timer 1 prescaled by 4 (=16.667MHz) |
|
303 // T2.iPrescaler = 4; // Timer 2 prescaled by 4 |
|
304 __e32_io_completion_barrier(); |
|
305 T1.iGTInterruptEnable = 0; |
|
306 T2.iGTInterruptEnable = 0; |
|
307 __e32_io_completion_barrier(); |
|
308 T1.iGTInterrupt = 0x1f; |
|
309 T2.iGTInterrupt = 0x1f; |
|
310 __e32_io_completion_barrier(); |
|
311 T1.iTimerCtrl = 2; // deassert reset for timer 1, count still stopped |
|
312 T2.iTimerCtrl = 2; // deassert reset for timer 2, count still stopped |
|
313 __e32_io_completion_barrier(); |
|
314 T1.iTimerReset = 0xfffffeffu; // timer 1 wraps after 2^32-256 counts |
|
315 T2.iTimerReset = 0xffffffffu; // timer 2 wraps after 2^32 counts |
|
316 __e32_io_completion_barrier(); |
|
317 T1.iTimerCtrl = 3; // start timer 1 |
|
318 __e32_io_completion_barrier(); |
|
319 T2.iTimerCtrl = 3; // start timer 2 |
|
320 __e32_io_completion_barrier(); |
|
321 |
|
322 // Each time T1 wraps, (T1-T2) increases by 256 after starting at 0 |
|
323 // t1=T1; t2=T2; n=(t1-t2)>>8; time = t1 + n * (2^32-256) |
|
324 |
|
325 TUint32 t[2]; |
|
326 TUint64 x = fast_counter_x(t); |
|
327 DEBUGPRINT("t1=%08x t2=%08x result %08x %08x", t[0], t[1], I64HIGH(x), I64LOW(x)); |
|
328 } |
|
329 |
|
330 void Hw_Init1() |
|
331 { |
|
332 __CHECKPOINT(); |
|
333 |
|
334 #ifdef __SMP__ |
|
335 NKern::Init0(InitVIB()); |
|
336 #else |
|
337 NKern::Init0(0); |
|
338 #endif |
|
339 Interrupt_Init1(); |
|
340 __CHECKPOINT(); |
|
341 Arm::Init1Interrupts(); |
|
342 __CHECKPOINT(); |
|
343 } |
|
344 |
|
345 #ifdef __SMP__ |
|
346 extern "C" void Hw_InitAPs() |
|
347 { |
|
348 TSubScheduler& ss = SubScheduler(); |
|
349 SSuperPageBase& spg = *(SSuperPageBase*)::SuperPageAddress; |
|
350 TInt ncpus = 4; |
|
351 TInt cpu; |
|
352 for (cpu=1; cpu<ncpus; ++cpu) |
|
353 { |
|
354 TAny* stack = 0; |
|
355 NThread* thread = 0; |
|
356 stack = malloc(4096); |
|
357 __NK_ASSERT_ALWAYS(stack); |
|
358 memset(stack, (0xe1|(cpu<<1)), 4096); |
|
359 thread = new NThread; |
|
360 __NK_ASSERT_ALWAYS(thread); |
|
361 |
|
362 SArmAPBootInfo info; |
|
363 memclr(&info,sizeof(info)); |
|
364 info.iCpu = cpu; |
|
365 info.iInitStackSize = 4096; |
|
366 info.iInitStackBase = (TLinAddr)stack; |
|
367 info.iMain = &ApMainGeneric; |
|
368 info.iArgs[0] = (TAny*)thread; |
|
369 info.iAPBootLin = spg.iAPBootPageLin; |
|
370 info.iAPBootPhys = spg.iAPBootPagePhys; |
|
371 info.iAPBootCodeLin = ::RomHeaderAddress; |
|
372 info.iAPBootCodePhys = spg.iRomHeaderPhys; |
|
373 info.iAPBootPageDirPhys = spg.iAPBootPageDirPhys; |
|
374 TUint32 delta = cpu*0x2000; |
|
375 info.iInitR13Fiq = TLinAddr(ss.iSSX.iFiqStackTop) + delta; |
|
376 info.iInitR13Irq = TLinAddr(ss.iSSX.iIrqStackTop) + delta; |
|
377 info.iInitR13Abt = TLinAddr(ss.iSSX.iAbtStackTop) + delta; |
|
378 info.iInitR13Und = TLinAddr(ss.iSSX.iUndStackTop) + delta; |
|
379 __KTRACE_OPT(KBOOT,DEBUGPRINT("iCpu=%08x", info.iCpu)); |
|
380 __KTRACE_OPT(KBOOT,DEBUGPRINT("iInitStackSize=%08x", info.iInitStackSize)); |
|
381 __KTRACE_OPT(KBOOT,DEBUGPRINT("iInitStackBase=%08x", info.iInitStackBase)); |
|
382 __KTRACE_OPT(KBOOT,DEBUGPRINT("iMain=%08x", info.iMain)); |
|
383 __KTRACE_OPT(KBOOT,DEBUGPRINT("iArgs=%08x %08x %08x %08x", info.iArgs[0], info.iArgs[1], info.iArgs[2], info.iArgs[3])); |
|
384 __KTRACE_OPT(KBOOT,DEBUGPRINT("iAPBootLin=%08x", info.iAPBootLin)); |
|
385 __KTRACE_OPT(KBOOT,DEBUGPRINT("iAPBootPhys=%08x", info.iAPBootPhys)); |
|
386 __KTRACE_OPT(KBOOT,DEBUGPRINT("iAPBootCodeLin=%08x", info.iAPBootCodeLin)); |
|
387 __KTRACE_OPT(KBOOT,DEBUGPRINT("iAPBootCodePhys=%08x", info.iAPBootCodePhys)); |
|
388 __KTRACE_OPT(KBOOT,DEBUGPRINT("iAPBootPageDirPhys=%08x", info.iAPBootPageDirPhys)); |
|
389 __KTRACE_OPT(KBOOT,DEBUGPRINT("iInitR13Fiq=%08x", info.iInitR13Fiq)); |
|
390 __KTRACE_OPT(KBOOT,DEBUGPRINT("iInitR13Irq=%08x", info.iInitR13Irq)); |
|
391 __KTRACE_OPT(KBOOT,DEBUGPRINT("iInitR13Abt=%08x", info.iInitR13Abt)); |
|
392 __KTRACE_OPT(KBOOT,DEBUGPRINT("iInitR13Und=%08x", info.iInitR13Und)); |
|
393 TInt r = NKern::BootAP(&info); |
|
394 __KTRACE_OPT(KBOOT,DEBUGPRINT("ret %d", r)); |
|
395 if (r==KErrNone) |
|
396 { |
|
397 while (__e32_atomic_load_acq32(&info.iArgs[1])==0) |
|
398 __cpu_yield(); |
|
399 __KTRACE_OPT(KBOOT,DEBUGPRINT("CPU %d: OK NullThread=%08x InitialStack=%08x", cpu, thread, stack)); |
|
400 stack = 0; |
|
401 thread = 0; |
|
402 } |
|
403 __NK_ASSERT_ALWAYS(r==KErrNone); |
|
404 if (stack) |
|
405 free(stack); |
|
406 if (thread) |
|
407 free(thread); |
|
408 } |
|
409 } |
|
410 #endif |
|
411 |
|
412 void Hw_Init3() |
|
413 { |
|
414 Interrupt_Init3(); |
|
415 StartSystemTimer(); |
|
416 } |
|
417 } |
|
418 |
|
419 extern "C" void NKCrashHandler(TInt aPhase, const TAny*, TInt) |
|
420 { |
|
421 if (aPhase==0) |
|
422 { |
|
423 return; |
|
424 } |
|
425 __finish(); |
|
426 } |
|
427 |
|
428 extern "C" void ExcFault(void* aExcInfo) |
|
429 { |
|
430 #ifdef __SMP__ |
|
431 SubScheduler().iSSX.iExcInfo = aExcInfo; |
|
432 SFullArmRegSet& a = *SubScheduler().iSSX.iRegs; |
|
433 #else |
|
434 TheScheduler.i_ExcInfo = aExcInfo; |
|
435 SFullArmRegSet& a = *(SFullArmRegSet*)TheScheduler.i_Regs; |
|
436 #endif |
|
437 if (aExcInfo) |
|
438 { |
|
439 Arm::SaveState(a); |
|
440 Arm::UpdateState(a, *(TArmExcInfo*)aExcInfo); |
|
441 } |
|
442 DumpFullRegSet(a); |
|
443 NKern::NotifyCrash(0,0); |
|
444 } |
|
445 |
|
446 /** |
|
447 Faults the system, noting file name and line number. |
|
448 |
|
449 Used from nanokernel code and in various __ASSERT macros. |
|
450 |
|
451 @param file The file name as a C string (__FILE__). |
|
452 @param line The line number (__LINE__). |
|
453 |
|
454 @see Kern::Fault() |
|
455 */ |
|
456 extern "C" void NKFault(const char* file, TInt line) |
|
457 { |
|
458 KPrintf("FAULT at line %d file %s", line, file); |
|
459 NKern::NotifyCrash(0,0); |
|
460 } |
|
461 |
|
462 |
|
463 void DebugPrint(const char* s, int l) |
|
464 { |
|
465 TInt i; |
|
466 #ifdef __SMP__ |
|
467 TInt irq=0; |
|
468 if (!NKern::Crashed()) |
|
469 irq = DbgSpinLock.LockIrqSave(); |
|
470 #endif |
|
471 for (i=0; i<l; ++i) |
|
472 PutC(*s++); |
|
473 #ifdef __SMP__ |
|
474 if (!NKern::Crashed()) |
|
475 DbgSpinLock.UnlockIrqRestore(irq); |
|
476 #endif |
|
477 } |
|
478 |
|
479 TInt __timer_period() |
|
480 { |
|
481 return 1000; |
|
482 } |
|
483 |
|
484 #ifdef __SMP__ |
|
485 TInt __microseconds_to_timeslice_ticks(TInt us) |
|
486 { |
|
487 return NKern::TimesliceTicks(us); |
|
488 } |
|
489 |
|
490 TInt __fast_counter_to_timeslice_ticks(TUint64 aFCdelta) |
|
491 { |
|
492 // fast counter freq = 400MHz/6 |
|
493 // timeslice freq = 400MHz/128 |
|
494 aFCdelta*=3; |
|
495 aFCdelta>>=6; |
|
496 return (TInt)aFCdelta; |
|
497 } |
|
498 #else |
|
499 TInt __microseconds_to_timeslice_ticks(TInt us) |
|
500 { |
|
501 return (us+999)/1000; |
|
502 } |
|
503 |
|
504 TInt __fast_counter_to_timeslice_ticks(TUint64 aFCdelta) |
|
505 { |
|
506 TUint64 fcf = fast_counter_freq(); |
|
507 TUint64 x = (aFCdelta * 1000 + (fcf - 1)) / fcf; |
|
508 return (TInt)x; |
|
509 } |
|
510 #endif |
|
511 |
|
512 extern "C" { |
|
513 extern TLinAddr RomHeaderAddress; |
|
514 void __finish() |
|
515 { |
|
516 RunCrashDebugger(); |
|
517 |
|
518 // TLinAddr f = RomHeaderAddress + 124; |
|
519 // (*(void (*)(TInt))f)(0x80000000); |
|
520 |
|
521 } |
|
522 } |
|
523 |
|
524 extern "C" void NKIdle(TUint32 aStage) |
|
525 { |
|
526 /* |
|
527 SCpuIdleHandler* cih = NKern::CpuIdleHandler(); |
|
528 #ifdef __SMP__ |
|
529 TSubScheduler& ss = SubScheduler(); |
|
530 if (cih && cih->iHandler) |
|
531 (*cih->iHandler)(cih->iPtr, aStage, ss.iUncached); |
|
532 #else |
|
533 if (cih && cih->iHandler) |
|
534 (*cih->iHandler)(cih->iPtr, aStage); |
|
535 #endif |
|
536 else if (K::PowerModel) |
|
537 K::PowerModel->CpuIdle(); |
|
538 else |
|
539 Arm::TheAsic->Idle(); |
|
540 */ |
|
541 __cpu_idle(); |
|
542 } |
|
543 |
|
544 |
|
545 extern "C" TUint32 IrqDispatch(TUint32 aVector) |
|
546 { |
|
547 if (aVector<32 || aVector>127) |
|
548 { |
|
549 GIC_CPU_IFC.iEoi = aVector; |
|
550 *(TInt*)0xdeaddead = 0; |
|
551 return aVector; |
|
552 } |
|
553 NKern::Interrupt(aVector - 32); |
|
554 return aVector; |
|
555 } |
|
556 |
|
557 const TUint8 IntIsEdge[96] = |
|
558 { |
|
559 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, |
|
560 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
561 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, |
|
562 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
563 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
564 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
|
565 }; |
|
566 |
|
567 extern "C" void Interrupt_Init1() |
|
568 { |
|
569 __KTRACE_OPT(KBOOT, DEBUGPRINT(">Interrupt_Init1()")); |
|
570 Arm::SetIrqHandler((TLinAddr)&IrqDispatch); |
|
571 TInt i; |
|
572 for (i=32; i<128; ++i) |
|
573 { |
|
574 TBool edge = IntIsEdge[i-32]; |
|
575 TUint32 flags = 0; |
|
576 if (i>=36 && i<42) |
|
577 flags |= NKern::EIrqInit_Count; // timers count all interrupts |
|
578 if (edge) |
|
579 flags |= NKern::EIrqInit_RisingEdge; |
|
580 else |
|
581 flags |= NKern::EIrqInit_LevelHigh; |
|
582 TInt r = NKern::InterruptInit(i-32, flags, i, i); |
|
583 __KTRACE_OPT(KBOOT, DEBUGPRINT("InterruptInit %d(%02x) -> %d", i-32, i, r)); |
|
584 __NK_ASSERT_ALWAYS(r==KErrNone); |
|
585 } |
|
586 |
|
587 __KTRACE_OPT(KBOOT, DEBUGPRINT("<Interrupt_Init1()")); |
|
588 } |
|
589 |
|
590 extern "C" void Interrupt_Init2AP() |
|
591 { |
|
592 } |
|
593 |
|
594 extern "C" void Interrupt_Init3() |
|
595 { |
|
596 } |
|
597 |
|
598 |
|
599 #include <e32rom.h> |
|
600 |
|
601 extern "C" TLinAddr DebugPortBase() |
|
602 { |
|
603 const TRomHeader& romHdr = *(const TRomHeader*)RomHeaderAddress; |
|
604 if (romHdr.iDebugPort & 1) |
|
605 return 0x18034400u; |
|
606 return 0x18034000u; |
|
607 } |
|
608 |
|
609 |
|
610 extern "C" TUint KernCoreStats_EnterIdle(TUint) |
|
611 { |
|
612 return (TUint) EFalse; |
|
613 } |
|
614 |
|
615 extern "C" void KernCoreStats_LeaveIdle(TInt,TUint) |
|
616 { |
|
617 } |