navienginebsp/ne1_tb/nktest/hw_init.cpp
changeset 0 5de814552237
equal deleted inserted replaced
-1:000000000000 0:5de814552237
       
     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 	}