//***** author Xue Chenguang****************/
#include <stdio.h>
#include <csl_bootcfgaux.h>
#include <cslr_emif4f.h>
#include <cslr_cgem.h>
#include <csl_bootrom.h>
#include "KeyStone_DDR_Init.h"
#include "KeyStone_common.h"
unsigned int DSP_Core_Clock_KHz= 1000000;
//void TCI6614_EVM_DDR_Init(float clock_MHz);
void main(void) {
	
//	TCI6614_EVM_DDR_Init(500);
	while(1)
	{
    unsigned int * p = (unsigned int *)0x80001000;
      *p= 0x12345678;
	}
}

/*
Keystone DDR configuration
Author: Brighton
Created on 2010-12-6
Updated on 2011-4-17 for TCI6608/C6678 EVM
Updated on 2011-7-12 for dual TCI6618 EVM
Updated on 2012-5-8  for C6670/TCI6618 EVM and TCI6614 EVM
*/
#if 0
CSL_BootcfgRegs * boot_cfg_regs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS;
//	CSL_RomcfgRegs   * boot_rom_ddr3_regs = (CSL_RomcfgRegs *) CSL_BOOT_ROM_DDR3_REGS;
CSL_Emif4fRegs * DDR_Regs= (CSL_Emif4fRegs *)CSL_DDR3_EMIF_CONFIG_REGS;

void KeyStone_DDR_PLL_init (unsigned int DDR_PLLM, unsigned int DDR_PLLD)
{
	int i;

	if(0<DDR_PLLM&&DDR_PLLM<=8192&&0<DDR_PLLD&&DDR_PLLD<=64)
	{
		CSL_BootCfgUnlockKicker();

		boot_cfg_regs->DDR3_PLL_CTL1 = 0x00000040      /*Set ENSAT bit = 1*/
			|((DDR_PLLM-1)/2)>>8;	/*BWADJ[11:8]*/

		/*Set Bypass = 1*/
		boot_cfg_regs->DDR3_PLL_CTL0 |= (1<<23) ;

		boot_cfg_regs->DDR3_PLL_CTL1 |= 0x00002000;      //Set RESET bit = 1

		boot_cfg_regs->DDR3_PLL_CTL0 = (boot_cfg_regs->DDR3_PLL_CTL0&0x00780000)|
			(((DDR_PLLM-1)/2)<<24)|((DDR_PLLM-1)<<6)|(DDR_PLLD-1);
		for(i=0;i<1000;i++)
			asm(" nop");            //Wait >1000ns for reset to complete

		boot_cfg_regs->DDR3_PLL_CTL1 &= ~(0x00002000);   //Clear RESET bit
		for(i=0;i<10000;i++)
			asm(" nop");          //Wait >2000 clocks (>30us) for PLL lock

		/*Set Bypass = 0 (PLL Mode)*/
		boot_cfg_regs->DDR3_PLL_CTL0 &= ~(1<<23) ;
	}
}


/*setup DDR incremental leveling, can only be executed after full leveling*/
void Keystone_DDR_incremental_leveling(Uint32 incremental_interval_ms)
{
	Uint32 uiIncemental_inteval;

	uiIncemental_inteval= incremental_interval_ms;
	if(0xFF<uiIncemental_inteval)
		uiIncemental_inteval= 0xFF;

	/*set normal incremental leveling inteval*/
	DDR_Regs->RDWR_LVL_CTRL =
		(0x7F<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDWRLVLINC_PRE_SHIFT)|
		(uiIncemental_inteval<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDLVLINC_INT_SHIFT)|
		(uiIncemental_inteval<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDLVLGATEINC_INT_SHIFT)|
		(uiIncemental_inteval<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_WRLVLINC_INT_SHIFT);
}

