/*  ============================================================================
 *   Copyright (c) Texas Instruments Inc 2010-2013
 *
 *   Use of this software is controlled by the terms and conditions found in the
 *   license agreement under which this software has been supplied.
* ============================================================================
Example to show the performance of CPU and DMA access memory on KeyStone device
* =============================================================================
 *  Revision History
 *  ===============
 *  7-Dec-2010 Brighton Feng   File Created
 *  20-Feb-2013 Brighton Feng   Updated for K2
 * ============================================================================
 */

#include <stdio.h>
#include <string.h>
#include "K2_common.h"
#include "K2_Board_Init.h"
#include "Mem_Access_performance.h"

//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,
	},
	/*split part of MSMC RAM into small blocks for test, assign different 
	propoties to each block for test purpose.
	Please note, the newly defined small block may overlap with previous defintion 
	of the big memory range, the overlap part will use new propoties*/
	{MSMC_RAM_TEST_BASE_ADDR+0*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BASE_ADDR+0*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, MMU_MEM_ATTR_STRONG_ORDER          , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	//{MSMC_RAM_TEST_BASE_ADDR+0*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BASE_ADDR+0*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, MMU_MEM_ATTR_DEVICE                , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{MSMC_RAM_TEST_BASE_ADDR+1*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BASE_ADDR+1*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_NON_CACHE      , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{MSMC_RAM_TEST_BASE_ADDR+2*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BASE_ADDR+2*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{MSMC_RAM_TEST_BASE_ADDR+3*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BASE_ADDR+3*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_OUTER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{//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,
	},
	/*split part of DDR3A into small blocks for test, assign different 
	propoties to each block for test purpose.
	Please note, the newly defined small block may overlap with previous defintion 
	of the big memory range, the overlap part will use new propoties*/
	{DDR3A_TEST_BASE_ADDR+0*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_PHYSICAL_BASE_ADDR+0*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, MMU_MEM_ATTR_STRONG_ORDER          , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	//{DDR3A_TEST_BASE_ADDR+0*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_PHYSICAL_BASE_ADDR+0*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, MMU_MEM_ATTR_DEVICE                , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{DDR3A_TEST_BASE_ADDR+1*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_PHYSICAL_BASE_ADDR+1*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_NON_CACHE      , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{DDR3A_TEST_BASE_ADDR+2*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_PHYSICAL_BASE_ADDR+2*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{DDR3A_TEST_BASE_ADDR+3*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_PHYSICAL_BASE_ADDR+3*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_OUTER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE}
#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,
	},
	/*split part of DDR3B into small blocks for test, assign different 
	propoties to each block for test purpose.
	Please note, the newly defined small block may overlap with previous defintion 
	of the big memory range, the overlap part will use new propoties*/
	{DDR3B_TEST_BASE_ADDR+0*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BASE_ADDR+0*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, MMU_MEM_ATTR_STRONG_ORDER          , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	//{DDR3B_TEST_BASE_ADDR+0*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BASE_ADDR+0*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, MMU_MEM_ATTR_DEVICE                , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{DDR3B_TEST_BASE_ADDR+1*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BASE_ADDR+1*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_NON_CACHE      , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{DDR3B_TEST_BASE_ADDR+2*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BASE_ADDR+2*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{DDR3B_TEST_BASE_ADDR+3*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BASE_ADDR+3*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_OUTER_SHARE, MMU_MEM_ATTR_GLOBAL,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,
	},
	/*split part of OSR into small blocks for test, assign different 
	propoties to each block for test purpose.
	Please note, the newly defined small block may overlap with previous defintion 
	of the big memory range, the overlap part will use new propoties*/
	{OSR_TEST_BASE_ADDR+0*OSR_TEST_BLOCK_SIZE, OSR_TEST_BASE_ADDR+0*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, MMU_MEM_ATTR_STRONG_ORDER          , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	//{OSR_TEST_BASE_ADDR+0*OSR_TEST_BLOCK_SIZE, OSR_TEST_BASE_ADDR+0*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, MMU_MEM_ATTR_DEVICE                , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{OSR_TEST_BASE_ADDR+1*OSR_TEST_BLOCK_SIZE, OSR_TEST_BASE_ADDR+1*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_NON_CACHE      , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{OSR_TEST_BASE_ADDR+2*OSR_TEST_BLOCK_SIZE, OSR_TEST_BASE_ADDR+2*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_INNER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE},
	{OSR_TEST_BASE_ADDR+3*OSR_TEST_BLOCK_SIZE, OSR_TEST_BASE_ADDR+3*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, MMU_MEM_ATTR_NORMAL_CACHE_RA_WB_WA , MMU_MEM_ATTR_RW, MMU_MEM_ATTR_XN, MMU_MEM_ATTR_OUTER_SHARE, MMU_MEM_ATTR_GLOBAL,MMU_MEM_ATTR_SECURE}
#endif
};

