navienginebsp/ne1_tb/bootstrap/ne1_tb.s
changeset 0 5de814552237
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/navienginebsp/ne1_tb/bootstrap/ne1_tb.s	Tue Sep 28 18:00:05 2010 +0100
@@ -0,0 +1,1040 @@
+;
+; Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description:  
+; ne1_tb/bootstrap/ne1_tb.s
+; NE1_TBVariant for platform specific boot code
+;
+
+		GBLL	__VARIANT_S__		; indicates that this is platform-specific code
+		GBLL	__NE1_TB_S__		; indicates which source file this is
+
+		INCLUDE	bootcpu.inc
+		INCLUDE	arm_types.inc
+		INCLUDE naviengine.inc
+
+	IF	CFG_DebugBootRom
+	GBLL					CFG_InitDebugPort
+	ENDIF
+	INIT_LOGICAL_SYMBOL		CFG_InitDebugPort
+
+	IF :DEF: CFG_AlternateEntryPoint; NOTE: Bootloader is defined by this macro
+	IMPORT	GetCoreldr
+	ENDIF
+	
+;*******************************************************************************
+;
+; Platform specific constant definitions
+
+	IF :DEF: CFG_AlternateEntryPoint :LOR: CFG_MMDirect
+RamBank0MaxSize		EQU		0x08000000 ; for bootloader or direct, the upper half is reserverd for the image
+	ELSE
+RamBank0MaxSize		EQU		0x10000000
+	ENDIF
+
+PrimaryRomBase		EQU		0x00000000
+PrimaryRomSize		EQU		0x04000000
+ExtensionRomBase	EQU		0x08000000
+ExtensionRomSize	EQU		0x00000000
+
+
+;*******************************************************************************
+
+; ASSP Specific constants
+
+	IF :LNOT: CFG_MMDirect
+
+;Serial Ports Linear Addresses:
+
+Serial0LinBase		EQU		KPrimaryIOBase
+Serial1LinBase		EQU		KPrimaryIOBase + (KHwUART1Phys - KHwUART0Phys)
+
+	ENDIF
+
+;Serial Port Register Offsets
+Serial_DLL			EQU		0
+Serial_DLH			EQU		4
+Serial_LCR			EQU		0xc
+Serial_THR			EQU		0
+Serial_LSR			EQU		0x14
+
+
+	IF :LNOT: CFG_MMDirect
+
+SysCtrlUnitLinBase  		EQU		KPrimaryIOBase + (0x1000*3)+0x1c00
+												; ... as the value in ne1_tb_bootloader\inc\bootloader_variantconfig.h
+	ENDIF												
+
+;*******************************************************************************
+; There are 4 red LEDs that can be controlled by a 16 bit register in the FPGA.
+; Each LED has a bit in the register, where 0==off and 1==on
+; We use each register to show the CPU status, where:
+;    off is "not started"
+;    on  is "started"
+; once the system is running, the OS may use the LEDs for other purposes
+;*******************************************************************************
+KHwFpgaLedsPhyicalBase      EQU   KHwFPGAPhys                + KHoFpgaLeds;
+
+	IF :LNOT: CFG_MMDirect
+KHwFpgaLedsLinBase          EQU   KPrimaryIOBase   + 0xB000  + KHoFpgaLeds;
+	ENDIF												
+
+
+;*******************************************************************************
+; struct SSmrIF
+; interface between Core Loader and Bootstrap
+; See: bootstrap_smrif.h
+;*******************************************************************************
+SSmrIF_iNumOfShwPart                    EQU 0x00000000
+SSmrIF_iSmribSize                       EQU 0x00000004
+SSmrIF_iSmrBanks                        EQU 0x00000008
+SSmrIF_sz                               EQU 0x0000000c
+
+
+
+;*******************************************************************************
+;
+
+        AREA |Boot$$Code|, CODE, READONLY, ALIGN=6
+
+;
+;*******************************************************************************
+;
+
+
+;***************************************************************************************
+; Determine variant required when running on NaviEngine NE1-TB
+; Enter with:
+;	R12 points to TRomHeader
+;	NO STACK
+;	R14 = return address (as usual)
+;
+; Return with:
+;	R10 = Super page address
+;***************************************************************************************
+;
+; The SuperPage is placed at the start of the free RAM.
+	EXPORT	CalculateSuperPageAddress
+CalculateSuperPageAddress
+		MOV		r7, lr
+		ANDS	r10, pc, #KHwDDR2RamBasePhys	; running from RAM? if not, r10=0
+		MOVEQ	r10, #KHwDDR2RamBasePhys		; if running from flash, super page is at base of RAM bank 0
+		BLNE	SetupSuperPageRunningFromRAM	; if running from RAM, super page goes after ROM image(s)
+		MOV		lr, r7
+		MOV		pc, lr
+
+;*******************************************************************************
+; Initialise Hardware
+;	Initialise CPU registers
+;	Determine the hardware configuration
+;	Determine the reset reason. If it is wakeup from a low power mode, perform
+;		whatever reentry sequence is required and jump back to the kernel.
+;	Set up the memory controller so that at least some RAM is available
+;	Set R10 to point to the super page or to a temporary version of the super page
+;		with at least the following fields valid:
+;		iBootTable, iCodeBase, iActiveVariant, iCpuId
+;	and optionally:
+;			iSmrData
+;	In debug builds initialise the debug serial port
+;
+; Enter with:
+;		R2	= value as at entry to ResetEntry, preserved unmodified
+;		R3	= value of cpsr on entry to ResetEntry
+;		R12 = points to TRomHeader
+;		NO STACK
+;		R14 = return address (as usual)
+;
+; Leave with :
+;		R10 = physical address of super page 
+;
+; All registers may be modified by this call
+;
+;*******************************************************************************
+	EXPORT	InitialiseHardware
+InitialiseHardware	ROUT
+		MOV		r13, lr					; save return address
+
+		MOV		r8, r2					; Preserve r2, r3 (cpsr) till later
+		MOV		r9, r3					; S/P initialisation by boot processor
+
+	IF :DEF: CFG_AlternateEntryPoint; NOTE: Bootloader is defined by this macro
+
+		LDR		r1, =KHwSYSCTRLPhys + 0x00C	; Reset status
+		LDR		r1,	[r1]
+		ANDS	r1, r1, #0x00030000		; soft-reset or hot-reset?
+		BNE		changed_wtop_mode
+
+		LDR		r1, =KHwSYSCTRLPhys + 0x11C	; WTOP
+		LDR		r0,	[r1]
+		ANDS	r0, r0, #0xFFFFFFFE		; clear bit 0b to be normal mode
+		STR		r0, [r1]
+
+		LDR		r1, =KHwSYSCTRLPhys + 0x00C	; Reset status
+		MOV		r0, #0x00000001
+		STR		r0, [r1]			; soft reset is executed
+
+changed_wtop_mode
+		; Fix the WFE JTAG problem:  WFE operations disconnected the JTAG debugger
+		; 0x18037d08 = 0;  // SCU CPU status = 0
+		LDR		r0, =KHwSYSCTRLPhys
+		MOV		r1, #0
+		STR		r1, [r0, #0x108]
+		
+		ARM_DSB
+		
+		; 0xC0000008 = 0;  // SCU CPU status = 0
+		LDR		r0, =KHwBaseMPcorePrivatePhys
+		MOV		r1, #0
+		STR		r1, [r0, #0x08]
+
+		ARM_DSB
+
+		; Check boot reason in the SCU Memo register
+		; Using ADRL as when CFG_DebugBootRom defined, SysCtrlUnitPhysicalAdr 
+		; beyond range for an ADR instruction.
+		ADRL 	r1, SysCtrlUnitPhysicalAdr
+		LDR		r1, [r1]
+		LDR		r0, [r1]
+
+		; Check if miniboot has run, and we're ready for the coreldr
+		TST		r0, #KtRestartReasonCoreLdr
+		MOVNE	r5, #KCoreLoaderAddress		; Jump into coreldr, NO RETURN!
+		BNE		all_cores_run_r5
+
+		TST		r0,	#KtRestartReasonBootRestart
+		BEQ		check_cpu_id
+		MOV		r5, #KRamTargetAddr
+	
+all_cores_run_r5
+		; There is something for all cores to run (coreldr or new image)
+		; at the address in r5.
+		; But, before we start, we need to get CPU0 to initialise the ASSP
+		; to make RAM accessible, and reset the Memo register.
+		; Otherwise, if the board reboots again (eg. if the user presses the reset switch)
+		; then the BootLoader will attempt to boot the RAM image again.  And after the
+		; reset switch, RAM is not longer valid.
+
+		; Is this the boot processor ?
+		MRC		p15, 0, r0, c0, c0, 5
+		ANDS	r0, r0, #0x0f			; r0 = CPU number 0-3
+		BNE		skip_init_step			; Branch out if CPU != 0 (!= boot processor)
+
+		; Initialise RAM controller etc. Only if NOT running from RAM
+		CMP		PC, #KHwDDR2RamBasePhys
+		BLLS	AsspInitialiseHardware
+
+		; Set SCU Memo register using CPU0
+		ADR 	r1, SysCtrlUnitPhysicalAdr
+		LDR		r1, [r1]
+		MOV		r0, #0
+		STR		r0, [r1]				; clear restart reason to 0
+
+skip_init_step
+		LDR		r0, =KHwSYSCTRLPhys + 0x014 ; Peripheral reset control
+		LDR		r1, [r0]
+		CMP		r1, #0
+		BNE		skip_init_step			; wait for AsspInitialiseHardware to complete
+
+		MOV		pc, r5					; Jump into loaded code, NO RETURN!
+
+	ENDIF
+
+check_cpu_id
+		; Is this the boot processor ?
+		MRC		p15, 0, r0, c0, c0, 5
+		ANDS	r0, r0, #0x0f			; r0 = CPU number 0-3
+		BEQ		IsBootProcessor			; Branch out if CPU 0 (= boot processor)
+
+		; No - this is an AP
+	IF	SMP
+		LDR		r11, =KHwBaseMPcorePrivatePhys	; r11 points to SCU
+		ADD		r8, r11, #0x1000		; Physical address of GIC Distributor
+		ADD		r9, r11, #0x100			; Physical address of GIC CPU Interface
+		B		APResetEntry			; NO RETURN!
+	ELSE
+1
+		mov		r0, #0
+		mcr		p15, 0, r0, c7, c0, 4
+		B		%BA1					; NO RETURN!
+	ENDIF
+
+		; This is the boot processor
+IsBootProcessor
+		; Initialise RAM controller etc. Only if NOT running from RAM
+		CMP		PC, #KHwDDR2RamBasePhys
+		BLLS	AsspInitialiseHardware		
+
+	IF :DEF: CFG_AlternateEntryPoint; NOTE: Bootloader is defined by this macro		
+		; Check for Alternate boot reasons (other than KtRestartReasonBootRestart)
+		ADR		r1, SysCtrlUnitPhysicalAdr
+		LDR		r1,	[r1]
+		LDR		r0,	[r1]
+			
+		TST		r0, #KtRestartReasonNANDImage	; Check for specific nand boot restart reason
+		BNE		GetCoreldr						; try booting from NAND flash, NO RETURN!
+	ENDIF	
+	
+		; Turn on LED for CPU 0 and turn off LEDs for CPU 1, 2, 3
+		GET_ADDRESS	r0, KHwFpgaLedsPhyicalBase, KHwFpgaLedsLinBase
+											; r0 is the address of the 16bit LED register in FPGA, aka FLED
+		MOV		r1, #KHtFpgaLed0			; Turn on LED for CPU0 and turn off the other LEDs
+		STRH	r1, [r0]					; write r1 back to the FLED register
+
+	IF :DEF: CFG_USE_SHARED_MEMORY
+		; Switch on Snoop Control Unit.
+		; The whole procedure for switching to SMP is:
+		;	- Set SCU on. 			: Done here
+		;	- Disable INTs			: Alreday disabled
+		;	- Flush DCache			: See InitCpu
+		;	- Set SMP bit in AUX reg		: See InitCpu
+		;	- Enable INTs			: Later on
+		MOV		r0, #KHwBaseMPcorePrivatePhys
+		MVN		r1, #0
+		STR		r1, [r0, #0x0C]			; invalidate all SCU ways
+		LDR		r1, [r0]
+		ORR		r1, r1, #1				; SCU Enable
+		ORR		r1, r1, #0xFE			; Enable all aliases of everything
+		ORR		r1, r1, #0x1F
+		STR		r1, [r0]
+	ENDIF
+		
+		ADRL	r1, ParameterTable		; pass address of parameter table
+		BL		InitCpu					; initialise CPU/MMU registers, r0..r7 modified
+
+	IF	CFG_InitDebugPort
+		BL		InitDebugPort			; r0..r2 modified  
+	ENDIF
+
+
+;;;;;;;;;;;;
+; Put super page at end of SDRAM for now and set up the required super page values
+;;;;;;;;;;;
+
+;        LDR     r10, =(KHwSdramBaseAddr+(KHwRamSizeMb<<20)-0x2000)
+		BL		CalculateSuperPageAddress
+
+
+		LDR		r7, =CFG_HWVD				        ; variant number from config.inc
+		STR		r7, [r10, #SSuperPageBase_iActiveVariant]
+
+		MOV		r1, #0
+		STR		r1, [r10, #SSuperPageBase_iHwStartupReason]	; reset reason = 0
+
+		ADD		r1, r10, #CpuPageOffset
+		STR		r1, [r10, #SSuperPageBase_iMachineData]
+
+		ADRL	r0, BootTable
+		STR		r0, [r10, #SSuperPageBase_iBootTable]		; set the boot function table
+
+		STR		r12, [r10, #SSuperPageBase_iCodeBase]		; set the base address of bootstrap code
+
+		MRC		p15, 0, r0, c0, c0, 0						; read CPU ID from CP15
+		STR		r0, [r10, #SSuperPageBase_iCpuId]
+		
+		
+		; Process SMRIB from pre-OS Loader and copy to CPU Page.
+		;
+		; r8 = r2 from ResetEntry = Address of block: <SMRIB size><SMRIB entries><...> 
+		; r9 = r3 the CPSR from entry of ResetEntry
+		;
+		; SMRIB address in r2 only valid when cpsr (r3) shows ResetEntry entered
+		; with System CPU mode set. Such a scenario can only be supported from 
+		; local media ROM boots. i.e. boot from NAND
+		;
+  
+		AND		r0, r9, #EMaskMode				 	; Check for System CPU mode
+		CMP		r0, #ESystemMode
+		MVNNE	r0, #0 								; Set iSmrData to KSuperPageAddressFieldUndefined when CPU
+		STRNE	r0, [r10, #SSuperPageBase_iSmrData]	; not in system mode before
+		BNE		NoSMRIB								; i.e. no SMRIB present/defined
+		
+		; Proceed to copy SMRIB to Cpu Page at SP+CpuSmrTableOffset
+		
+		ADD		r1, r10, #CpuSmrTableOffset			; Set the iSmrData member to the SMRIB address 
+		STR		r1, [r10, #SSuperPageBase_iSmrData] ; in the CpuPage, see bootdefs.h, space 
+													; for 8 SSmrBank records, max. Sets r1 for call to WordMove
+
+        ; preparing r0, r2 for call to WordMove                                                    
+        LDR     r0, [r8, #SSmrIF_iSmrBanks]         ; Load SMR Banks starting address from SSmrIF::iSmrBanks
+                                                    ; see kernboot.h 
+        
+        LDR     r2, [r8, #SSmrIF_iSmribSize]        ; Load SMRIB size from SSmrIF::iSmribSize and validate, while
+
+		DWORD	r0, "Variant Bootstrap found SMRIB at"
+		DWORD	r2, "With the size of the SMRIB being"
+		DWORD	r1, "Will copy to                    "
+
+		CMP		r2, #SSmrBank_sz
+		FAULT	LT									; Fault if SMRIB size < 16
+		CMP		r2, #CpuSmrTableTop-CpuSmrTableOffset-16	; -16 to allow space for null entry, 7 entries allowed
+		FAULT	GT									; Fault if SMRIB size > 112 	
+
+		BL		WordMove							; r0=src addr, r1=dest addr, r2=bytes, modifies r0..r3
+													; No need to copy or add zero entry, Cpu page zerod already		  
+NoSMRIB
+
+
+		MOV		pc, r13
+		; END of InitialiseHardware()                
+
+
+
+;*******************************************************************************
+; Initialise Assp H/W (memory controllers)
+;
+; Enter with :
+;		R12 points to ROM header
+;		There is no valid stack
+;
+; Leave with :
+;		R0-R2 modified
+;		Other registers unmodified
+;*******************************************************************************
+	EXPORT	AsspInitialiseHardware
+AsspInitialiseHardware	ROUT
+
+		ADR		r0,Init_data
+1
+		LDR		r1,[r0],#4
+		LDR		r2,[r0],#4
+		CMP		r1, #0
+		BEQ		%FT2
+		STR		r2,[r1]
+		B		%BT1
+2
+		MOV		pc, r14	; return
+
+Init_data
+;*DDR2 Init
+	DCD	0x18021044,0x30022123
+	DCD 0x18021058,0x00000001
+	DCD 0x18021008,0x00000020
+
+;*delay(Reset Status Register dummy write)
+    DCD 0x18037C0C,0x00000000
+    DCD 0x18021008,0x10000004
+    DCD 0x18021008,0x00010002
+    DCD 0x18021008,0x00018002
+    DCD 0x18021008,0x00008002
+    DCD 0x18021008,0X1D480002
+    DCD 0x18021008,0x10000004
+    DCD 0x18021008,0x00000001
+    DCD 0x18021008,0x00000001
+
+;*delay(Reset Status Register dummy write)
+    DCD 0x18037C0C,0x00000000
+    DCD 0x18037C0C,0x00000000
+    DCD 0x18037C0C,0x00000000
+    DCD 0x18021008,0x19480002
+    DCD 0x18021008,0x01308002
+    DCD 0x18021008,0x00000100
+    DCD 0x18021040,0x1485A912
+    DCD 0x18021034,0x00000121
+
+;*SysCon Init
+;*  .word 0x18037C80,0x007F0103
+
+    DCD 0x18037C80,0x00000000
+
+;*ExBus Init
+    DCD 0x1801A000,0x0000004A
+    DCD 0x1801A004,0x08000049
+    DCD 0x1801A008,0x0600004E
+    DCD 0x1801A00C,0x0400004B
+    DCD 0x1801A010,0x1000004A
+    DCD 0x1801A014,0x1400000A
+    DCD 0x1801A020,0x10388E7F
+    DCD 0x1801A024,0x10388E7E
+    DCD 0x1801A028,0x10388E7E
+    DCD 0x1801A02C,0x10388E7F
+    DCD 0x1801A030,0x10388E7E
+    DCD 0x1801A034,0x10388E7E
+
+;*ExBus PCS5 UART-EX Init
+	DCD 0x14020003,0x00
+	DCD 0x14020001,0x00
+	DCD 0x14020002,0x07
+	DCD 0x14020003,0x80
+	DCD 0x14020000,0x1E
+	DCD 0x14020001,0x00
+	DCD 0x14020003,0x03
+	DCD 0x14020004,0x03
+	
+;*ExBus PCS5 CharLED
+	DCD 0x14000000,0x59
+	DCD 0x14000001,0x45
+	DCD 0x14000002,0x53
+	DCD 0x14000003,0x21
+	DCD 0x14000004,0x21
+	DCD 0x14000005,0x20
+	DCD 0x14000006,0x20
+	DCD 0x14000007,0x20
+	
+;*ExBus PCS4 LED
+	DCD 0x10000030,0x00AA
+
+    DCD 0x18037C14,0x00000000; reset release for all peripheral units
+							 ; other cores are waiting for this, must be last
+		
+;*End
+    DCD 0x0,		  0x0
+
+
+;*******************************************************************************
+; Notify an unrecoverable error during the boot process
+;
+; Enter with:
+;	R14 = address at which fault detected
+;
+; Don't return
+;*******************************************************************************
+	EXPORT	Fault
+Fault	ROUT
+		B		BasicFaultHandler	; generic handler dumps registers via debug
+									; serial port
+
+
+
+
+
+;*******************************************************************************
+; Reboot the system
+; This function assumes that CPU#0 is running !!!
+;
+; Enter with:
+;		R0 = reboot reason code
+;
+; Don't return (of course)
+;*******************************************************************************
+	ALIGN	32, 0
+	EXPORT	RestartEntry
+RestartEntry	ROUT
+
+		; Save R0 parameter in HW dependent register which is preserved over reset
+		GET_ADDRESS	r1, KHwSYSCTRLPhys, SysCtrlUnitLinBase
+		STR		r0, [r1]
+
+		; Set SFTRSTP to reset all peripherals and all cores
+		MOV		r0, #1
+		STR		r0, [r1, #0xC]
+		SUB		pc, pc, #8
+
+SysCtrlUnitPhysicalAdr
+		DCD KHwSYSCTRLPhys
+LedPhysicalAdr
+		DCD 0x4010a06
+
+;*******************************************************************************
+; Get a pointer to the list of RAM banks
+;
+; The pointer returned should point to a list of {BASE; MAXSIZE;} pairs, where
+; BASE is the physical base address of the bank and MAXSIZE is the maximum
+; amount of RAM which may be present in that bank. MAXSIZE should be a power of
+; 2 and BASE should be a multiple of MAXSIZE. The generic code will examine the
+; specified range of addresses and determine the actual amount of RAM if any
+; present in the bank. The list is terminated by an entry with zero size.
+;
+; The pointer returned will usually be to constant data, but could equally well
+; point to RAM if dynamic determination of the list is required.
+;
+; Enter with :
+;		R10 points to super page
+;		R12 points to ROM header
+;		R13 points to valid stack
+;
+; Leave with :
+;		R0 = pointer
+;		Nothing else modified
+;*******************************************************************************
+GetRamBanks	ROUT
+		ADR		r0, %FT1
+		MOV		pc, lr
+1
+		DCD		KHwDDR2RamBasePhys | RAM_VERBATIM, RamBank0MaxSize
+		DCD		0,0				; terminator
+
+
+
+
+
+;*******************************************************************************
+; Get a pointer to the list of ROM banks
+;
+; The pointer returned should point to a list of entries of SRomBank structures,
+; usually declared with the ROM_BANK macro.
+; The list is terminated by a zero size entry (four zero words)
+;
+; ROM_BANK	PB, SIZE, LB, W, T, RS, SS
+; PB = physical base address of bank
+; SIZE = size of bank
+; LB = linear base if override required - usually set this to 0
+; W = bus width (ROM_WIDTH_8, ROM_WIDTH_16, ROM_WIDTH_32)
+; T = type (see TRomType enum in kernboot.h)
+; RS = random speed
+; SS = sequential speed
+;
+; Only PB, SIZE, LB are used by the rest of the bootstrap.
+; The information given here can be modified by the SetupRomBank call, if
+; dynamic detection and sizing of ROMs is required.
+;
+; Enter with :
+;		R10 points to super page
+;		R12 points to ROM header
+;		R13 points to valid stack
+;
+; Leave with :
+;		R0 = pointer
+;		Nothing else modified
+;*******************************************************************************
+GetRomBanks	ROUT
+		ADR		r0, %FT1
+		MOV		pc, lr
+1
+	IF	CFG_MMDirect
+		ROM_BANK	KRamTargetAddr,		0x08000000,			0, ROM_WIDTH_32, ERomTypeXIPFlash, 0, 0	; image in RAM
+	ENDIF
+;		ROM_BANK	PrimaryRomBase,		PrimaryRomSize,		0, ROM_WIDTH_32, ERomTypeXIPFlash, 0, 0
+;		ROM_BANK	ExtensionRomBase,	ExtensionRomSize,	0, ROM_WIDTH_32, ERomTypeXIPFlash, 0, 0
+		DCD		0,0,0,0			; terminator
+
+
+
+
+
+;*******************************************************************************
+; Get a pointer to the list of hardware banks
+;
+; The pointer returned should point to a list of hardware banks declared with
+; the HW_MAPPING and/or HW_MAPPING_EXT macros. A zero word terminates the list.
+; For the direct memory model, all hardware on the system should be mapped here
+; and the mapping will set linear address = physical address.
+; For the moving or multiple model, only the hardware required to boot the kernel
+; and do debug tracing needs to be mapped here. The linear addresses used will
+; start at KPrimaryIOBase and step up as required with the order of banks in
+; the list being maintained in the linear addresses used.
+;
+; HW_MAPPING PB, SIZE, MULT
+;	This declares a block of I/O with physical base PB and address range SIZE
+;	blocks each of which has a size determined by MULT. The page size used for
+;	the mapping is determined by MULT. The linear address base of the mapping
+;	will be the next free linear address rounded up to the size specified by
+;	MULT.
+;	The permissions used for the mapping are the standard I/O permissions (BTP_Hw).
+;
+; HW_MAPPING_EXT PB, SIZE, MULT
+;	This declares a block of I/O with physical base PB and address range SIZE
+;	blocks each of which has a size determined by MULT. The page size used for
+;	the mapping is determined by MULT. The linear address base of the mapping
+;	will be the next free linear address rounded up to the size specified by
+;	MULT.
+;	The permissions used for the mapping are determined by a BTP_ENTRY macro
+;	immediately following this macro in the HW bank list or by a DCD directive
+;	specifying a different standard permission type.
+;
+; HW_MAPPING_EXT2 PB, SIZE, MULT, LIN
+;	This declares a block of I/O with physical base PB and address range SIZE
+;	blocks each of which has a size determined by MULT. The page size used for
+;	the mapping is determined by MULT. The linear address base of the mapping
+;	is specified by the LIN parameter.
+;	The permissions used for the mapping are the standard I/O permissions (BTP_Hw).
+;
+; HW_MAPPING_EXT3 PB, SIZE, MULT, LIN
+;	This declares a block of I/O with physical base PB and address range SIZE
+;	blocks each of which has a size determined by MULT. The page size used for
+;	the mapping is determined by MULT. The linear address base of the mapping
+;	is specified by the LIN parameter.
+;	The permissions used for the mapping are determined by a BTP_ENTRY macro
+;	immediately following this macro in the HW bank list or by a DCD directive
+;	specifying a different standard permission type.
+;
+; Configurations without an MMU need not implement this function.
+;
+; Enter with :
+;		R10 points to super page
+;		R12 points to ROM header
+;		R13 points to valid stack
+;
+; Leave with :
+;		R0 = pointer
+;		Nothing else modified
+;*******************************************************************************
+GetHwBanks	ROUT
+		ADR		r0, %FT1
+		MOV		pc, lr
+
+1
+	IF	CFG_MMDirect
+		HW_MAPPING		KHwLANPhys				,1,	HW_MULT_1M		; LAN, FPGA
+		HW_MAPPING		0x18000000				,1,	HW_MULT_1M		; I/O registers @ 18000000
+		HW_MAPPING		KHwBaseMPcorePrivatePhys,1,	HW_MULT_1M		; MPCORE private range
+	ELSE
+		HW_MAPPING		KHwUART0Phys			,1,	HW_MULT_4K		; Mapped at KPrimaryIOBase + 0
+		HW_MAPPING		KHwBaseMPcorePrivatePhys,2,	HW_MULT_4K		; Mapped at KPrimaryIOBase + 1000h
+		HW_MAPPING		KHwTimer0Phys			,2,	HW_MULT_4K		; Mapped at KPrimaryIOBase + 3000h
+		HW_MAPPING		KHwDispPhys				,4,	HW_MULT_4K		; Mapped at KPrimaryIOBase + 5000h
+		HW_MAPPING		KHwI2CPhys				,2, HW_MULT_4K		; Mapped at KPrimaryIOBase + 9000h
+		HW_MAPPING		KHwFPGAPhys				,1, HW_MULT_4K		; Mapped at KPrimaryIOBase + B000h
+		HW_MAPPING		KHwSPDIFPhys			,1, HW_MULT_4K		; Mapped at KPrimaryIOBase + C000h
+		HW_MAPPING		KHwSDPhys				,1, HW_MULT_4K		; Mapped at KPrimaryIOBase + D000h
+		HW_MAPPING		KHwAHBEXDMACPhys		,6, HW_MULT_4K		; Mapped at KPrimaryIOBase + E000h
+		HW_MAPPING		KHwLANPhys				,1, HW_MULT_4K		; Mapped at KPrimaryIOBase + 14000h
+		HW_MAPPING		KHwGPIOPhys				,1, HW_MULT_4K		; Mapped at KPrimaryIOBase + 15000h
+		HW_MAPPING		KHwAHB32PCI_ExtPhys		,2, HW_MULT_4K		; Mapped at KPrimaryIOBase + 16000h
+		HW_MAPPING		KHwUSBHPhys				,2, HW_MULT_4K		; Mapped at KPrimaryIOBase + 18000h
+		HW_MAPPING		KHwAXI64DMACPhys		,1,	HW_MULT_4K		; Mapped at KPrimaryIOBase + 1A000h
+																	; Next to be mapped at KPrimaryIOBase + 1B000h
+	ENDIF
+		DCD			0												; Terminator
+
+;*******************************************************************************
+; Set up RAM bank
+;
+; Do any additional RAM controller initialisation for each RAM bank which wasn't
+; done by InitialiseHardware.
+; Called twice for each RAM bank :-
+;	First with R3 = 0xFFFFFFFF before bank has been probed
+;	Then, if RAM is present, with R3 indicating validity of each byte lane, ie
+;	R3 bit 0=1 if D0-7 are valid, bit1=1 if D8-15 are valid etc.
+; For each call R1 specifies the bank physical base address.
+;
+; Enter with :
+;		R10 points to super page
+;		R12 points to ROM header
+;		R13 points to stack
+;		R1 = physical base address of bank
+;		R3 = width (bottom 4 bits indicate validity of byte lanes)
+;			 0xffffffff = preliminary initialise
+;
+; Leave with :
+;		No registers modified
+;*******************************************************************************
+SetupRamBank	ROUT
+		MOV		pc, lr
+
+
+
+
+
+;*******************************************************************************
+; Set up ROM bank
+;
+; Do any required autodetection and autosizing of ROMs and any additional memory
+; controller initialisation for each ROM bank which wasn't done by
+; InitialiseHardware.
+;
+; The first time this function is called R11=0 and R0 points to the list of
+; ROM banks returned by the BTF_RomBanks call. This allows any preliminary setup
+; before autodetection begins.
+;
+; This function is subsequently called once for each ROM bank with R11 pointing
+; to the current information held about that ROM bank (SRomBank structure).
+; The structure pointed to by R11 should be updated with the size and width
+; determined. The size should be set to zero if there is no ROM present in the
+; bank.
+;
+; Enter with :
+;		R10 points to super page
+;		R12 points to ROM header
+;		R13 points to stack
+;		R11 points to SRomBank info for this bank
+;		R11 = 0 for preliminary initialise (all banks)
+;
+; Leave with :
+;		Update SRomBank info with detected size/width
+;		Set the size field to 0 if the ROM bank is absent
+;		Can modify R0-R4 but not other registers
+;
+;*******************************************************************************
+SetupRomBank	ROUT
+		MOV		pc, lr
+
+
+
+
+
+;*******************************************************************************
+; Reserve physical memory
+;
+; Reserve any physical RAM needed for platform-specific purposes before the
+; bootstrap begins allocating RAM for page tables/kernel data etc.
+;
+; There are two methods for this:
+;	1.	The function ExciseRamArea may be used. This will remove a contiguous
+;		region of physical RAM from the RAM bank list. That region will never
+;		again be identified as RAM.
+;	2.	A list of excluded physical address ranges may be written at [R11].
+;		This should be a list of (base,size) pairs terminated by a (0,0) entry.
+;		This RAM will still be identified as RAM by the kernel but will not
+;		be allocated by the bootstrap and will subsequently be marked as
+;		allocated by the kernel immediately after boot.
+;
+; Enter with :
+;		R10 points to super page
+;		R11 indicates where preallocated RAM list should be written.
+;		R12 points to ROM header
+;		R13 points to stack
+;
+; Leave with :
+;		R0-R3 may be modified. Other registers should be preserved.
+;*******************************************************************************
+ReservePhysicalMemory	ROUT
+;	IF :DEF: CFG_AlternateEntryPoint
+;	IF 0
+;		STMFD	sp!, {r9,r11,lr}
+;		LDR		r0, =KRamTargetAddr		; reserve the first 64MB RAM for the image to download into.
+;		MOV		r1, #0x4000000			; 64MB
+;		MOV		r2, #0
+;		MOV		r11, #0
+;		LDR		r9, [r10, #SSuperPageBase_iRamBootData]
+;		BL		ExciseRamArea							; remove RAM
+;		LDMFD	sp!, {r9,r11,pc}
+;	ENDIF
+		MOV		pc, lr
+
+	IF	CFG_MMDirect
+	INIT_NUMERIC_CONSTANT	KTTBRExtraBits, 0x02
+	ELSE
+	IF SMP
+	INIT_NUMERIC_CONSTANT	KTTBRExtraBits, 0x02
+	ELSE
+	INIT_NUMERIC_CONSTANT	KTTBRExtraBits, 0x08
+	ENDIF
+	ENDIF
+
+
+;*******************************************************************************
+; Return parameter specified by R0 (see TBootParam enum)
+;
+; Enter with :
+;		R0 = parameter number
+;
+; Leave with :
+;		If parameter value is supplied, R0 = value and N flag clear
+;		If parameter value is not supplied, N flag set. In this case the
+;		parameter may be defaulted or the system may fault.
+;		R0,R1,R2 modified. No other registers modified.
+;
+;*******************************************************************************
+GetParameters ROUT
+		ADR		r1, ParameterTable
+		B		FindParameter
+ParameterTable
+		; Include any parameters specified in TBootParam enum here
+		; if you want to override them.
+		DCD		BPR_TTBRExtraBits,	KTTBRExtraBits
+	IF	CFG_MMDirect
+		DCD		BPR_UncachedLin,	0x7F000000	; parameter number, parameter value
+	IF	SMP
+		DCD		BPR_APBootLin,		0x7F001000	; parameter number, parameter value
+	ENDIF
+;	IF	CFG_BootLoader
+;		DCD		BPR_BootLdrImgAddr,	KRamImageAddr
+;	ENDIF
+	ENDIF
+		DCD		-1								; terminator
+
+;*******************************************************************************
+; Do final platform-specific initialisation before booting the kernel
+;
+; Typical uses for this call would be:
+;	1.	Mapping cache flushing areas
+;	2.	Setting up pointers to routines in the bootstrap which are used by
+;		the variant or drivers (eg idle code).
+;
+; Enter with :
+;		R10 points to super page
+;		R11 points to TRomImageHeader for the kernel
+;		R12 points to ROM header
+;		R13 points to stack
+;
+; Leave with :
+;		R0-R9 may be modified. Other registers should be preserved.
+;
+;*******************************************************************************
+FinalInitialise ROUT
+		STMFD	sp!, {lr}
+
+	IF	SMP
+; Handshake with APs
+
+	IF	CFG_MMDirect
+		LDR		r7, =KHwBaseMPcorePrivatePhys		; R7 points to SCU (physical address for direct memory model)
+	ELSE
+		LDR		r7, =KPrimaryIOBase + 0x1000	; R7 points to SCU (virtual address for other memory models)
+	ENDIF
+		ADD		r8, r7, #0x1000					; Virtual address of GIC Distributor
+		ADD		r9, r7, #0x100					; Virtual address of GIC CPU Interface
+		LDR		r5, [r7, #4]					; SCU configuration register
+		DWORD	r5, "SCU Config"
+		AND		r5, r5, #3
+		ADD		r5, r5, #1						; r5 = number of CPUs
+		DWORD	r5, "NCPUs"
+		MOV		r6, #0							; CPU number
+		B		%FA2
+1
+		DWORD	r6, "CPU"
+		BL		HandshakeAP						; handshake with this AP
+2
+		; Turn on LED for this CPU (CPU0==LED0, etc...)
+		GET_ADDRESS	r0, KHwFpgaLedsPhyicalBase, KHwFpgaLedsLinBase
+												; r0 is the address of the 16 bit LED register in FPGA, aka FLED
+		LDRH	r1, [r0]						; read the contents of FLED into r1
+		MOV		r2, #KHtFpgaLed0
+		MOV		r2, r2, LSL r6					; r2 is the LED value we want to OR in (ie, 1<<CPU number)
+		ORR		r1, r1, r2						; r1 = r1 | r2
+		STRH	r1, [r0]						; write r1 back to the FLED register
+
+		ADD		r6, r6, #1						; r6 = CPU number of next AP
+		CMP		r6, r5							; if equal to number of CPUs, finished
+		BLO		%BA1							; else do next AP
+	ENDIF
+
+		LDMFD	sp!, {pc}
+
+;*******************************************************************************
+; Output a character to the debug port
+;
+; Enter with :
+;		R0 = character to output
+;		R13 points to valid stack
+;
+; Leave with :
+;		nothing modified
+;*******************************************************************************
+DoWriteC	ROUT
+	IF	CFG_DebugBootRom
+		STMFD	sp!, {r1,r2,lr}
+		BL		GetDebugPortBase	; r1 = base address of debug port
+
+		; wait for debug port to be ready for data
+1
+		LDR		r2, [r1, #Serial_LSR]
+		TST		r2, #0x20
+		BEQ		%BT1
+		
+		; output character to debug port
+		STR		r0, [r1, #Serial_THR]
+
+		LDMFD	sp!, {r1,r2,pc}
+	ELSE
+		MOV		pc, lr
+	ENDIF
+
+
+	IF	CFG_InitDebugPort
+;*******************************************************************************
+; Initialise the debug port
+;
+; Enter with :
+;		R12 points to ROM header
+;		There is no valid stack
+;
+; Leave with :
+;		R0-R2 modified
+;		Other registers unmodified
+;*******************************************************************************
+InitDebugPort	ROUT
+		MOV     r0, lr
+		BL		GetDebugPortBase			; r1 = base address of debug port
+
+		LDR		r2, [r12, #TRomHeader_iDebugPort]
+		MOVS	r2, r2, LSL #24				; C=1 if high speed, C=0 low speed
+
+		; set up debug port
+		MOV		r2, #0x83
+		STR		r2, [r1, #Serial_LCR]
+		MOVCS	r2, #KBaudRateDiv_230400
+		MOVCC	r2, #KBaudRateDiv_default
+		STR		r2, [r1, #Serial_DLL]
+		MOV		r2, #0
+		STR		r2, [r1, #Serial_DLH]
+		MOV		r2, #0x03
+		STR		r2, [r1, #Serial_LCR]
+
+		MOV		pc, r0
+
+;*******************************************************************************
+; Get the base address of the debug UART
+;	It is uart0 (for TRomHeader::iDebugPort ==0) or uart1 otherwise
+;	Returns physical or linear address, depending on the state of MMU.
+;
+; Enter with :
+;		R12 points to ROM header
+;		There may be no stack
+;
+; Leave with :
+;		R1 = base address of port
+;		No other registers modified
+;*******************************************************************************
+GetDebugPortBase	ROUT
+		LDR		r1, [r12, #TRomHeader_iDebugPort]
+		CMP		r1, #0x100
+		BEQ		%FA2				; port 0 at 230400
+		CMP		r1, #0
+		BNE		%FA1				; skip if not port 0
+2
+		GET_ADDRESS	r1, KHwUART0Phys, Serial0LinBase
+		MOV		pc, lr
+1
+		GET_ADDRESS	r1, KHwUART1Phys, Serial1LinBase
+		MOV		pc, lr
+
+	ENDIF	; CFG_InitDebugPort
+
+;*******************************************************************************
+; BOOT FUNCTION TABLE
+;*******************************************************************************
+
+BootTable
+		DCD	DoWriteC				; output a debug character
+		DCD	GetRamBanks				; get list of RAM banks
+		DCD	SetupRamBank			; set up a RAM bank
+		DCD	GetRomBanks				; get list of ROM banks
+		DCD	SetupRomBank			; set up a ROM bank
+		DCD	GetHwBanks				; get list of HW banks
+		DCD	ReservePhysicalMemory	; reserve physical RAM if required
+		DCD	GetParameters			; get platform dependent parameters
+		DCD	FinalInitialise			; Final initialisation before booting the kernel
+		DCD HandleAllocRequest		; allocate memory		
+		DCD	GetPdeValue				; usually in generic code
+		DCD	GetPteValue				; usually in generic code
+		DCD	PageTableUpdate			; usually in generic code
+		DCD	EnableMmu				; Enable the MMU (usually in generic code)
+
+	IF :DEF: CFG_USE_SHARED_MEMORY
+SharedMemory	EQU		1
+	ELSE
+SharedMemory	EQU		0
+	ENDIF
+
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RORO, MEMORY_FULLY_CACHED,       	1,  1,  0,  SharedMemory	; ROM
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RWNO, MEMORY_FULLY_CACHED,       	0,  1,  0,  SharedMemory	; kernel data/stack/heap
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RWNO, MEMORY_FULLY_CACHED,       	0,  1,  0,  SharedMemory	; super page/CPU page
+	IF	SMP
+	    BTP_ENTRY   CLIENT_DOMAIN, PERM_RWNO, MEMORY_UNCACHED,				0,  1,  0,  SharedMemory	; page directory/tables
+	ELSE
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RWNO, MEMORY_FULLY_CACHED,			0,  1,  0,  SharedMemory	; page directory/tables
+	ENDIF
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RONO, MEMORY_FULLY_CACHED,       	1,  1,  0,  SharedMemory	; exception vectors
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RWNO, MEMORY_STRONGLY_ORDERED,      0,  1,  0,  SharedMemory	; hardware registers
+		DCD         0                                                       			 				; unused (minicache flush)
+		DCD         0                                                         							; unused (maincache flush)
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RWNO, MEMORY_FULLY_CACHED,       	0,  1,  0,  SharedMemory	; page table info
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RWRW, MEMORY_FULLY_CACHED,       	1,  1,  0,  SharedMemory	; user RAM
+		BTP_ENTRY   CLIENT_DOMAIN, PERM_RONO, MEMORY_STRONGLY_ORDERED,      1,  1,  0,  SharedMemory	; temporary identity mapping
+		BTP_ENTRY   CLIENT_DOMAIN, UNC_PERM,  MEMORY_STRONGLY_ORDERED,      0,  1,  0,  SharedMemory	; uncached
+
+
+		END
+
+