/******************************************************************************
 *  ============================================================================
 *  @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         : 2012/10/30
    Author       : Zhan
    Modification : Add comments to the whole projects
******************************************************************************/
#include <stdio.h>
#include <string.h>

#include "KeyStone_common.h"
#include "KeyStone_DDR_init.h"
#include "Robust_MNav_Init.h"
#include "Robust_SRIO_Init.h"
#include "Robust_INTC.h"
#include "Robust_L1_MP.h"
#include "Robust_LL2_MP.h"
#include "Robust_L1P_ED.h"
#include "Robust_LL2_EDC.h"
#include "Robust_SL2_EDC.h"
#include "Robust_DDR_ECC.h"
#include "Robust_SL2_XMC_MP.h"
#include "Robust_DDR_XMC_MP.h"
#include "Robust_SL2_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"
//#include "Hook.h"

#define L1D_MP_TEST 		1
#define L1P_MP_TEST 		1
#define LL2_MP_TEST 		1
#define XMC_SL2_MP_TEST 	1
#define XMC_DDR_MP_TEST 	1
#define SMS_SL2_MP_TEST 	1
#define SES_DDR_MP_TEST 	1
#define PERIPHERAL_MP_TEST 	1
#define L1P_ED_TEST 		1
#define LL2_EDC_TEST 		1
#define SL2_EDC_TEST 		1
#define DDR_ECC_TEST 		0 	/*only for EVM with ECC memory*/
#define EDMA_ERROR_TEST 	1
#define WATCH_DOG_TEST 		1
/*reserved space test can not safely return, thus other tests after this will not run,
to run following tests, this test must be disabled.*/
#define RESERVED_SPACE_TEST 1
/*interrup drop test can not safely return, thus other tests after this will not run,
to run following tests, this test must be disabled.*/
#define INT_DROP_TEST 		1


/*----------------------------------------------*
 * external variables                           *
 *----------------------------------------------*/

/*----------------------------------------------*
 * external routine prototypes                  *
 *----------------------------------------------*/

/*----------------------------------------------*
 * internal routine prototypes                  *
 *----------------------------------------------*/

/*----------------------------------------------*
 * project-wide global variables                *
 *----------------------------------------------*/

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