/*execute DDR full leveling*/
int Keystone_DDR_full_leveling()
{
	Uint32 i;

	/*enable full leveling*/
	DDR_Regs->RDWR_LVL_RMP_CTRL =
		(1<<CSL_EMIF4F_RDWR_LVL_RMP_CTRL_REG_RDWRLVL_EN_SHIFT);

	/*start full leveling*/
	DDR_Regs->RDWR_LVL_CTRL =
		(1<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDWRLVLFULL_START_SHIFT);

	/*Read back any of the DDR3 controller registers.
	This ensures full leveling is complete because this step is executed
	only after full	leveling completes.*/
	i= DDR_Regs->RDWR_LVL_RMP_CTRL; 	//dummy read

	//Wait 3ms for leveling to complete
	TSC_delay_ms(3);

	if(DDR_Regs->STATUS&(CSL_EMIF4F_STATUS_REG_RDLVLGATETO_MASK
		|CSL_EMIF4F_STATUS_REG_RDLVLTO_MASK
		|CSL_EMIF4F_STATUS_REG_WRLVLTO_MASK))
	{
		printf("DDR3 leveling has failed, STATUS = 0x%x\n", DDR_Regs->STATUS);
		return 1;
	}
	return 0;
}



/*configure DDR according to the clock speed
please note, clock_MHz is the clock speed in MHz, not data rate.
For example, clock speed for 1333.333M data rate is 666.667MHz*/
void TCI6614_EVM_DDR_Init(float clock_MHz)
{
	int i;

	CSL_BootCfgUnlockKicker();

	//initial vale for leveling
	/*WRLVL_INIT_RATIO*/
	boot_cfg_regs->DDR3_CONFIG_REG[2] = 0x20;
	boot_cfg_regs->DDR3_CONFIG_REG[3] = 0x24;
	boot_cfg_regs->DDR3_CONFIG_REG[4] = 0x3A;
	boot_cfg_regs->DDR3_CONFIG_REG[5] = 0x38;
	boot_cfg_regs->DDR3_CONFIG_REG[6] = 0x51;
	boot_cfg_regs->DDR3_CONFIG_REG[7] = 0x5E;
	boot_cfg_regs->DDR3_CONFIG_REG[8] = 0x5E;
	boot_cfg_regs->DDR3_CONFIG_REG[9] = 0x5E;
	boot_cfg_regs->DDR3_CONFIG_REG[10]= 0x44;

	/*GTLVL_INIT_RATIO*/
	boot_cfg_regs->DDR3_CONFIG_REG[14] = 0xA1;
	boot_cfg_regs->DDR3_CONFIG_REG[15] = 0xA0;
	boot_cfg_regs->DDR3_CONFIG_REG[16] = 0xA7;
	boot_cfg_regs->DDR3_CONFIG_REG[17] = 0xA9;
	boot_cfg_regs->DDR3_CONFIG_REG[18] = 0xCA;
	boot_cfg_regs->DDR3_CONFIG_REG[19] = 0xBE;
	boot_cfg_regs->DDR3_CONFIG_REG[20] = 0xDD;
	boot_cfg_regs->DDR3_CONFIG_REG[21] = 0xDD;
	boot_cfg_regs->DDR3_CONFIG_REG[22] = 0xBA;

	boot_cfg_regs->DDR3_CONFIG_REG[0] |= 0xF; 	// set dll_lock_diff to 15

	/*Invert Clock Out*/
	boot_cfg_regs->DDR3_CONFIG_REG[0] &= ~(0x007FE000);  // clear ctrl_slave_ratio field
	boot_cfg_regs->DDR3_CONFIG_REG[0] |= 0x00200000;     // set ctrl_slave_ratio to 0x100
	boot_cfg_regs->DDR3_CONFIG_REG[12] |= 0x08000000;    // Set invert_clkout = 1

	boot_cfg_regs->DDR3_CONFIG_REG[23] |= 0x00000200; //Set bit 9 = 1 to use forced ratio leveling for read DQS

	/*the PHY_RESET is pulsed (0 -> 1 -> 0) to latch these
	leveling configuration values into the PHY logic.*/
	DDR_Regs->DDR_PHY_CTRL_1 &= ~(0x00008000);
	DDR_Regs->DDR_PHY_CTRL_1 |= (0x00008000);
	DDR_Regs->DDR_PHY_CTRL_1 &= ~(0x00008000);


	/*Drives CKE low.
	This is a JEDEC requirement that we have 500us delay between reset de-assert
	and cke assert and then program the correct refresh rate
	The DDR internal clock is divide by 16 before SDCFG write*/
	DDR_Regs->SDRAM_REF_CTRL = 0x80000000|(unsigned int)(500.f*clock_MHz/16.f);

	DDR_Regs->SDRAM_TIM_1 =
		((unsigned int)(13.75*clock_MHz/1000.f-0.0001f)<<CSL_EMIF4F_SDRAM_TIM_1_REG_T_RP_SHIFT)|
		((unsigned int)(13.75*clock_MHz/1000.f-0.0001f)<<CSL_EMIF4F_SDRAM_TIM_1_REG_T_RCD_SHIFT)|
		((unsigned int)(15*clock_MHz/1000.f-0.0001f)<<CSL_EMIF4F_SDRAM_TIM_1_REG_T_WR_SHIFT)|
		((unsigned int)(36*clock_MHz/1000.f-0.0001f)<<CSL_EMIF4F_SDRAM_TIM_1_REG_T_RAS_SHIFT)|
		((unsigned int)(49.5*clock_MHz/1000.f-0.0001f)<<CSL_EMIF4F_SDRAM_TIM_1_REG_T_RC_SHIFT)|
		((unsigned int)(45*clock_MHz/4000.f-0.0001f)<<CSL_EMIF4F_SDRAM_TIM_1_REG_T_RRD_SHIFT)| 	/*T_RRD = (tFAW/(4*tCK)) C 1*/
		(_max2(4-1, (unsigned int)(7.5*clock_MHz/1000.f-0.0001f))<<CSL_EMIF4F_SDRAM_TIM_1_REG_T_WTR_SHIFT);
	DDR_Regs->SDRAM_TIM_2   =
		(_max2(3-1, (unsigned int)(6*clock_MHz/1000.f-0.0001f))<<CSL_EMIF4F_SDRAM_TIM_2_REG_T_XP_SHIFT)|
		(_max2(5-1, (unsigned int)((128+10)*clock_MHz/1000.f-0.0001f))<<CSL_EMIF4F_SDRAM_TIM_2_REG_T_XSNR_SHIFT)| 	/*T_XSNR = (tXS /tCK)C 1*/
		((512-1)<<CSL_EMIF4F_SDRAM_TIM_2_REG_T_XSRD_SHIFT)| 	/*T_XSRD =tXSDLLC 1*/
		(_max2(4-1, (unsigned int)(7.5*clock_MHz/1000.f-0.0001f))<<CSL_EMIF4F_SDRAM_TIM_2_REG_T_RTP_SHIFT)|
		(_max2(3-1, (unsigned int)(5.625*clock_MHz/1000.f-0.0001f))<<CSL_EMIF4F_SDRAM_TIM_2_REG_T_CKE_SHIFT);
	DDR_Regs->SDRAM_TIM_3   =
		(5<<CSL_EMIF4F_SDRAM_TIM_3_REG_T_PDLL_UL_SHIFT)| 	/*This field must always be programmed to 0x5.*/
		((5)<<CSL_EMIF4F_SDRAM_TIM_3_REG_T_CSTA_SHIFT)| 	/*This field should be set according to PHY requirements as 0x5.*/
		((unsigned int)(5.625*clock_MHz/1000.f+0.9999f)<<CSL_EMIF4F_SDRAM_TIM_3_REG_T_CKESR_SHIFT)|
		((64-1)<<CSL_EMIF4F_SDRAM_TIM_3_REG_ZQ_ZQCS_SHIFT)|
		((unsigned int)(128*clock_MHz/1000.f-0.0001f)<<CSL_EMIF4F_SDRAM_TIM_3_REG_T_RFC_SHIFT)|
		(15<<CSL_EMIF4F_SDRAM_TIM_3_REG_T_RAS_MAX_SHIFT); 	/*This field must always be programmed to 0xF.*/

	DDR_Regs->DDR_PHY_CTRL_1  = 0x00100100|
		(15<<CSL_EMIF4F_DDR_PHY_CTRL_1_REG_READ_LATENCY_SHIFT); 	/*between CAS Latency + 1 and CAS Latency + 7*/

	DDR_Regs->ZQ_CONFIG =
		((0)<<CSL_EMIF4F_ZQ_CONFIG_REG_ZQ_CS1EN_SHIFT)|
		((1)<<CSL_EMIF4F_ZQ_CONFIG_REG_ZQ_CS0EN_SHIFT)|
		((1)<<CSL_EMIF4F_ZQ_CONFIG_REG_ZQ_DUALCALEN_SHIFT)| 	/*This bit should always be set to 1.*/
		((1)<<CSL_EMIF4F_ZQ_CONFIG_REG_ZQ_SFEXITEN_SHIFT)|
		((512/256-1)<<CSL_EMIF4F_ZQ_CONFIG_REG_ZQ_ZQINIT_MULT_SHIFT)| 	/*T_ZQ_ZQINIT_MULT = (tZQinit/tZQoper C 1)*/
		((256/64-1)<<CSL_EMIF4F_ZQ_CONFIG_REG_ZQ_ZQCL_MULT_SHIFT)| 	/*T_ZQ_ZQCL_MULT = (tZQoper/tZQCS C 1)*/
		/*interval between ZQCS commands = 0.5%/((TSens x Tdriftrate) + (VSens x Vdriftrate))
		=0.5%/((max (dRTTdT, dRONdTM) x Tdriftrate in C/second) + (max(dRTTdV, dRONdVM) x Vdriftrate in mV/second))
		this time need be converted to refresh period number*/
		(((unsigned int)(1000000000*0.5/(1.5*1.2+0.15*15))/(64000000/8192))<<CSL_EMIF4F_ZQ_CONFIG_REG_ZQ_REFINTERVAL_SHIFT);

	/*map priority 0,1,2,3 to COS0,
	map priority 3,5,6,7 to COS1*/
	DDR_Regs->PRI_COS_MAP =
		((1)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_COS_MAP_EN_SHIFT)|
		((1)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_7_COS_SHIFT)|
		((1)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_6_COS_SHIFT)|
		((1)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_5_COS_SHIFT)|
		((1)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_4_COS_SHIFT)|
		((0)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_3_COS_SHIFT)|
		((0)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_2_COS_SHIFT)|
		((0)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_1_COS_SHIFT)|
		((0)<<CSL_EMIF4F_PRI_COS_MAP_REG_PRI_0_COS_SHIFT);

	/*master based COS map is disabled*/
	DDR_Regs->MSTID_COS_1_MAP= 0;
	DDR_Regs->MSTID_COS_2_MAP= 0;

	/*LAT_CONFIG*/
	DDR_Regs->VBUSM_CONFIG=
		(8<<CSL_EMIF4F_VBUSM_CONFIG_REG_COS_COUNT_1_SHIFT)|
		(16<<CSL_EMIF4F_VBUSM_CONFIG_REG_COS_COUNT_2_SHIFT)|
		(32<<CSL_EMIF4F_VBUSM_CONFIG_REG_PR_OLD_COUNT_SHIFT);

	DDR_Regs->ECC_CTRL =
		((0)<<CSL_EMIF4F_ECC_CTRL_REG_ECC_EN_SHIFT)|
		((0)<<CSL_EMIF4F_ECC_CTRL_REG_ECC_ADDR_RNG_PROT_SHIFT)|
		((0)<<CSL_EMIF4F_ECC_CTRL_REG_ECC_ADDR_RNG_2_EN_SHIFT)|
		((0)<<CSL_EMIF4F_ECC_CTRL_REG_ECC_ADDR_RNG_1_EN_SHIFT);

	DDR_Regs->ECC_ADDR_RNG_1=
		((0)<<CSL_EMIF4F_ECC_ADDR_RNG_1_REG_ECC_STRT_ADDR_1_SHIFT)|
		((0)<<CSL_EMIF4F_ECC_ADDR_RNG_1_REG_ECC_END_ADDR_1_SHIFT);

	DDR_Regs->ECC_ADDR_RNG_2=
		((0)<<CSL_EMIF4F_ECC_ADDR_RNG_2_REG_ECC_STRT_ADDR_2_SHIFT)|
		((0)<<CSL_EMIF4F_ECC_ADDR_RNG_2_REG_ECC_END_ADDR_2_SHIFT);

	/* enables DRAM configuration.  It still has the refresh interval
	programmed to the longer number needed during DRAM initialization.*/
	DDR_Regs->SDRAM_REF_CTRL = (unsigned int)(500.f*clock_MHz/16.f);

	DDR_Regs->SDRAM_CONFIG =
		(3<<CSL_EMIF4F_SDRAM_CONFIG_REG_SDRAM_TYPE_SHIFT)| 	/*Set to 3 for DDR3. All other values reserved.*/
		(0<<CSL_EMIF4F_SDRAM_CONFIG_REG_IBANK_POS_SHIFT)|
		(DDR_TERM_RZQ_OVER_6<<CSL_EMIF4F_SDRAM_CONFIG_REG_DDR_TERM_SHIFT)|
		(DDR_DYN_ODT_DISABLED<<CSL_EMIF4F_SDRAM_CONFIG_REG_DYN_ODT_SHIFT)|
		(0<<CSL_EMIF4F_SDRAM_CONFIG_REG_DDR_DISABLE_DLL_SHIFT)|
		(SDRAM_DRIVE_RZQ_OVER_7<<CSL_EMIF4F_SDRAM_CONFIG_REG_SDRAM_DRIVE_SHIFT)|
		(DDR_CWL_8<<CSL_EMIF4F_SDRAM_CONFIG_REG_CWL_SHIFT)|
		(DDR_BUS_WIDTH_64<<CSL_EMIF4F_SDRAM_CONFIG_REG_NARROW_MODE_SHIFT)|
		(DDR_CL_11<<CSL_EMIF4F_SDRAM_CONFIG_REG_CL_SHIFT)|
		(DDR_ROW_SIZE_14_BIT<<CSL_EMIF4F_SDRAM_CONFIG_REG_ROWSIZE_SHIFT)|
		(DDR_BANK_NUM_8<<CSL_EMIF4F_SDRAM_CONFIG_REG_IBANK_SHIFT)|
		(0<<CSL_EMIF4F_SDRAM_CONFIG_REG_EBANK_SHIFT)|
		(DDR_PAGE_SIZE_10_BIT_1024_WORD<<CSL_EMIF4F_SDRAM_CONFIG_REG_PAGESIZE_SHIFT);

	for(i=0;i<100000;i++)
		asm(" nop"); 	//Wait 600us for HW init to complete

//	DDR_Regs->SDRAM_REF_CTRL    = 64000000/8192/(1000/clock_MHz);
	DDR_Regs->SDRAM_REF_CTRL    = (unsigned int)64000.f*clock_MHz/8192.f;

#if 0
	//enable full leveling, no incremental leveling
	/*Typically program a higher rate of incremental leveling in the ramp window*/
	DDR_Regs->RDWR_LVL_RMP_WIN = 10000/7.8; 	/*10000us*/
	DDR_Regs->RDWR_LVL_RMP_CTRL =
		(1<<CSL_EMIF4F_RDWR_LVL_RMP_CTRL_REG_RDWRLVL_EN_SHIFT)|
		(0<<CSL_EMIF4F_RDWR_LVL_RMP_CTRL_REG_RDWRLVLINC_RMP_PRE_SHIFT)|
		(0<<CSL_EMIF4F_RDWR_LVL_RMP_CTRL_REG_RDLVLINC_RMP_INT_SHIFT)|
		(0<<CSL_EMIF4F_RDWR_LVL_RMP_CTRL_REG_RDLVLGATEINC_RMP_INT_SHIFT)|
		(0<<CSL_EMIF4F_RDWR_LVL_RMP_CTRL_REG_WRLVLINC_RMP_INT_SHIFT);
	DDR_Regs->RDWR_LVL_CTRL =
		(1<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDWRLVLFULL_START_SHIFT)|
		(0x7F<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDWRLVLINC_PRE_SHIFT)|
		(0<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDLVLINC_INT_SHIFT)|
		(0<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_RDLVLGATEINC_INT_SHIFT)|
		(0<<CSL_EMIF4F_RDWR_LVL_CTRL_REG_WRLVLINC_INT_SHIFT);

	TSC_delay_ms(3); 	//Wait 3ms for leveling to complete

	//Read MMR to ensure full leveling is complete
	i= DDR_Regs->RDWR_LVL_RMP_CTRL;

	if(DDR_Regs->STATUS&(CSL_EMIF4F_STATUS_REG_RDLVLGATETO_MASK
		|CSL_EMIF4F_STATUS_REG_RDLVLTO_MASK
		|CSL_EMIF4F_STATUS_REG_WRLVLTO_MASK))
	{
		printf("DDR3 leveling has failed, STATUS = 0x%x\n", DDR_Regs->STATUS);
		return;
	}

	/*simple test*/
	*((Uint32 *)0x80000000)= 0xaaaaaaaa;
	if(0xaaaaaaaa!=(*((Uint32 *)0x80000000)))
		puts("DDR3 access test failed.");
#else
	Keystone_DDR_full_leveling();
#endif
}


