#include <machine/asm.h>
#include <arm/armreg.h>
#include <arm/arm32/pte.h>


	.section .start,"ax",%progbits

	.global	_C_LABEL(beast_start)
_C_LABEL(beast_start):

        /*
         * We will go ahead and disable the MMU here so that we don't
         * have to worry about flushing caches, etc.
         *
         * Note that we may not currently be running VA==PA, which means
         * we'll need to leap to the next insn after disabing the MMU.
         */

	/* ADR is a pseudo instruction - LDR Rx, =label
	 * Load unmapped label address into R8 register
	 *
	 */
	adr     r8, Lunmapped

	/* BIC - bit clear instruction
	 * BIC{<cond>}{S} <Rd> <Rn> <shifter_operand>
	 * Bitwise AND of <Rn> with complement of value of <shifter_operand>
	 * Stores ther result in <Rd>
	 *
	 * R8 = (R8) AND ~(0xff000000)
	 */
	bic     r8, r8, #0xff000000     /* clear upper 8 bits */



	/*
	 * Setup coprocessor 15.
	 */

	/* MRC - Move to ARM Register from Coprocesor
	 *
	 * MRC{<cond>} <coproc>, <optcode_1>, <Rd>, <CRn>, <CRm> {, <optcode_2>}
	 *
	 * <coproc> 	-	p15	; CP15 registers
	 * <optcode_1> 	-	0
	 * <Rd>		-	R2 	; ARM destination register
	 * <CRn>	-	C1	; Coprocesor register - first operand
	 * <CRm>	-	C0	; Aditional coprocessor source or destination register
	 * <optcode_2>	-	0
	 * 
	 *
	 *
	 * 	defined in arch/arm/include/armreg.h
	 *
	 * 		MMU register 1 (Control Register):
	 *			- M (bit[0]):	0 - MMU disable
	 *					1 - MMU enable
	 *			- A (bit[1]):	0 - Alignment fault checking disabled
	 *					1 - Alignment fault checking enabled
	 *			- S (bit[8]):	System protection bit
	 *			- R (bit[9]):	ROM protection bit
	 *
	 * 		MMU register 2 (Translation Table Base):
	 *			
	 *			3                      1 1                 0
	 *			1                      4 3                 0
	 *			+-----------------------+-------------------+
	 *			|        TTB            |     UNP/SBZP      |
	 *			+-----------------------+-------------------+
	 *			
	 *			TTB - address of the currntly active first-level translation table
	 *			UNP - UNPREDICTABLE
	 *			 and  is ignored
	 *	
	 * 		MMU register 3 (Domain Access Control):
	 *			16 domain (2bits field) available.
	 *
	 * 		MMU register 4 (Reserved):
	 * 		MMU register 5 (Fault status):
	 * 		MMU register 6 (Fault address):
	 * 		MMU register 8 (TLB functions):
	 * 		MMU register 10(TLB lockdown):
	 *
	 */		
	mrc     p15, 0, r2, c1, c0, 0

	/* Disable MMU bit 
	 *
	 *	#define CPU_CONTROL_MMU_ENABLE 0x00000001
	 * 
	 */
	bic     r2, r2, #CPU_CONTROL_MMU_ENABLE

	/* MCR - Move to Coprocesor from ARM Register */
	mcr     p15, 0, r2, c1, c0, 0

        nop
        nop
        nop
	
	/* Jump to unmapped */
	mov     pc, r8                  /* Heave-ho! */

Lunmapped:
	/*
	 * We want to construct a memory map that maps us
	 * VA==PA (SDRAM at 0x00000000). We create these
	 * mappings uncached and unbuffered to be safe.
	 */

	/*
	 * Step 1: Map the entire address space VA==PA.
	 */
	/* load table label address into R4 */
	adr	r4, Ltable
	/* R0 == 0x4000 */
	ldr	r0, [r4]			/* r0 = &l1table */

	/* defined in arch/arm/include/arm32/pte.h */
	mov	r1, #(L1_TABLE_SIZE / 4)	/* 4096 entry */
	mov	r2, #(L1_S_SIZE)		/* 1MB / section */
	mov	r3, #(L1_S_AP(AP_KRW))		/* kernel read/write */
	orr	r3, r3, #(L1_TYPE_S)		/* L1 entry is section */
	
	/* 0x4000 - 0x00000402 
	 * 0x4004 - 0x00100402
	 * 0x4008 - 0x00200402
	 * 0x400C - 0x00300402
	   ...
	 */
	
