/*
Keystone common miscellaneous functions and definitions
Author: Brighton
Created on 2010-12-12
*/
#ifndef _KEYSTONE_COMMON_H_
#define _KEYSTONE_COMMON_H_

#include <c6x.h>
#include <tistdtypes.h>
#include <cslr_xmc.h>
#include <cslr_cgem.h>
#include <cslr_bootcfg.h>
#include <cslr_tpcc.h>
#include <cslr_device.h>
#include <cslr_cpintc.h>
#include <cslr_tmr.h>
#include <cslr_srio.h>
#include <cslr_vusr.h>
#include <csl_psc.h>
#include <csl_tmr.h>
#include <csl_cache.h>
#include <csl_cacheAux.h>

#if 0
#include <cslr_pllc.h>
#else
/**************************************************************************\
* Register Overlay Structure
\**************************************************************************/
typedef struct  {
    volatile Uint8 RSVD0[228];
    volatile Uint32 RSTYPE;
    volatile Uint32 RSTCTRL;
    volatile Uint32 RSTCFG;
    volatile Uint32 RSISO;
    volatile Uint8 RSVD1[12];
    volatile Uint32 PLLCTL;
    volatile Uint8 RSVD2[4];
    volatile Uint32 SECCTL;
    volatile Uint8 RSVD3[4];
    volatile Uint32 PLLM;
    volatile Uint32 PREDIV;
    volatile Uint32 PLLDIV1;
    volatile Uint32 PLLDIV2;
    volatile Uint32 PLLDIV3;
    volatile Uint8 RSVD4[4];
    volatile Uint32 POSTDIV;
    volatile Uint8 RSVD5[12];
    volatile Uint32 PLLCMD;
    volatile Uint32 PLLSTAT;
    volatile Uint32 ALNCTL;
    volatile Uint32 DCHANGE;
    volatile Uint32 CKEN;
    volatile Uint32 CKSTAT;
    volatile Uint32 SYSTAT;
    volatile Uint8 RSVD6[12];
    volatile Uint32 PLLDIV4;
    volatile Uint32 PLLDIV5;
    volatile Uint32 PLLDIV6;
    volatile Uint32 PLLDIV7;
    volatile Uint32 PLLDIV8;
    volatile Uint32 PLLDIV9;
    volatile Uint32 PLLDIV10;
} CSL_PllcRegs;
#endif

#define 	CPU_CLK_KHZ 		(1000000)

/*convert local address to global address for EDMA on multi-core DSP*/
#define GLOBAL_ADDR(addr) ((Uint32)addr<0x1000000?\
						(Uint32)addr+(0x10000000+DNUM*0x1000000):\
						(Uint32)addr)

extern CSL_XmcRegs * XMC_regs;
extern CSL_CgemRegs * CGEM_regs;
extern CSL_BootcfgRegs * boot_cfg_regs;
extern CSL_PllcRegs * pllc_regs;
extern CSL_PscRegs *  pscRegs;

extern CSL_TpccRegs*  gEDMACC0Regs;
extern CSL_TpccRegs*  gEDMACC1Regs;
extern CSL_TpccRegs*  gEDMACC2Regs;
extern CSL_TpccRegs*  gEDMACCRegs[3];
extern CSL_CPINTCRegs* cpIntc0Regs;
extern CSL_CPINTCRegs* cpIntc1Regs;
extern CSL_TmrRegs * timer0Regs;
extern CSL_TmrRegs * timer1Regs;
extern CSL_TmrRegs * timer2Regs;
extern CSL_TmrRegs * timer3Regs;
extern CSL_TmrRegs * timer4Regs;
extern CSL_TmrRegs * timer5Regs;
extern CSL_TmrRegs * timer6Regs;
extern CSL_TmrRegs * timer7Regs;
extern CSL_TmrRegs * timer8Regs;
extern CSL_TmrRegs * timerRegs[9];

extern unsigned int cycle_measure_overhead;
/*get the delay between current and prvious TSC
The delay must be less than 32 bit
enable the TSC with "TSCL= 0;" before use this macro*/
#define TSC_getDelay(preTSC) 	((unsigned int)((0xFFFFFFFFl+TSCL)- (unsigned long long)preTSC)+ 1)
#define TSC_count_cycle_from(preTSC) 	(TSC_getDelay(preTSC)- cycle_measure_overhead)

/* Initialize Time stame counter to measure cycles*/
extern void TSC_init();

/*delay in millisecond*/
extern void TSC_delay_ms(Uint32 ms);

/*delay in microsecond*/
extern void TSC_delay_us(Uint32 us);

/*DSP core PLL configuration*/
extern void KeyStone_main_PLL_init ( unsigned int main_PLLM, unsigned int main_PLLD);
extern void KeyStone_DDR_PLL_init (unsigned int DDR_PLLM, unsigned int DDR_PLLD);
extern void KeyStone_PA_PLL_init (unsigned int PA_PLLM,	unsigned int PA_PLLD);

extern void lock_mem_prot_regs();
extern void unlock_mem_prot_regs();
extern void KeyStone_XM_cfg();
extern void KeyStone_L1_cfg();
extern void KeyStone_L2_cfg();

