#include <sysreg.h>
#include "hal_1967VN028.h"

#define SDRAM_MODEL_48LC32M16

#ifdef SDRAM_MODEL_48LC32M16
	#define SDRCON_PG	    SDRCON_PG1K
	#define SDRAM_SIZE	 	0x04000000  // 64 MWord (256 MByte)
#endif

#define SDRAM_START  	0x40000000	// start address of SDRAM

//#define FOREVER_REPEAT
#define NUM_OF_REPEAT	1

#define PROC_ADRR(id) ( 0x10000000 + ( id << 26)  )
#define VAR_IN_PROC(id, var) ( *(unsigned int*) (PROC_ADRR(id) + (unsigned int)(&var)) )

unsigned int errFlag = 0, tmp, FlagInitSDRAM = 0;

void ErrorStop(unsigned int testNumber){
	errFlag = testNumber;
	if (testNumber) __builtin_sysreg_write(__FLAGREG,0xCF);
	while(1);
}

int main(void)
{
	unsigned int i, testCounter = 0, NumOfRepeat;
	unsigned int *sdramPointer = (unsigned int *) SDRAM_START;
	unsigned int sdrconValue, sysconValue;

	NumOfRepeat = NUM_OF_REPEAT;
	__builtin_sysreg_write(__FLAGREG, 0xEF); 	//Test Start

	// Init SYSCON and SDRCON
	sysconValue = SYSCON_MP_WID64 | SYSCON_MEM_WID64 |
			      SYSCON_MSH_PIPE2 | SYSCON_MSH_WT0 | SYSCON_MSH_IDLE |
				  SYSCON_MS1_PIPE1 | SYSCON_MS1_WT0 | SYSCON_MS1_IDLE |
                  SYSCON_MS0_SLOW | SYSCON_MS0_WT3 | SYSCON_MS0_IDLE;
	HAL_SYS_SRAMEnable(sysconValue);

	sdrconValue = SDRCON_INIT | SDRCON_RAS2PC5 | SDRCON_PC2RAS2 |
            	  SDRCON_REF1100 | SDRCON_PG | SDRCON_CLAT2 | SDRCON_ENBL;

	tmp = __builtin_sysreg_read(__SYSTAT);
	//if (tmp != 0)
	//	while( VAR_IN_PROC(0x00, FlagInitSDRAM) == 0 ){}

	HAL_SYS_SDRAMEnable(sdrconValue);

	if(!tmp)
		FlagInitSDRAM = 1;

	while(1)
		tmp = __builtin_sysreg_read(__SYSTAT);

#ifdef FOREVER_REPEAT
while(1){
#else
while(NumOfRepeat--){
#endif

	//----------------------------------------------------------------------------------------------------//
	//Test 1. Rotation 0x00000000 and 0xFFFFFFFF
	testCounter++;
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		*(sdramPointer + i) = 0x00000000;
		*(sdramPointer + i + 1) = 0xFFFFFFFF;
	}
	//Check test 1
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		if (( *(sdramPointer + i) != 0x00000000 ) || ( *(sdramPointer + i + 1) != 0xFFFFFFFF ))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 2. Rotation 0xAAAAAAAA and 0x55555555
	testCounter++;
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		*(sdramPointer + i) = 0xAAAAAAAA;
		*(sdramPointer + i + 1) = 0x55555555;
	}
	//Check test 2
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		if (( *(sdramPointer + i) != 0xAAAAAAAA ) || ( *(sdramPointer + i + 1) != 0x55555555 ))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 3. Rotation 0x0000FFFF and 0xFFFF0000
	testCounter++;
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		*(sdramPointer + i) = 0x0000FFFF;
		*(sdramPointer + i + 1) = 0xFFFF0000;
	}
	//Check test 3
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		if (( *(sdramPointer + i) != 0x0000FFFF ) || ( *(sdramPointer + i + 1) != 0xFFFF0000 ))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 4. All bits = 0
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) = 0x00000000;
	}
	//Check test 4
	for(i=0;i<SDRAM_SIZE;i++){
		if ( *(sdramPointer + i) != 0x00000000 )
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 5. All bits = 1
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) = 0xFFFFFFFF;
	}
	//Check test 5
	for(i=0;i<SDRAM_SIZE;i++){
		if ( *(sdramPointer + i) != 0xFFFFFFFF )
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 6. Write/Read Address
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) = (unsigned int) sdramPointer + i;
	}
	//Check test 6
	for(i=0;i<SDRAM_SIZE;i++){
		if (*(sdramPointer + i) != (unsigned int) sdramPointer + i)
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 7. Null Shifter
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) =  ~(1<<(i&0x1F));
	}
	//Check test 7
	for(i=0;i<SDRAM_SIZE;i++){
		if (*(sdramPointer + i) !=  ~(1<<(i&0x1F)))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 8. One Shifter
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) =  (1<<(i&0x1F));
	}
	//Check test 8
	for(i=0;i<SDRAM_SIZE;i++){
		if (*(sdramPointer + i) !=  (1<<(i&0x1F)))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 9. Pseudo-random counter
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++)
		*(sdramPointer + i) = (i<<24)+(i<<18)+i;
	//check
	for(i=0;i<SDRAM_SIZE;i++){
		if(*(sdramPointer + i) != (i<<24)+(i<<18)+i)
			ErrorStop(testCounter);
	}

	//Check pointer
	testCounter++;
	if ((unsigned int) sdramPointer != 0x40000000) ErrorStop(testCounter);
}

	//End all tests
	__builtin_sysreg_write(__FLAGREG, 0x0F); //Test passed
	while(1);
}