/*array to save the third level MMU translation table.
First and second level MMU translation tables are allocated statically in driver.
For this test, the "memory_map[]" includes two ranges (MSMC and OSR test blocks)
less than 2MB, which requires third level table*/
unsigned long long ullMMU3rdLevelTT[NUM_MSMC_RAM_3RD_LEVEL_TABLES+NUM_OSR_3RD_LEVEL_TABLES][512] __attribute__ ((aligned (4096)));

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

/*list of all memory blocks for test.
load store latency test will be done on each blocks.
memory copy test will be done inside each block and between all blocks.*/
Memory_Test_Block mem_test_blocks[]=
{
	/*MSMC RAM blocks for test*/
	{MSMC_RAM_TEST_BASE_ADDR+0*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, "MSRAM(strongly ordered)"}
	//,{MSMC_RAM_TEST_BASE_ADDR+0*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, "MSRAM(device type)     "}
	,{MSMC_RAM_TEST_BASE_ADDR+1*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, "MSRAM(normal non-cache)"}
	,{MSMC_RAM_TEST_BASE_ADDR+2*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, "MSRAM(RA_WB_WA,  in sh)"}
	//,{MSMC_RAM_TEST_BASE_ADDR+3*MSMC_RAM_TEST_BLOCK_SIZE, MSMC_RAM_TEST_BLOCK_SIZE, "MSRAM(RA_WB_WA, out sh)"}
	/*DDR3A blocks for test*/                                                    
	,{DDR3A_TEST_BASE_ADDR+0*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, "DDR3A(strongly ordered)"}
	//,{DDR3A_TEST_BASE_ADDR+0*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, "DDR3A(device type)     "}
	,{DDR3A_TEST_BASE_ADDR+1*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, "DDR3A(normal non-cache)"}
	,{DDR3A_TEST_BASE_ADDR+2*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, "DDR3A(RA_WB_WA,  in sh)"}
	//,{DDR3A_TEST_BASE_ADDR+3*DDR3A_TEST_BLOCK_SIZE, DDR3A_TEST_BLOCK_SIZE, "DDR3A(RA_WB_WA, out sh)"}
#if (2==CSL_DDR3_PER_CNT)                                                          
	/*DDR3B blocks for test*/                                                        
	,{DDR3B_TEST_BASE_ADDR+0*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, "DDR3B(strongly ordered)"}
	//,{DDR3B_TEST_BASE_ADDR+0*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, "DDR3B(device type)     "}
	,{DDR3B_TEST_BASE_ADDR+1*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, "DDR3B(normal non-cache)"}
	,{DDR3B_TEST_BASE_ADDR+2*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, "DDR3B(RA_WB_WA,  in sh)"}
	//,{DDR3B_TEST_BASE_ADDR+3*DDR3B_TEST_BLOCK_SIZE, DDR3B_TEST_BLOCK_SIZE, "DDR3B(RA_WB_WA, out sh)"}
#endif                                                                             
#ifdef CSL_OSR_DATA 	/*for K2L only*/
	/*OSR blocks for test*/                                                          
	,{OSR_TEST_BASE_ADDR+0*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, "OSR (strongly ordered) "}
	//,{OSR_TEST_BASE_ADDR+0*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, "OSR (device type)      "}
	,{OSR_TEST_BASE_ADDR+1*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, "OSR (normal non-cache) "}
	,{OSR_TEST_BASE_ADDR+2*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, "OSR (RA_WB_WA,  in sh) "}
	//,{OSR_TEST_BASE_ADDR+3*OSR_TEST_BLOCK_SIZE, OSR_TEST_BLOCK_SIZE, "OSR (RA_WB_WA, out sh) "}
#endif                                                                                                     
};
unsigned int num_mem_test_blocks= sizeof(mem_test_blocks)/sizeof(Memory_Test_Block); 

int main()
{   
	/*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();
	KeyStone_Exception_cfg(TRUE);

	EDMA_init();
	K2_SMS_MPAX_init(PRIVID_ARM_COREPAC, MSMC_SHARE);
	K2_SES_MPAX_init(PRIVID_ARM_COREPAC, MSMC_SHARE);

#ifdef CSL_OSR_DATA 	//for K2L
	//enable OSR for test
	KeyStone_enable_PSC_module(CSL_PSC_PD_OSR, CSL_PSC_LPSC_OSR);
#endif

	//Main core speed= MAIN_PLL_REF_CLK_MHZ*MAIN_PLL_MULTIPLIER/MAIN_PLL_DIVISOR
	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, NULL);
#if (2==CSL_DDR3_PER_CNT)
	K2_DDR3B_config(NULL, NULL);
#endif

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

	MemoryCopyTest();

	LoadStoreCycleTest();

	edma_test();


	puts("Test complete");
    
    return 0;
}