/*memory protection and address extension configuration table 
for TCI6616, C6670 EVM
Please note, this configuration table can not be put in the memory segment 
that will be modified based on this table. Normally, to put this table 
in LL2 is a good idea.
*/
#pragma DATA_SECTION(XMC_MPAX_cfg_table,".far:Core_MPAX")
MPAX_Config XMC_MPAX_cfg_table[]=
{
    /*BADDR         RADDR           SegementSize      AccessPermisionMask
    32-bit virtual  36-bit physical in byte, must     Access types allowed
    base address    address right   be power of 2     in this address range
                    shift by 4                                            */
    {0x0C000000,    0x00C000000>>4,  2*1024*1024,    MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*SL2, RWX*/
    {0x10000000,    0x010000000>>4,  0x04000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*LL2 global address space, RW*/
    {0x18000000,    0x00C100000>>4,  1*1024*1024,    MP_SR|MP_SW|MP_UR|MP_UW},/*remap Shared L2 to 0x18000000 for read/write*/
    {0x20000000,    0x020000000>>4,  0x04000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*peripherals configuraion, RW*/
    {0x30000000,    0x030000000>>4,  0x08000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*RAC/QM/TAC/BCP/FFTC/TCP3D, RW*/
    {0x40000000,    0x040000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*HyperLink mapped memory windows, RW*/
    {0x60000000,    0x060000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*PCIE mapped memory windows, RW*/
    {0x21000000,    0x100000000>>4,  4*1024,         MP_SR|MP_SW|MP_UR|MP_UW},/*map DDR3 configuration registers at physical address 0x1:00000000 to logical address 0x21000000*/
    {0x80000000,    0x800000000>>4,  0x10000000,     MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*DDR, RWX*/
    {0x90000000,    0x810000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW}/*DDR, RW*/
};
/*memory protection and address extension configuration table 
for TCI6614 EVM
Please note, this configuration table can not be put in the memory segment 
that will be modified based on this table. Normally, to put this table 
in LL2 is a good idea.
*/
#pragma DATA_SECTION(XMC_MPAX_cfg_table_TCI6614,".far:Core_MPAX")
MPAX_Config XMC_MPAX_cfg_table_TCI6614[]=
{
    /*BADDR         RADDR           SegementSize      AccessPermisionMask
    32-bit virtual  36-bit physical in byte, must     Access types allowed
    base address    address right   be power of 2     in this address range
                    shift by 4                                            */
    {0x0C000000,    0x00C000000>>4,  2*1024*1024,    MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*SL2, RWX*/
    {0x10000000,    0x010000000>>4,  0x04000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*LL2 global address space, RW*/
    {0x18000000,    0x00C100000>>4,  1*1024*1024,    MP_SR|MP_SW|MP_UR|MP_UW},/*remap Shared L2 to 0x18000000 for read/write*/
    {0x20000000,    0x020000000>>4,  0x04000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*peripherals configuraion, RW*/
    {0x30000000,    0x030000000>>4,  0x08000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*RAC/QM/TAC/BCP, RW*/
    {0x40000000,    0x040000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*HyperLink mapped memory windows, RW*/
    {0x60000000,    0x060000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*PCIE mapped memory windows, RW*/
    {0x70000000,    0x070000000>>4,  0x10000000,     MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*EMIF, RWX*/
    {0x21000000,    0x100000000>>4,  4*1024,         MP_SR|MP_SW|MP_UR|MP_UW},/*map DDR3 configuration registers at physical address 0x1:00000000 to logical address 0x21000000*/
    {0x80000000,    0x800000000>>4,  0x10000000,     MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*DDR, RWX*/
    {0x90000000,    0x810000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*DDR, RW*/
    {0xa0000000,    0x820000000>>4,  0x20000000,     MP_SR|MP_SW|MP_UR|MP_UW}/*DDR, RW*/
};
/*memory protection and address extension configuration table,
for C6678 EVM
Please note, this configuration table can not be put in the memory segment 
that will be modified based on this table. Normally, to put this table 
in LL2 is a good idea.
*/
#pragma DATA_SECTION(XMC_MPAX_cfg_table_C6678,".far:Core_MPAX")
MPAX_Config XMC_MPAX_cfg_table_C6678[]=
{
    /*BADDR         RADDR           SegementSize      AccessPermisionMask
    32-bit virtual  36-bit physical in byte, must     Access types allowed
    base address    address right   be power of 2     in this address range
                    shift by 4                                            */
    {0x0C000000,    0x00C000000>>4,  4*1024*1024,    MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*SL2, RWX*/
    {0x10000000,    0x010000000>>4,  0x08000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*LL2 global address space, RW*/
    {0x18000000,    0x00C100000>>4,  1*1024*1024,    MP_SR|MP_SW|MP_UR|MP_UW},/*remap Shared L2 to 0x18000000 for read/write*/
    {0x20000000,    0x020000000>>4,  0x02000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*peripherals configuraion, RW*/
    {0x34000000,    0x034000000>>4,  0x00200000,     MP_SR|MP_SW|MP_UR|MP_UW},/*QM, RW*/
    {0x40000000,    0x040000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*HyperLink mapped memory windows, RW*/
    {0x60000000,    0x060000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*PCIE mapped memory windows, RW*/
    {0x70000000,    0x070000000>>4,  0x10000000,     MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*EMIF, RWX*/
    {0x21000000,    0x100000000>>4,  4*1024,         MP_SR|MP_SW|MP_UR|MP_UW},/*map DDR3 configuration registers at physical address 0x1:00000000 to logical address 0x21000000*/
    {0x80000000,    0x800000000>>4,  0x10000000,     MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*DDR, RWX*/
    {0x90000000,    0x810000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW}/*DDR, RW*/
};

#pragma DATA_SECTION(XMC_MPAX_cfg_table_C6657,".far:Core_MPAX")
MPAX_Config XMC_MPAX_cfg_table_C6657[]=
{
    /*BADDR         RADDR           SegementSize      AccessPermisionMask
    32-bit virtual  36-bit physical in byte, must     Access types allowed
    base address    address right   be power of 2     in this address range
                    shift by 4                                            */
    {0x0C000000,    0x00C000000>>4,  1*1024*1024,    MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*SL2, RWX*/
    {0x10000000,    0x010000000>>4,  0x02000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*LL2 global address space, RW*/
    {0x18000000,    0x00C0C0000>>4,  256*1024,       MP_SR|MP_SW|MP_UR|MP_UW},/*remap Shared L2 to 0x18000000 for read/write*/
    {0x20000000,    0x020000000>>4,  0x02000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*peripherals configuraion, RW*/
    {0x34000000,    0x034000000>>4,  0x00200000,     MP_SR|MP_SW|MP_UR|MP_UW},/*QM, RW*/
    {0x40000000,    0x040000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*HyperLink mapped memory windows, RW*/
    {0x60000000,    0x060000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW},/*PCIE mapped memory windows, RW*/
    {0x70000000,    0x070000000>>4,  0x10000000,     MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*EMIF, RWX*/
    {0x21000000,    0x100000000>>4,  4*1024,         MP_SR|MP_SW|MP_UR|MP_UW},/*map DDR3 configuration registers at physical address 0x1:00000000 to logical address 0x21000000*/
    {0x80000000,    0x800000000>>4,  0x10000000,     MP_SR|MP_SW|MP_SX|MP_UR|MP_UW|MP_UX},/*DDR, RWX*/
    {0x90000000,    0x810000000>>4,  0x10000000,     MP_SR|MP_SW|MP_UR|MP_UW}/*DDR, RW*/
};
/*----------------------------------------------*
 * constants                                    *
 *----------------------------------------------*/

/*----------------------------------------------*
 * macros                                       *
 *----------------------------------------------*/

/*----------------------------------------------*
 * routines' implementations                    *
 *----------------------------------------------*/
/*****************************************************************************
 Prototype    : main
 Description  : Robust system test main function
 Input        : void  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/5
    Author       : Zhan
    Modification : Created function

*****************************************************************************/
void main(void)
{
	int i;
	TDSP_Board_Type DSP_Board_Type;
	DDR_ECC_Config DDR_ECC_cfg;

    TSC_init();	//initialize TSC to measure cycle

    IER= 0; 	//disable all interrupts
    
    CACHE_setL1PSize(CACHE_L1_32KCACHE);
    CACHE_setL1DSize(CACHE_L1_32KCACHE);
    CACHE_setL2Size(CACHE_0KCACHE);
	CACHE_invAllL1p(CACHE_WAIT);
	CACHE_wbInvAllL1d(CACHE_WAIT);
	CACHE_wbInvAllL2(CACHE_WAIT);
	CSL_XMC_invalidatePrefetchBuffer();
	_mfence();
	_mfence();

	/* protect L1 as cache */
   	L1_cache_protection();

	/*make other cores local memory cacheable*/
	for(i=16; i<24; i++)
		gpCGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT);

	/*make other space non-cacheable and non-prefetchable*/
	for(i=24; i<128; i++)
		gpCGEM_regs->MAR[i]=0;

	/*make DDR cacheable*/
	for(i=128; i<256; i++)
		gpCGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT);

	memset((void *)&DDR_ECC_cfg, 0, sizeof(DDR_ECC_cfg));

	DSP_Board_Type= KeyStone_Get_dsp_board_type();
	if((C6670_EVM == DSP_Board_Type)
		||(DUAL_NYQUIST_EVM == DSP_Board_Type)
		||(TCI6614_EVM == DSP_Board_Type))
	{
		/*DDR ECC is supported on TCI6614 EVM*/
		if(TCI6614_EVM == DSP_Board_Type)
		{
			/*XMC memory address extension/mapping and memory protection*/
			KeyStone_XMC_MPAX_setup(XMC_MPAX_cfg_table_TCI6614, 0,
				sizeof(XMC_MPAX_cfg_table_TCI6614)/sizeof(MPAX_Config));

			DDR_ECC_cfg.addressRange[0].startAddr= 0x00000000;
			DDR_ECC_cfg.addressRange[0].byteCnt=   0x01000000;
			DDR_ECC_cfg.addressRange[1].startAddr= 0x08000000;
			DDR_ECC_cfg.addressRange[1].byteCnt=   0x01000000;
			DDR_ECC_cfg.rangeMode= EN_ECC_WITHIN_DEFINED_RANGES;
		}
		else
		{
			/*XMC memory address extension/mapping and memory protection*/
			KeyStone_XMC_MPAX_setup(XMC_MPAX_cfg_table, 0,
				sizeof(XMC_MPAX_cfg_table)/sizeof(MPAX_Config));
		}
		//DSP core speed
		KeyStone_main_PLL_init (122.88, 236, 29); 	//for 122.88MHz input clock

	}
	else if(C6678_EVM==DSP_Board_Type || C6657_EVM==DSP_Board_Type)
	{
		if(C6678_EVM==DSP_Board_Type)
		{
		    /*XMC memory address extension/mapping and memory protection*/
		    KeyStone_XMC_MPAX_setup(XMC_MPAX_cfg_table_C6678, 0,
			    sizeof(XMC_MPAX_cfg_table_C6678)/sizeof(MPAX_Config));
		}
		else
		{
		    KeyStone_XMC_MPAX_setup(XMC_MPAX_cfg_table_C6657, 0,
			    sizeof(XMC_MPAX_cfg_table_C6657)/sizeof(MPAX_Config));
		}
#if 0
		DDR_ECC_cfg.addressRange[0].startAddr= 0x00000000;
		DDR_ECC_cfg.addressRange[0].byteCnt=   0x01000000;
		DDR_ECC_cfg.addressRange[1].startAddr= 0x08000000;
		DDR_ECC_cfg.addressRange[1].byteCnt=   0x01000000;
		DDR_ECC_cfg.rangeMode= EN_ECC_WITHIN_DEFINED_RANGES;
#endif
		//DSP core speed
		KeyStone_main_PLL_init (100, 10, 1); 	//for 100MHz input clock
	}
	else
	{
		puts("Unknown DSP type!");
		return;
	}
#ifdef STM_DEBUG
    ETB_init();
    STM_init();
#endif    
	if((C6670_EVM == DSP_Board_Type)
		||(DUAL_NYQUIST_EVM == DSP_Board_Type)
		||(TCI6614_EVM == DSP_Board_Type)
		||(C6678_EVM == DSP_Board_Type))
	{
	    //DDR init 66.66667*20/1= 1333
	    KeyStone_DDR_init (66.66667, 20, 1, &DDR_ECC_cfg);
	}
	else
	{
		//EVM6657 with 50MHz input for DDR
		KeyStone_DDR_init (50, 26, 1, NULL);
	}
#if 0
	/*make function profile record buffer non-cacheable*/
	for(i=((Uint32)ProfileData)/(16*1024*1024);
		i<= (((Uint32)ProfileData)+sizeof(ProfileData))/(16*1024*1024); i++)
		gpCGEM_regs->MAR[i]= 0;
	hook_init();
#endif
    /* Initialize the QMSS to verify the peripheral MPU for QMSS */
    QMSS_init();

    /* Initialize the SRIO to verify the SMS and SES memory protection */
    SRIO_Init();

    EDMA_init(); //initialize the EDMA for test.

	/*INTC/CIC initialization*/
   	Robust_Interrupts_Init();

	//Enable MSMC Memory protection error interrupt for local core
    KeyStone_MSMC_MP_interrupt_en(1<<DNUM);
    
	/* enable the all MPU interrupts */
	KeyStone_MPU_interrupts_enable();

	/*enable L1P ED and scrub whole L1P*/
	L1P_EDC_setup();

   	/*enable LL2 EDC and scrub whole LL2*/
	LL2_EDC_setup();

	/*setup timer with period in second for LL2 EDC scrubbing*/
   	LL2_EDC_scrubbing_timer_setup(600); //LL2 EDC scrubbing period is 600 seconds

	/*Enable MSMC EDC and setup scrubbing cycle counter= 255*1024*/
	KeyStone_SL2_EDC_enable(255);

   	/*exception configuration, also configure event 23 as the CIC exception input*/
   	KeyStone_Exception_cfg();

#if L1D_MP_TEST 
	L1D_MP_test();
#endif
#if L1P_MP_TEST 	
	L1P_MP_test();
#endif
#if LL2_MP_TEST 	
	LL2_MP_test();
#endif
#if XMC_SL2_MP_TEST
	XMC_SL2_MP_test();
#endif
#if XMC_DDR_MP_TEST 
	XMC_DDR_MP_test();
#endif
#if SMS_SL2_MP_TEST
	SMS_SL2_MP_test();
#endif
#if SES_DDR_MP_TEST 
	SES_DDR_MP_test();
#endif
#if PERIPHERAL_MP_TEST
	peripheral_MP_test();
#endif
#if L1P_ED_TEST 	
	L1P_ED_test();
#endif
#if LL2_EDC_TEST 
	LL2_EDC_test();
#endif
#if SL2_EDC_TEST 
	SL2_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 can not safely return, thus other tests after this will not be done*/
	Reserved_Space_Test();
#endif
#if INT_DROP_TEST 	
/*interrup drop test can not safely return, thus other tests after this will not run*/
	INT_drop_test();
#endif

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