/*
this function write the address to corresponding memory unit and readback for verification
*/
unsigned int DDR_Address_Test(unsigned int uiStartAddress,
	unsigned int uiByteCount)
{
    unsigned int i;
    volatile unsigned long long *ulpAddressPointer;
    volatile unsigned long long ulReadBack;

	ulpAddressPointer = (unsigned long long *)uiStartAddress;
	for(i=0; i<uiByteCount/8; i++)
	{
		/* fill with address value */
        *ulpAddressPointer = _itoll(((unsigned int)ulpAddressPointer)+4,
        	(unsigned int)ulpAddressPointer);
        ulpAddressPointer++;
    }

	WritebackInvalidCache((void *)uiStartAddress, uiByteCount);

	ulpAddressPointer = (unsigned long long *)uiStartAddress;
	for(i=0; i<uiByteCount/8; i++)
	{
        ulReadBack = *ulpAddressPointer;
        if ( ulReadBack != _itoll(((unsigned int)ulpAddressPointer)+4,
        	(unsigned int)ulpAddressPointer)) /* verify data */
        {
			printf("Memory Test fails at 0x%8x, Write 0x%16llx, Readback 0x%16llx\n",
				ulpAddressPointer, _itoll(((unsigned int)ulpAddressPointer)+4, (unsigned int)ulpAddressPointer), ulReadBack);
			return 1;
        }
        ulpAddressPointer++;
    }

    return 0;              /* show no error */
}

