/******************************************************************************
 *  ============================================================================
 *  @n   (C) Copyright 2011, 2012, Texas Instruments, Inc.
 *  @n   All Rights Reserved.
 *  @n
 *  @n GENERAL DISCLAIMER
 *  @n ------------------ 
 *  @n All software and related documentation is provided "AS IS" and without   
 *  @n warranty or support of any kind and Texas Instruments expressly disclaims
 *  @n all other warranties, express or implied, including, but not limited to, 
 *  @n the implied warranties of merchantability and fitness for a particular   
 *  @n purpose.  Under no circumstances shall Texas Instruments be liable for   
 *  @n any incidental, special or consequential damages that result from the    
 *  @n use or inability to use the software or related documentation, even if   
 *  @n Texas Instruments has been advised of the liability.                     
 *  ============================================================================
 ******************************************************************************
  File Name     : Robust_System.c
  Version       : Initial Draft
  Author        : Brighton Feng
  Created       : 2012/10/5
  Last Modified :
  Description   : Robust_System.c
       This project shows how to use the protection hardware to build the robust
    system on KeyStone device
  Function List :
              main
  History       :
  1.Date        : 2012/10/5
    Author      : Brighton Feng
    Modification: Created file
  2.Date        : July 24, 2013
    Author      : Andy Yin
    Modification: update for K2
  3.Date         : 2014/4/21
    Author       : Brighton Feng
    Modification : Update for K2L
******************************************************************************/
#include <stdio.h>
#include <string.h>

#include "K2_common.h"
#include "K2_Board_Init.h"
#include "Robust_MNav_Init.h"
#include "Robust_MSMC_RAM_EDC.h"
#include "Robust_DDR_ECC.h"
#include "Robust_MSMC_SMS_MP.h"
#include "Robust_DDR_SES_MP.h"
#include "Robust_watch_dog.h"
#include "Robust_Peripherals_MPU.h"
#include "Robust_EDMA.h"
#include "Robust_Reserved_Space.h"

#define SMS_MSMC_RAM_MP_TEST 	1
#define SES_DDR_MP_TEST 		1
#define PERIPHERAL_MP_TEST 		1
#define MSMC_RAM_EDC_TEST 		1
#define DDR_ECC_TEST 			1 	/*only for EVM with ECC memory, NOT supported by K2H, K2K rev 1.x*/
#define EDMA_ERROR_TEST 		1
#define WATCH_DOG_TEST 			1
#define RESERVED_SPACE_TEST 	1

/*----------------------------------------------*
 * module-wide global variables                 *
 *----------------------------------------------*/

//MMU memory ranges tables
MMU_Memory_Map_Range memory_ranges[]=
{
	{//MSMC RAM
    .uiVirtualAddress   = 0x0C000000,
    .ullPhysicalAddress = 0x0C000000,
    .uiByteCnt          = MSMC_RAM_SIZE_BYTES,
    .attribute          = MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA,
    .accessPermission   = MMU_MEM_ATTR_RW,
    .exectuePermission  = MMU_MEM_ATTR_X,
    .shareAttr          = MMU_MEM_ATTR_OUTER_SHARE,
    .isGlobal           = MMU_MEM_ATTR_GLOBAL,
    .isSecure           = MMU_MEM_ATTR_SECURE,
	},                     
#if 1
	{//DDR3A               
    .uiVirtualAddress   = 0x80000000,
    .ullPhysicalAddress = 0x800000000ULL, 	
    .uiByteCnt          = 0x20000000, 	
    .attribute          = MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA,
    .accessPermission   = MMU_MEM_ATTR_RW,
    .exectuePermission  = MMU_MEM_ATTR_XN,
    .shareAttr          = MMU_MEM_ATTR_OUTER_SHARE,
    .isGlobal           = MMU_MEM_ATTR_GLOBAL,
    .isSecure           = MMU_MEM_ATTR_SECURE,
	},
	{//DDR3A, non-cacheable               
    .uiVirtualAddress   = 0x80000000+0x20000000,
    .ullPhysicalAddress = 0x800000000ULL+0x20000000ULL, 	
#if (DDR3A_SIZE_BYTES>0x80000000ULL)
    .uiByteCnt          = 0x80000000-0x20000000, 	
#else
    .uiByteCnt          = DDR3A_SIZE_BYTES-0x20000000, 	
#endif
    .attribute          = MMU_MEM_ATTR_STRONG_ORDER,
    .accessPermission   = MMU_MEM_ATTR_RW,
    .exectuePermission  = MMU_MEM_ATTR_XN,
    .shareAttr          = MMU_MEM_ATTR_OUTER_SHARE,
    .isGlobal           = MMU_MEM_ATTR_GLOBAL,
    .isSecure           = MMU_MEM_ATTR_SECURE,
	}
#else
	{//DDR3A               
    .uiVirtualAddress   = 0x80000000,
    .ullPhysicalAddress = 0x800000000ULL, 	
#if (DDR3A_SIZE_BYTES>0x80000000ULL)
    .uiByteCnt          = 0x80000000, 	
#else
    .uiByteCnt          = DDR3A_SIZE_BYTES, 	
#endif
    .attribute          = MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA,
    .accessPermission   = MMU_MEM_ATTR_RW,
    .exectuePermission  = MMU_MEM_ATTR_XN,
    .shareAttr          = MMU_MEM_ATTR_OUTER_SHARE,
    .isGlobal           = MMU_MEM_ATTR_GLOBAL,
    .isSecure           = MMU_MEM_ATTR_SECURE,
	}
#endif
#if (2==CSL_DDR3_PER_CNT)
	,{//DDR3B
    .uiVirtualAddress   = 0x60000000,
    .ullPhysicalAddress = 0x60000000, 	
    .uiByteCnt          = 0x20000000,
    .attribute          = MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA,
    .accessPermission   = MMU_MEM_ATTR_RW,
    .exectuePermission  = MMU_MEM_ATTR_XN,
    .shareAttr          = MMU_MEM_ATTR_INNER_SHARE,
    .isGlobal           = MMU_MEM_ATTR_GLOBAL,
    .isSecure           = MMU_MEM_ATTR_SECURE,
	}
#endif
#ifdef CSL_OSR_DATA 	//for K2L only
	,{//OSR
    .uiVirtualAddress   = CSL_OSR_DATA,
    .ullPhysicalAddress = CSL_OSR_DATA,
    .uiByteCnt          = 0x00200000,
    .attribute          = MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA,
    .accessPermission   = MMU_MEM_ATTR_RW,
    .exectuePermission  = MMU_MEM_ATTR_XN,
    .shareAttr          = MMU_MEM_ATTR_INNER_SHARE,
    .isGlobal           = MMU_MEM_ATTR_GLOBAL,
    .isSecure           = MMU_MEM_ATTR_SECURE,
	}
#endif
};