1:
	str	r3, [r0], #0x04
	add	r3, r3, r2
	subs	r1, r1, #1
	bgt	1b
	

        /*
         * Step 2: Map VA 0xc0000000->0xc7fffffc to PA 0x00000000->0x07fffffc.
         */
	/* R0 = 0x4000 */
	ldr     r0, [r4]
	/* R0 = 0x7000 */
	add     r0, r0, #(0xc00 * 4)            /* offset to 0xc00xxxxx */

	mov     r1, #0x80                        /* 128MB */

	/* 
	 *	#define L1_S_AP(x)      ((x) << 10)   - access permission 
	 *	AP_KRW	0x01	- kernel read/write
	 *
	 */
	mov     r3, #(L1_S_AP(AP_KRW)) 
	orr     r3, r3, #(L1_TYPE_S)		/* L1 descriptor - section 0x02 */

	/*
	 * (0x7000-0x4000)/4 = 0xC00
	 * 0x7000 <==> 0xC000000
	 * 0x7000 - 0x00000402
	 * 0x7004 - 0x00100402
	 * 0x7008 - 0x00200402	
	 * ....
	 */

1:
        str     r3, [r0], #0x04
        add     r3, r3, r2
        subs    r1, r1, #1
        bgt     1b

	/*
	 *	First-level descriptor (can be section, coarse page table, fine page table):
	 *	Here section :)
	 *	
	 *      3                                   1 1                                        0 0 0
	 *      1                                   4 3                                        2 1 0 
	 *     +-------------------------------------+------------------------------------------+-+-+ 
	 *     |      Translation base[31:14]        |   Modified virtual address[31:20]        |0|0|
	 *     +-------------------------------------+------------------------------------------+-+-+
	 *
	 *
	 *	Translation table base - CP15/C2 register - must reside on 16KB boundary
	 *
	 *	Eg.
	 *	Vadd = 		0xC000 2000
	 *	Tb =   		0x0000 4000
	 *	FL-dsc[31:14] =	0b 0000 0000 0000 0000 01
	 *	MVA[31:20]    = 0b 			 11 0000 0000 00
	 *	FL-dsc	      = 0b 0000 0000 0000 0000 0111 0000 0000 0000 (0x7000)
	 * 
	 *	Translating section reference (*0x7000 == 0x0000 0402):	
	 *	 
	 *      3                                  2 1              1 1 1 0 0       0 0 0 0 0 0  
	 *      1                                  0 9              2 1 0 9 8       5 4 3 2 1 0
	 *     +------------------------------------+----------------+---+-+---------+-+-+-+-+-+
	 *     |     Section base address           |       SBZ      | AP|0|  Domain |1|C|B|1|0|
	 *     +------------------------------------+----------------+---+-+---------+-+-+-+-+-+
	 *	AP - Access Permision for this section
	 *	Domain - one of 16 possible domains
	 *	CB - write-back cachable, write-through cachable, noncached buffered, noncached nonbuffered
	 *
	 *
	 *     PHYSICAL ADDRESS	( 0x0000 2000 ):
	 *
	 *      3                                  2 1                                         0
	 *      1                                  0 9                                         0
	 *     +------------------------------------+-------------------------------------------+
	 *     |     Section base address           |     Modified virtual address[19:0]        |
	 *     +------------------------------------+-------------------------------------------+
	 */



	/* OK!  Page table is set up.  Give it to the CPU. */
	adr	r0, Ltable
	ldr	r0, [r0]
	mcr	p15, 0, r0, c2, c0, 0

	/* Flush the old TLBs, just in case. */
	mcr	p15, 0, r0, c8, c7, 0

	/* Set the Domain Access register.  Very important! */
	mov	r0, #1
	mcr	p15, 0, r0, c3, c0, 0

	/* Get ready to jump to the "real" kernel entry point... */
	ldr	r1, Lstart
	mov	r1, r1			/* Make sure the load completes! */

	/* OK, let's enable the MMU. */
	mrc	p15, 0, r2, c1, c0, 0
	orr	r2, r2, #CPU_CONTROL_MMU_ENABLE
	mcr	p15, 0, r2, c1, c0, 0

	nop
	nop
	nop

	/* CPWAIT sequence to make sure the MMU is on... */
	mrc	p15, 0, r2, c2, c0, 0	/* arbitrary read of CP15 */
	mov	r2, r2			/* force it to complete */
	mov	pc, r1			/* leap to kernel entry point! */

Ltable:
	.word	0x4000


/* From locore.S - arch/arm/arm32/locore.S */

Lstart:
	.word	start