extern void edma_Init ();

extern Int32 Keystone_enable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum);
extern Int32 Keystone_disable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum);
extern Int32 Keystone_disable_PSC_Power_Domain (Uint32 pwrDmnNum);

/*configure timer to generate continual clock or interrupts,
period is in DSP core clock/6*/
extern void Timer_Init(int timer_num, unsigned long long period);

extern void	Reset_Timer(int timer_num);

/*configure timer to generate one-shot pulse or interrupt,
delay is in DSP core clock/6*/
extern void Timer_One_Shot_Init(int timer_num, Uint32 delay);

/*configure timer as watch-dog,
period is in DSP core clock/6*/
extern void Watchdog_Timer_Init(int timer_num, unsigned long long period);

typedef enum
{
	WD_OUT_NONE = 0,
	WD_RESET_LOCAL = 2,
	WD_TRIGGER_NMI = 3,
	WD_TRIGGER_NMI_RESET_LOCAL = 4,
	WD_RESET_DEVICE = 5
}TWatchdogOutputMode;

/*write sequence of a A5C6h followed by a DA7Eh 
to services the watchdog timer.*/
extern void Service_Watchdog(int timer_num);

extern void Exception_cfg();

static inline unsigned int SWAP_ENDIAN(unsigned int byte_index)
{
#ifdef _BIG_ENDIAN
	return ((byte_index&0xFFFFFFFC)+(3-byte_index&3));
#else
	return byte_index;
#endif
}

static inline void InvalidPrefetchBuffer()
{
	//invalid prefetch buffer
	XMC_regs->XPFCMD = 1<<CSL_XMC_XPFCMD_INV_SHIFT;
}
 
static inline void Invalid(void * blockPtr, Uint32 byteCnt)
{
	if(byteCnt>0xFFFF*4)
		byteCnt= 0xFFFF*4;
	if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0C400000)	//SL2
	{
		CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT);
		InvalidPrefetchBuffer();
	}
	else if((Uint32)blockPtr>=0x10000000) 	//DDR or other cores
	{
		CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT);
		InvalidPrefetchBuffer();
	}
}

static inline void WritebackInvalidAll(void * blockPtr)
{
	if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0C400000)	//SL2
	{
		CACHE_wbInvAllL1d(CACHE_WAIT);//CACHE_invL1d((void *)blockPtr, byteCnt, CACHE_WAIT);
		InvalidPrefetchBuffer();
	}
	else if((Uint32)blockPtr>=0x10000000) 	//DDR or other cores
	{
		//CACHE_invL2((void *)blockPtr, byteCnt, CACHE_WAIT);
		CACHE_wbInvAllL2(CACHE_WAIT);
		InvalidPrefetchBuffer();
	}
}


static inline void Writeback(void * blockPtr, Uint32 byteCnt)
{
	if(byteCnt>0xFFFF*4)
		byteCnt= 0xFFFF*4;
	if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0C400000)	//SL2
	{
		CACHE_wbL1d((void *)blockPtr, byteCnt, CACHE_WAIT);
	}
	else if((Uint32)blockPtr>=0x10000000) 	//DDR or other cores
	{
		CACHE_wbL2((void *)blockPtr, byteCnt, CACHE_WAIT);
	}
}
 
static inline void WritebackAll(void * blockPtr)
{
	if((Uint32)blockPtr>=0x0C000000&&(Uint32)blockPtr<0x0C400000)	//SL2
	{
		CACHE_wbAllL1d(CACHE_WAIT);;
	}
	else if((Uint32)blockPtr>=0x10000000) 	//DDR or other cores
	{
		CACHE_wbAllL2(CACHE_WAIT);
	}
}

typedef enum
{
	TCI6616 = 0, 						
	TCI6618, 						
	TCI6608,
	TCI6614,
	UNKNOWN
}TDSP_Type;

static inline TDSP_Type Get_dsp_type()
{
	if(0x0009D02F == (boot_cfg_regs->DEVICE_ID_REG0&0xFFFFFFF))
		return TCI6616;
	if(0x0B94102F == (boot_cfg_regs->DEVICE_ID_REG0&0xFFFFFFF))
		return TCI6618;
	if(0x0009E02F == (boot_cfg_regs->DEVICE_ID_REG0&0xFFFFFFF))
		return TCI6608;
	if(0x0B96202F == (boot_cfg_regs->DEVICE_ID_REG0&0xFFFFFFF))
		return TCI6614;
	return UNKNOWN;
}

static inline Uint32 Get_DSP_Number()
{
	TDSP_Type dspType= Get_dsp_type();

	if(TCI6616==dspType||TCI6618==dspType)
	{
		/*Nyquist EVM use boot configure pin 4 and 5 to identify DSPs*/
		return (( boot_cfg_regs->BOOT_REG0 >> (3+1) ) & 0x03);
	}

	/*if use DNUM to differentiate DSPs for two DSPs test,
	the program must be run on core 0 of DSP 0 and core 1 of DSP1*/
	return DNUM;
}


#endif

