/****************************************************************************\
 *           Copyright (C) 2013 Texas Instruments Incorporated.             *
 *                           All Rights Reserved                            *
 *                                                                          *
 * GENERAL DISCLAIMER                                                       *
 * ------------------                                                       *
 * All software and related documentation is provided "AS IS" and without   *
 * warranty or support of any kind and Texas Instruments expressly disclaims*
 * all other warranties, express or implied, including, but not limited to, *
 * the implied warranties of merchantability and fitness for a particular   *
 * purpose.  Under no circumstances shall Texas Instruments be liable for   *
 * any incidental, special or consequential damages that result from the    *
 * use or inability to use the software or related documentation, even if   *
 * Texas Instruments has been advised of the liability.                     *
 ****************************************************************************
This example shows SPI master mode operations on KeyStone 2 device:
1. SPI loopback
2. read/write SPI NOR FLASH
3. SPI EDMA loopback
 ****************************************************************************
 * Created by :                                                             *
 *            Brighton Feng                                                *
 *            Texas Instruments                                             * 
 *            MAR 5, 2013                                                 *
***************************************************************************/

#include <stdio.h>
#include <string.h>
#include "K2_Board_Init.h"
#include "K2_Board_Init.h"
#include "SPI_loopback_TEST.h"
#include "SPI_NOR_FLASH_drv.h"
#include "SPI_NOR_FLASH_TEST.h"
#include "SPI_EDMA_TEST.h"
#include "SPI_Intc.h"

#define SPI_LOOPBACK_TEST 		1
#define SPI_NOR_FLASH_TEST 		1
#define SPI_EDMA_TEST           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,
	}
};

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,
};

SPI_Config spiCfg;
SPI_Interrupt_Config spiIntCfg;

void SPI_Init(Uint32 SPI_idx)
{
	/*data format for NOR FLASH test*/
	spiCfg.dataFormat[0]= &FlashDataFormat;

	/*data format for loopback test*/
	spiCfg.dataFormat[1]= &loopbackDataFormat;

	/*data format for EDMA loopback test*/	
	spiCfg.dataFormat[2]= &EdmaDataFormat;

	spiIntCfg.overrunInterruptEnable= TRUE;
	spiIntCfg.bitErrorInterruptEnable= TRUE;
	spiCfg.interruptCfg     = &spiIntCfg;
	spiCfg.number_SPI_pins  = 4;

	K2_SPI_init(SPI_idx, &spiCfg);
}
int main()
{
	int i;
	int iNOR_FLASH_size_KB;
	int iNOR_FLASH_addres_width;	

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

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

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

	/*clear configuration structure to default values*/
	memset(&spiCfg, 0, sizeof(spiCfg));
	memset(&spiIntCfg, 0, sizeof(spiIntCfg));
	
	SPI_Interrupts_Init();

#if SPI_LOOPBACK_TEST	
	spiCfg.loopBack = TRUE;	
    spiCfg.DMA_requestEnable= FALSE;
	for(i = 0; i < CSL_SPI_PER_CNT;i++)
	{
		SPI_Init(i);
		printf("\nSPI port %d internal loopback test at %dMHz...\n",
			i, loopbackDataFormat.clockSpeedKHz/1000);

		SPI_loopback_test(i);
	}
#endif
	
#if SPI_EDMA_TEST     
    SPI_EDMA_Init();   
    
    spiCfg.loopBack = TRUE;
    spiCfg.DMA_requestEnable= TRUE;
	for(i = 0; i < CSL_SPI_PER_CNT;i++)
	{
	    SPI_Init(i);

	    printf("\nSPI port %d EDMA test at %dMHz...\n", i, 
			EdmaDataFormat.clockSpeedKHz/1000);
	    
		SPI_EDMA_test(i);
	}
#endif
	
#if SPI_NOR_FLASH_TEST

	/*128Mb N25Q128 NOR FLASH  configuration */ 
	iNOR_FLASH_size_KB= SPI_FLASH_SIZE_BYTES/1024;
	if(SPI_FLASH_SIZE_BYTES>(16*1024*1024))
		iNOR_FLASH_addres_width = 32;
	else
		iNOR_FLASH_addres_width = 24;

	spiCfg.loopBack = FALSE;	
    spiCfg.DMA_requestEnable= FALSE;
	SPI_Init(CSL_SPI_0);

	printf("\nSPI port 0 NOR_FLASH test at %dMHz...\n",
		FlashDataFormat.clockSpeedKHz/1000);

	if(iNOR_FLASH_addres_width>24) 	//enabele 4 bytes address
	{
		SPI_NOR_FLASH_command(CSL_SPI_0, SPI_NOR_FLASH_RESET_ENABLE);
		delay_us(1);
		SPI_NOR_FLASH_command(CSL_SPI_0, SPI_NOR_FLASH_RESET_MEMORY);
		delay_us(1);

		/*write enable insturction*/
		SPI_NOR_FLASH_command(CSL_SPI_0, SPI_NOR_FLASH_WREN);
		/*enable 4-byte mode*/
		SPI_NOR_FLASH_command(CSL_SPI_0, SPI_NOR_FLASH_EN4B);
	}
	
	Uint8 ID[4];
	SPI_NOR_FLASH_ID_read(CSL_SPI_0, ID);
	printf("Read SPI NOR FLASH ID = 0x%x 0x%x 0x%x\n", ID[0], ID[1], ID[2]);
	
	if(iNOR_FLASH_size_KB<=256*4)
		SPI_NOR_FLASH_Test(CSL_SPI_0, 0, iNOR_FLASH_size_KB*1024, iNOR_FLASH_addres_width);
	else
	{
		/*spilt large space into small sections to show the progress,
		reserved the first half, only test the second half to save time*/
		for(i=iNOR_FLASH_size_KB-256*2; i<iNOR_FLASH_size_KB; i+= 256)
			SPI_NOR_FLASH_Test(CSL_SPI_0, i*1024, (i+256)*1024, iNOR_FLASH_addres_width);
	}	
#endif

	printf("SPI test complete at %lld cycle.\n", get_64_bit_cycle_count());
	return 0;
}