MMU_Long_Format_Config mmu_cfg=
{
	.memory_map        = memory_ranges,
	.uiNumMemMapRanges = sizeof(memory_ranges)/sizeof(MMU_Memory_Map_Range),
	.ullpMMU3rdLevelTT = NULL, 	//No level 3 translation table
	.bAlignCheck       = TRUE,
	.tableCacheAttr    = MMU_TAB_ATTR_CACHE_WB_WA,
	.tableShareAttr	   = MMU_MEM_ATTR_INNER_SHARE,
};

/*----------------------------------------------*
 * routines' implementations                    *
 *----------------------------------------------*/
/*****************************************************************************
 Prototype    : main
 Description  : Robust system test main function
 Input        : void  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/5
    Author       : Zhan Xiang
    Modification : Created function
  2.Date        : 2014/10/30
    Author      : Brighton Feng
    Modification: updated for ARM

*****************************************************************************/
int main(void)
{
	DDR3_ECC_Config DDR_ECC_cfg;

	/*common initialization for internal modules in K2 device 
	enable GIC, memory protection interrupts, EDC for MSMC RAM */
	K2_common_device_init();
	/*initialize GIC interface for CPU, enable IRQ, FIQ, PMU*/
	K2_common_CPU_init();
    
	memset((void *)&DDR_ECC_cfg, 0, sizeof(DDR_ECC_cfg));
#if DDR_ECC_TEST
	DDR_ECC_cfg.addressRange[0].startAddr= 0x00000000ULL;
	DDR_ECC_cfg.addressRange[0].byteCnt=   0x01000000ULL;
	DDR_ECC_cfg.addressRange[1].startAddr= 0x20000000ULL;
	DDR_ECC_cfg.addressRange[1].byteCnt=   0x01000000ULL;
	DDR_ECC_cfg.rangeMode= EN_ECC_WITHIN_DEFINED_RANGES;
	DDR_ECC_cfg.one_bit_ECC_INT_threshold= 1;
	DDR_ECC_cfg.one_bit_ECC_INT_window= 0; 	//disable one-bit ECC interrupt window
#endif

	KeyStone_main_PLL_init(MAIN_PLL_REF_CLK_MHZ, MAIN_PLL_MULTIPLIER, MAIN_PLL_DIVISOR);

#ifndef DEVICE_K2E 	//K2E only has main PLL for both ARM and DSP cores
	//ARM core speed= ARM_PLL_REF_CLK_MHZ*ARM_PLL_MULTIPLIER/ARM_PLL_DIVISOR
	K2_ARM_PLL_init(ARM_PLL_REF_CLK_MHZ, ARM_PLL_MULTIPLIER, ARM_PLL_DIVISOR);
	//K2_ARM_PLL_init(125, 8, 1);
#endif

	//DDR configuration
	K2_DDR3A_config(NULL, &DDR_ECC_cfg);
#if (2==CSL_DDR3_PER_CNT)
	//K2_DDR3B_config(NULL, &DDR_ECC_cfg);
#endif

	//enable exception handling
	KeyStone_Exception_cfg(TRUE);

	/*MMU configure for ARM core*/
	MMU_long_format_init(&mmu_cfg);
	CP15_ICacheEnable();
	CP15_DCacheEnable();

    /* Initialize the QMSS to verify the peripheral MPU for QMSS */
   	QMSS_init();

   	EDMA_init(); //initialize the EDMA for test.
	K2_SMS_MPAX_init(PRIVID_ARM_COREPAC, MSMC_SHARE);
	K2_SES_MPAX_init(PRIVID_ARM_COREPAC, MSMC_SHARE);

	//setup timer and EDMA to scrub 8KB in read ONLY DDR ECC range every 1ms.
	DDR_EDC_scrubbing_setup(10, 8, &DDR_ECC_cfg);

#if SMS_MSMC_RAM_MP_TEST
	SMS_MSMC_RAM_MP_test();
#endif
#if SES_DDR_MP_TEST 
	SES_DDR_MP_test();
#endif
#if PERIPHERAL_MP_TEST
	peripheral_MP_test();
#endif
#if MSMC_RAM_EDC_TEST 
	MSMC_RAM_EDC_test();
#endif
#if DDR_ECC_TEST 
	DDR_ECC_test();
#endif
#if EDMA_ERROR_TEST 
	EDMA_ERROR_test();
#endif
#if WATCH_DOG_TEST 
	watch_dog_test();
#endif
#if RESERVED_SPACE_TEST
	Reserved_Space_Test();
#endif

	puts("test complete.");
   	//while(1);
	return 0;
}