/*
this function write the address to corresponding memory unit and readback for verification
*/
unsigned int DDR_Fill_Test(unsigned int uiStartAddress,
	unsigned int uiByteCount, unsigned int uiPattern)
{
    unsigned int i;
    volatile unsigned long long *ulpAddressPointer;
    volatile unsigned long long ulReadBack;

	ulpAddressPointer = (unsigned long long *)uiStartAddress;
	for(i=0; i<uiByteCount/8; i++)
	{
		/* fill with address value */
        *ulpAddressPointer = _itoll(uiPattern, uiPattern);
        ulpAddressPointer++;
    }

	WritebackInvalidCache((void *)uiStartAddress, uiByteCount);

	ulpAddressPointer = (unsigned long long *)uiStartAddress;
	for(i=0; i<uiByteCount/8; i++)
	{
        ulReadBack = *ulpAddressPointer;
        if ( ulReadBack != _itoll(uiPattern, uiPattern)) /* verify data */
        {
			printf("Memory Test fails at 0x%8x, Write 0x%16llx, Readback 0x%16llx\n",
				ulpAddressPointer, _itoll(uiPattern, uiPattern), ulReadBack);
			return 1;
        }
        ulpAddressPointer++;
    }

    return 0;              /* show no error */
}


void TSC_delay_ms(Uint32 ms)
{
	volatile unsigned long long preTSC, currentTSC;
	unsigned long long delay_cycles;
	Uint32 tscl, tsch;

	tscl= TSCL;
	tsch= TSCH;
	preTSC= _itoll(tsch,tscl);

	delay_cycles= ((unsigned long long)ms*1000000000000l/DSP_Core_Clock_KHz);

	do
	{
		tscl= TSCL;
		tsch= TSCH;
		currentTSC= _itoll(tsch,tscl);
	}
	while((currentTSC-preTSC)<delay_cycles);
}
#endif
