/*  ============================================================================
 *   Copyright (c) Texas Instruments Inc 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 Multicore Navigator on KeyStone device
* =============================================================================
 *  Revision History
 *  ===============
 *  Feb 5, 2013 Brighton Feng   File Created
 * ============================================================================
 */

#include <stdio.h>
#include <string.h>
#include <csl_qm_queue.h>
#include "K2_common.h"
#include "K2_Board_Init.h"
#include "MNav_QM_Intc_setup.h"
#include "MNav_Test.h"

#define TEST_QUEUE_MANAGER		1
#define TEST_QM_PACKET_DMA 		1
#define TEST_PA_PACKET_DMA 		1

//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,
	},                     
	{//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,
	}
#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,
};

void QueuePushPopTest(Uint32 uiQueueNumber)
{
	Uint32 uiDescriptorNumber;

	uiDescriptorNumber= gpQueueStatusConfigRegs[uiQueueNumber].REG_A_EntryCount;
	if(uiDescriptorNumber>TEST_DESC_BUF_SIZE)
		uiDescriptorNumber=TEST_DESC_BUF_SIZE;

	printf("Queue %d push test through Queue Manage Registers\n", uiQueueNumber);
	QueuePushCycleTest(&gpQueueManageRegs[uiQueueNumber], uiDescriptorNumber, &gpQueueManageRegs[uiQueueNumber]);
	checkQueues(); 	//for debug

#if 0
	printf("Queue %d push test through Queue Manage Proxy Registers\n", uiQueueNumber);
	QueuePushCycleTest(&gpQueueManageProxyRegs[uiQueueNumber], uiDescriptorNumber, &gpQueueManageRegs[uiQueueNumber]);
	checkQueues(); 	//for debug
#endif

	printf("Queue %d push test through Queue Manage VBUSM Data Space\n", uiQueueNumber);
	QueuePushCycleTest(&gpQueueManageVBUSM[uiQueueNumber], uiDescriptorNumber, &gpQueueManageRegs[uiQueueNumber]);
	checkQueues(); 	//for debug

	printf("Queue %d pop test through Queue Manage Registers\n", uiQueueNumber);
	QueuePopCycleTest(&gpQueueManageRegs[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

	printf("Queue %d pop test through Queue Manage VBUSM Data Space\n", uiQueueNumber);
	QueuePopCycleTest(&gpQueueManageVBUSM[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

	printf("Empty Queue %d pop test through Queue Manage Registers\n", EMPTY_FDQ);
	QueuePopCycleTest(&gpQueueManageRegs[EMPTY_FDQ], uiDescriptorNumber);
	checkQueues(); 	//for debug


	printf("Queue %d push to pop delay test through Queue Manage Registers\n", uiQueueNumber);
	QueuePushToPopDelayTest(&gpQueueManageRegs[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

	printf("Queue %d push to pop delay test through Queue Manage VBUSM Data Space\n", uiQueueNumber);
	QueuePushToPopDelayTest(&gpQueueManageVBUSM[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

}

void CpuAccessQueueTest()
{
	puts("Queue Push/Pop test on descriptors with internal linking RAM");
	QueuePushPopTest(DDR_MONO_LINK_RAM0_FDQ);

	puts("Queue Push/Pop test on descriptors with external linking RAM");
	QueuePushPopTest(DDR_MONO_LINK_RAM1_FDQ);

}

void QueuePendInterruptTest()
{
	puts("\nQueue pend interrupt test on descriptors with internal linking RAM");
	QueuePushToPendInterruptDelayTest(&gpQueueManageVBUSM[DDR_MONO_LINK_RAM0_FDQ]);

	puts("Queue pend interrupt test on descriptors with external linking RAM");
	QueuePushToPendInterruptDelayTest(&gpQueueManageVBUSM[DDR_MONO_LINK_RAM1_FDQ]);
}

void PktDmaThroughputTest(Uint32 uiSrcQuNum, Uint32 uiTxQuNum, 
	Uint32 uiFlowID, Uint32 uiMaxBytes, Uint32 uiNumCh)
{
	int i;

	for(i=8; i<=uiMaxBytes; i*=2)
		PktDmaThroughput(uiSrcQuNum, uiTxQuNum, uiFlowID, i, uiNumCh);
}

void PktDmaTest(Uint32 uiTxQuNum, Uint32 uiNumCh)
{
	printf("host Packet DMA test with %d channels\n", uiNumCh);

	/*Packet DMA transfer from MSMC RAM to MSMC RAM*/
	//PktDmaThroughputTest(MSMC_RAM_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_MSMC_RAM_HOST, MSMC_RAM_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from MSMC RAM to DDR*/
	PktDmaThroughputTest(MSMC_RAM_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_DDR_HOST, MSMC_RAM_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from DDR to MSMC RAM*/
	PktDmaThroughputTest(DDR_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_MSMC_RAM_HOST, MSMC_RAM_PACKET_BUFFER_SIZE3, uiNumCh);

	printf("monolithic Packet DMA test with %d channels\n", uiNumCh);

	/*Packet DMA transfer from MSMC RAM to DDR*/
	PktDmaThroughputTest(MSMC_RAM_MONOLITHIC_FDQ, uiTxQuNum, RX_FLOW_DDR_MONO, MSMC_RAM_MONO_DESCRIPTOR_SIZE, uiNumCh);
	/*Packet DMA transfer from DDR to MSMC RAM*/
	PktDmaThroughputTest(DDR_MONO_LINK_RAM0_FDQ, uiTxQuNum, RX_FLOW_MSMC_RAM_MONO, MSMC_RAM_MONO_DESCRIPTOR_SIZE, uiNumCh);
}

int main()
{   
	int i;

	/*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);

	//make QMSS access to MSMC RAM sharable with ARM core
	K2_SMS_MPAX_init(PRIVID_QM_SECOND, MSMC_SHARE);

	//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();

	QMSS_init();
	QMSS_PktDMA_init();
	checkQueues(); 	//for debug
	
	QM_Interrupts_Init();

#if TEST_QUEUE_MANAGER
	CpuAccessQueueTest();
	checkQueues(); 	//for debug

	QueuePendInterruptTest();
	checkQueues(); 	//for debug

	QueueReclamationDelayTest(DDR_HOST_SIZE3_FDQ);
	checkQueues(); 	//for debug

	QueuePushToAccumulationDelayTest(QMSS_INTD1, DDR_MONO_LINK_RAM0_FDQ);
	checkQueues(); 	//for debug
#if defined(DEVICE_K2H) || defined(DEVICE_K2K)
	QueuePushToAccumulationDelayTest(QMSS_INTD2, DDR_MONO_LINK_RAM0_FDQ);
	checkQueues(); 	//for debug
#endif
#endif
#if TEST_QM_PACKET_DMA
	puts("test Packet DMA1 in QMSS");
	for(i= 1; i<=4; i*=2)
#ifdef QMSS_QM1_INFRASTRUCTURE_DMA_QUEUE_BASE
		PktDmaTest(QMSS_QM1_INFRASTRUCTURE_DMA_QUEUE_BASE, i);
#else
		PktDmaTest(QMSS_QMSS_PKTDMA_QUEUE_BASE, i);
#endif

#ifdef QMSS_QM2_INFRASTRUCTURE_DMA_QUEUE_BASE
	puts("test Packet DMA2 in QMSS");
	PktDmaTest(QMSS_QM2_INFRASTRUCTURE_DMA_QUEUE_BASE, 1);
	checkQueues(); 	//for debug
#endif
#endif

#if TEST_PA_PACKET_DMA
	//enable PA for test
	KeyStone_enable_PSC_module(CSL_PSC_PD_NETCP, CSL_PSC_LPSC_PA);

	PA_PktDMA_init();

	puts("test Packet DMA in PA");
	PktDmaTest(QMSS_PASS_QUEUE_BASE, 1);
	checkQueues(); 	//for debug
#endif

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

