/*
Keystone common miscellaneous functions and definitions
Author: Brighton
Created on 2010-12-12
*/
#include <stdio.h>
#include <tistdtypes.h>
#include <csl_bootcfgAux.h>
#include <csl_pscAux.h>
#include <cslr_chip.h>
#include "KeyStone_common.h"

CSL_XmcRegs * XMC_regs = (CSL_XmcRegs *) CSL_XMC_CONFIG_REGS;
CSL_CgemRegs * CGEM_regs = (CSL_CgemRegs *)CSL_CGEM0_5_REG_BASE_ADDRESS_REGS;
CSL_BootcfgRegs * boot_cfg_regs = (CSL_BootcfgRegs *)CSL_BOOT_CFG_REGS;
CSL_CPINTCRegs* cpIntc0Regs = (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS;
CSL_CPINTCRegs* cpIntc1Regs = (CSL_CPINTCRegs*)CSL_CP_INTC_0_REGS;
CSL_PllcRegs * pllc_regs = (CSL_PllcRegs * )0x02310000;
CSL_PscRegs *  pscRegs =   (CSL_PscRegs *)CSL_PSC_REGS;

CSL_TpccRegs*  gEDMACC0Regs  = (CSL_TpccRegs*)CSL_EDMA0CC_REGS;
CSL_TpccRegs*  gEDMACC1Regs  = (CSL_TpccRegs*)CSL_EDMA1CC_REGS;
CSL_TpccRegs*  gEDMACC2Regs  = (CSL_TpccRegs*)CSL_EDMA2CC_REGS;
CSL_TpccRegs*  gEDMACCRegs[3]  = {
	(CSL_TpccRegs*)CSL_EDMA0CC_REGS,
	(CSL_TpccRegs*)CSL_EDMA1CC_REGS,
	(CSL_TpccRegs*)CSL_EDMA2CC_REGS
};

CSL_TmrRegs * timer0Regs = (CSL_TmrRegs *)CSL_TIMER_0_REGS;
CSL_TmrRegs * timer1Regs = (CSL_TmrRegs *)CSL_TIMER_1_REGS;
CSL_TmrRegs * timer2Regs = (CSL_TmrRegs *)CSL_TIMER_2_REGS;
CSL_TmrRegs * timer3Regs = (CSL_TmrRegs *)CSL_TIMER_3_REGS;
CSL_TmrRegs * timer4Regs = (CSL_TmrRegs *)CSL_TIMER_4_REGS;
CSL_TmrRegs * timer5Regs = (CSL_TmrRegs *)CSL_TIMER_5_REGS;
CSL_TmrRegs * timer6Regs = (CSL_TmrRegs *)CSL_TIMER_6_REGS;
CSL_TmrRegs * timer7Regs = (CSL_TmrRegs *)CSL_TIMER_7_REGS;
CSL_TmrRegs * timer8Regs = (CSL_TmrRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS));
CSL_TmrRegs * timerRegs[9] = {
	(CSL_TmrRegs *)CSL_TIMER_0_REGS,
	(CSL_TmrRegs *)CSL_TIMER_1_REGS,
	(CSL_TmrRegs *)CSL_TIMER_2_REGS,
	(CSL_TmrRegs *)CSL_TIMER_3_REGS,
	(CSL_TmrRegs *)CSL_TIMER_4_REGS,
	(CSL_TmrRegs *)CSL_TIMER_5_REGS,
	(CSL_TmrRegs *)CSL_TIMER_6_REGS,
	(CSL_TmrRegs *)CSL_TIMER_7_REGS,
	(CSL_TmrRegs *)(CSL_TIMER_7_REGS+(CSL_TIMER_7_REGS-CSL_TIMER_6_REGS))
};

/*DSP core PLL configuration*/
void KeyStone_main_PLL_init ( unsigned int main_PLLM, unsigned int main_PLLD)
{
	unsigned int i;

	if(0<main_PLLM&&main_PLLM<=4096&&0<main_PLLD&&main_PLLD<=64)
	{
		CSL_BootCfgUnlockKicker();

		boot_cfg_regs->CORE_PLL_CTL1 |= 0x00000040; //Set ENSAT = 1

		printf("Initialize main PLL = x%d/%d\n", main_PLLM, main_PLLD);

		/*1. If executing this sequence immediately after device power-up, you must allow for*/
		/*the PLL to become stable. PLL stabilization time is 100 ¦Ìs.                       */
		for(i=0; i< 20000; i++)
			asm(" nop 5");

		/*2. Check the status of BYPASS bit in SECCTL register, execute following steps if   */
		/*BYPASS == 1 (if bypass enabled), otherwise skip this step:                         */
		if(0 != (pllc_regs->SECCTL & 0x00800000))
		{		
			/*a. In MAINPLLCTL1, write ENSAT = 1 (for optimal PLL operation)                     */
			boot_cfg_regs->CORE_PLL_CTL1 |= 0x00000040;      /*Set ENSAT bit = 1*/

			/*b. In PLLCTL, write PLLENSRC = 0 (enable PLLEN to control PLL controller mux       */
			pllc_regs->PLLCTL &= (~(1<<5));

			/*c. In PLLCTL, write PLLEN = 0 (bypass enabled in PLL controller mux)               */
			pllc_regs->PLLCTL &= (~(1<<0));

			/*d. Wait 4 cycles of the reference clock CLKIN (to make sure the PLL controller     */
			/*mux switches properly to the bypass)                                               */
			for(i=0; i< 4*8192/5+1; i++)
				asm(" nop 4");

			/*e. In SECCTL, write BYPASS = 1 (bypass enabled in PLL mux)                         */
			pllc_regs->SECCTL |= 0x00800000;

			/*f. In PLLCTL, write PLLPWRDN = 1 (power down the PLL)                              */
			pllc_regs->PLLCTL |= (1<<1);	//Power down the PLL

			/*g. Wait for at least 5 ¦Ìs based on the reference clock CLKIN (PLL power down      */
			/*toggling time)                                                                     */
			for(i=0; i< 1000; i++)
				asm(" nop 5");

			/*h. In PLLCTL, write PLLPWRDN = 0 (power up the PLL)                                */
			pllc_regs->PLLCTL &= ~(1<<1);         // Power up PLL
		}

		/*3. In PLLCTL, write PLLRST = 1 (PLL is reset)                                      */
		pllc_regs->PLLCTL |= (1<<3);

		/*4. PLLM is split in two different registers. Program PLLM[5:0] in PLL multiplier   */
		/*control register (PLLM) and PLLM[12:6] in MAINPLLCTL0 register                     */
		/*5. BWADJ is split in two different registers. Program BWADJ[7:0] in                */
		/*MAINPLLCTL0 and BWADJ[11:8] in MAINPLLCTL1 register. BWADJ value                   */
		/*must be set to ((PLLM + 1) >> 1) - 1)                                              */
		/*6. Program PLLD in MAINPLLCTL0 register                                            */
		boot_cfg_regs->CORE_PLL_CTL0 = ((main_PLLM-1)<<24)| 	/*BWADJ[7:0]*/
			(((main_PLLM*2-1)&0x1FC0)<<6)|(main_PLLD-1);
		pllc_regs->PLLM= (main_PLLM*2-1)&0x3F;
		boot_cfg_regs->CORE_PLL_CTL1 &= 0xFFFFFFF0; 
		boot_cfg_regs->CORE_PLL_CTL1 |= (main_PLLM-1)>>8;	/*BWADJ[11:8]*/

		/*7. In SECCTL, write OD (Output Divide) = 1 (that is divide-by-2)                   */
		pllc_regs->SECCTL &= 0xff87ffff;
		pllc_regs->SECCTL |= 0x00080000;
		
		/*8. If necessary, program PLLDIVn. Note that you must apply the GO operation to     */
		/*change these dividers to a new ratios (see Section 3.2 ¡®¡®Divider n (D1 to Dn) and*/
		/*GO Operation ¡¯¡¯ on page 3-3).                                                    */

		/*9. Wait for at least 7 ¦Ìs based on the reference clock CLKIN (PLL reset time)     */
		for(i=0; i< 2000; i++)
			asm(" nop 5");

		/*10. In PLLCTL, write PLLRST = 0 (PLL reset is released)                            */
		pllc_regs->PLLCTL &= (~(1<<3));

		/*11. Wait for at least 500 ¡Á CLKIN cycles ¡Á (PLLD + 1) (PLL lock time)            */
		for(i=0; i< 10000*main_PLLD; i++)
			asm(" nop 5");

		/*12. In SECCTL, write BYPASS = 0 (enable PLL mux to switch to PLL mode)             */
		pllc_regs->SECCTL &= ~(0x00800000);
		
		/*13. Set the PLLEN bit in PLLCTL to 1 to enable PLL mode*/
		pllc_regs->PLLCTL= pllc_regs->PLLCTL|(1<<0);

	}

}


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

		printf("Initialize DDR PLL = x%d/%d\n", DDR_PLLM, DDR_PLLD);
		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) ;
	}
}

void KeyStone_PA_PLL_init (unsigned int PA_PLLM,	unsigned int PA_PLLD)
{
	if(0<PA_PLLM&&PA_PLLM<=8192&&0<PA_PLLD&&PA_PLLD<=64)
	{
		CSL_BootCfgUnlockKicker();

		printf("Initialize PA PLL = x%d/%d\n", PA_PLLM, PA_PLLD);
		boot_cfg_regs->PA_PLL_CTL0 = (boot_cfg_regs->PA_PLL_CTL0&0x00F80000)|
			(((PA_PLLM-1)/2)<<24)|((PA_PLLM-1)<<6)|(PA_PLLD-1);
		boot_cfg_regs->PA_PLL_CTL1 = 0x00000040      /*Set ENSAT bit = 1*/
			|((PA_PLLM-1)/2)>>8;	/*BWADJ[11:8]*/

	}
}

unsigned int mem_prot_key[4] = {1, 2, 3, 4};

/*lock memory protection registers*/
void lock_mem_prot_regs()
{
	int i;
	
	/*1. Write a 1 to the KEYR field of the MPLKCMD register. This resets some internal
	status for the MPLK0 through MPLK3 registers.*/
	CGEM_regs->MPLKCMD = (1<<CSL_CGEM_MPLKCMD_KEYR_SHIFT);
	
	/*2. Write the key to MPLK0 through MPLK3. All four registers must be written
	exactly once. They may be written in any order.*/
	for(i=0; i<4; i++)
	{
		CGEM_regs->MPLK[i] = mem_prot_key[i];
	}

	/*3. Write a 1 to the LOCK field of the MPLKCMD register. This engages the lock.*/
	CGEM_regs->MPLKCMD = (1<<CSL_CGEM_MPLKCMD_LOCK_SHIFT);

	/*wait to make sure it is locked*/
	while(0==(CGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK));
}

/*unlock memory protection registers*/
void unlock_mem_prot_regs()
{
	int i;
	
	/*1. Write a 1 to the KEYR field in the MPLKCMD register. This resets some internal
	status for the MPLK0 through the MPLK3 registers.*/
	CGEM_regs->MPLKCMD = (1<<CSL_CGEM_MPLKCMD_KEYR_SHIFT);

	/*2. Write the unlock key to MPLK0 through the MPLK3 registers. The hardware
	compares the written value with the stored key value. Software must write to all
	four registers exactly once. The writes can arrive in any order.*/
	for(i=0; i<4; i++)
	{
		CGEM_regs->MPLK[i] = mem_prot_key[i];
	}

	/*3. Write a 1 to the UNLOCK field in the MPLKCMD register. If the key written in
	step 2 matches the stored key, the hardware disengages the lock. If the key written
	in step 2 does not match, the hardware signals an exception. The hardware
	reports the fault address as the address of the MPLKCMD register.*/
	CGEM_regs->MPLKCMD = (1<<CSL_CGEM_MPLKCMD_UNLOCK_SHIFT);

	/*wait to make sure it is unlocked*/
	while(1==(CGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK));
}

/*XMC memory address extension/mapping and memory protection*/
void KeyStone_XM_cfg()
{
	if(CGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)
		unlock_mem_prot_regs();
	
	/*change memory attribute of the default memory segement 0, 1 
	to read/write, not for execution, to catch runaway code*/
	XMC_regs->XMPAX[0].XMPAXH = 
		((0)&(CSL_XMC_XMPAXH_BADDR_MASK))|
		((30)<<(CSL_XMC_XMPAXH_SEGSZ_SHIFT)); 	/*2^(30+1)=2GB*/
	XMC_regs->XMPAX[0].XMPAXL = 
		((0)&(CSL_XMC_XMPAXL_RADDR_MASK))|
		((1)<<(CSL_XMC_XMPAXL_SR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_SW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_SX_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UX_SHIFT));
	XMC_regs->XMPAX[1].XMPAXH = 
		((0x80000000)&(CSL_XMC_XMPAXH_BADDR_MASK))|
		((30)<<(CSL_XMC_XMPAXH_SEGSZ_SHIFT)); 	/*2^(30+1)=2GB*/
	XMC_regs->XMPAX[1].XMPAXL = 
		((0x80000000)&(CSL_XMC_XMPAXL_RADDR_MASK))|
		((1)<<(CSL_XMC_XMPAXL_SR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_SW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_SX_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UX_SHIFT));

	/*map DDR2 configuration registers at physical address 0x1:00000000 to logical address 0x21000000*/
	XMC_regs->XMPAX[2].XMPAXH = 
		((0x21000000)&(CSL_XMC_XMPAXH_BADDR_MASK))|
		((11)<<(CSL_XMC_XMPAXH_SEGSZ_SHIFT)); 	/*2^(11+1)=4KB*/
	XMC_regs->XMPAX[2].XMPAXL = 
		((0x10000000)&(CSL_XMC_XMPAXL_RADDR_MASK))|
		((1)<<(CSL_XMC_XMPAXL_SR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_SW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_SX_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UX_SHIFT));

	/*remap Shared L2 to 0x18000000 for read/write*/
	XMC_regs->XMPAX[3].XMPAXH = 
		((0x18000000)&(CSL_XMC_XMPAXH_BADDR_MASK))|
		((23)<<(CSL_XMC_XMPAXH_SEGSZ_SHIFT)); 	/*2^(23+1)=16MB*/
	XMC_regs->XMPAX[3].XMPAXL = 
		((0x00C00000)&(CSL_XMC_XMPAXL_RADDR_MASK))|
		((1)<<(CSL_XMC_XMPAXL_SR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_SW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_SX_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UR_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UX_SHIFT));
#if 0
	/*remap the first 16MB DDR for code*/
	XMC_regs->XMPAX[4].XMPAXH = 
		((0x80000000)&(CSL_XMC_XMPAXH_BADDR_MASK))|
		((23)<<(CSL_XMC_XMPAXH_SEGSZ_SHIFT)); 	/*2^(23+1)=16MB*/
	XMC_regs->XMPAX[4].XMPAXL = 
		((0x80000000)&(CSL_XMC_XMPAXL_RADDR_MASK))|
		((0)<<(CSL_XMC_XMPAXL_SR_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_SW_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_SX_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UR_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UW_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UX_SHIFT));

	/*remap the second 16MB DDR for read only*/
	XMC_regs->XMPAX[5].XMPAXH = 
		((0x81000000)&(CSL_XMC_XMPAXH_BADDR_MASK))|
		((23)<<(CSL_XMC_XMPAXH_SEGSZ_SHIFT)); 	/*2^(23+1)=16MB*/
	XMC_regs->XMPAX[5].XMPAXL = 
		((0x80100000)&(CSL_XMC_XMPAXL_RADDR_MASK))|
		((1)<<(CSL_XMC_XMPAXL_SR_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_SW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_SX_SHIFT))|
		((1)<<(CSL_XMC_XMPAXL_UR_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UW_SHIFT))|
		((0)<<(CSL_XMC_XMPAXL_UX_SHIFT));
#endif
	lock_mem_prot_regs();
}

/*----configure the memory protection for local L1 memory----*/
void KeyStone_L1_cfg()
{
	int i;

	if(CGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)
		unlock_mem_prot_regs();

	/*clear any memory protection fault*/
	CGEM_regs->L1PMPFCR = 1;
	CGEM_regs->L1DMPFCR = 1;
	CGEM_regs->L2MPFCR = 1;

	/*set L1P only for local execution*/
	for(i=0; i<16; i++)
	{
		CGEM_regs->L1PMPPA[i] = 
			((0)<<CSL_CGEM_L1PMPPA_AID5_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_AID4_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_AID3_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_AID2_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_AID1_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_AID0_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_AIDX_SHIFT)|
			((1)<<CSL_CGEM_L1PMPPA_LOCAL_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_SR_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_SW_SHIFT)|
			((1)<<CSL_CGEM_L1PMPPA_SX_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_UR_SHIFT)|
			((0)<<CSL_CGEM_L1PMPPA_UW_SHIFT)|
			((1)<<CSL_CGEM_L1PMPPA_UX_SHIFT);
	}
	
	/*set L1D only for local read/write*/
	for(i=0; i<16; i++)
	{
		CGEM_regs->L1DMPPA[i] = 
			((0)<<CSL_CGEM_L1DMPPA_AID5_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_AID4_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_AID3_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_AID2_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_AID1_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_AID0_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_AIDX_SHIFT)|
			((1)<<CSL_CGEM_L1DMPPA_LOCAL_SHIFT)|
			((1)<<CSL_CGEM_L1DMPPA_SR_SHIFT)|
			((1)<<CSL_CGEM_L1DMPPA_SW_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_SX_SHIFT)|
			((1)<<CSL_CGEM_L1DMPPA_UR_SHIFT)|
			((1)<<CSL_CGEM_L1DMPPA_UW_SHIFT)|
			((0)<<CSL_CGEM_L1DMPPA_UX_SHIFT);
	}
	lock_mem_prot_regs();
}

/*----configure the memory protection for local L2 memory----*/
void KeyStone_L2_cfg()
{
	int i;
	TDSP_Type dspType;

	if(CGEM_regs->MPLKSTAT&CSL_CGEM_MPLKSTAT_LK_MASK)
		unlock_mem_prot_regs();
		
	dspType= Get_dsp_type();
	if(TCI6616==dspType||TCI6618==dspType)
	{
		/*set first 64KB LL2 only for local execution*/
		for(i=0; i<2; i++)
		{
			CGEM_regs->L2MPPA[i] = 
				((0)<<CSL_CGEM_L2MPPA_AID5_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID4_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID3_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID2_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID1_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID0_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AIDX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_LOCAL_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SW_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SX_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UW_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UX_SHIFT);
		}

		/*set 32KB LL2 only for read only*/
		for(i=2; i<3; i++)
		{
			CGEM_regs->L2MPPA[i] = 
				((1)<<CSL_CGEM_L2MPPA_AID5_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID4_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID3_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID2_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID1_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID0_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AIDX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_LOCAL_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UX_SHIFT);
		}
		/*set the remaining LL2 for read/write*/
		for(i=3; i<32; i++)
		{
			CGEM_regs->L2MPPA[i] = 
				((1)<<CSL_CGEM_L2MPPA_AID5_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID4_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID3_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID2_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID1_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID0_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AIDX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_LOCAL_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SR_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UR_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UX_SHIFT);
		}
	}
	else if(TCI6608==dspType)
	{
		/*set first 64KB LL2 only for local execution*/
		for(i=0; i<4; i++)
		{
			CGEM_regs->L2MPPA[i] = 
				((0)<<CSL_CGEM_L2MPPA_AID5_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID4_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID3_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID2_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID1_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AID0_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_AIDX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_LOCAL_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SW_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SX_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UW_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UX_SHIFT);
		}

		/*set 32KB LL2 only for read only*/
		for(i=4; i<6; i++)
		{
			CGEM_regs->L2MPPA[i] = 
				((1)<<CSL_CGEM_L2MPPA_AID5_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID4_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID3_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID2_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID1_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID0_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AIDX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_LOCAL_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UR_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UX_SHIFT);
		}
		/*set the remaining LL2 for read/write*/
		for(i=6; i<32; i++)
		{
			CGEM_regs->L2MPPA[i] = 
				((1)<<CSL_CGEM_L2MPPA_AID5_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID4_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID3_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID2_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID1_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AID0_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_AIDX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_LOCAL_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SR_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_SW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_SX_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UR_SHIFT)|
				((1)<<CSL_CGEM_L2MPPA_UW_SHIFT)|
				((0)<<CSL_CGEM_L2MPPA_UX_SHIFT);
		}
	}

	lock_mem_prot_regs();
}

void edma_Init ()
{
	int i;
	unsigned int * uipPaRAM;

	/*clear PaRAM*/
	uipPaRAM= (unsigned int *)&(gEDMACC0Regs->PARAMSET[0]);
	for(i=0; i<8*CSL_EDMA3_TPCC0_NUM_PARAMSETS; i++) 	
		*uipPaRAM++=0;

	uipPaRAM= (unsigned int *)&(gEDMACC1Regs->PARAMSET[0]);
	for(i=0; i<8*CSL_EDMA3_TPCC1_NUM_PARAMSETS; i++) 	
		*uipPaRAM++=0;

	uipPaRAM= (unsigned int *)&(gEDMACC2Regs->PARAMSET[0]);
	for(i=0; i<8*CSL_EDMA3_TPCC2_NUM_PARAMSETS; i++) 	
		*uipPaRAM++=0;
		
	/*Assign PaRAM for different channels*/
	for(i=0; i<CSL_EDMA3_TPCC0_NUM_DMACH; i++) 	
		gEDMACC0Regs->TPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT;

	for(i=0; i<CSL_EDMA3_TPCC1_NUM_DMACH; i++) 	
		gEDMACC1Regs->TPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT;

	for(i=0; i<CSL_EDMA3_TPCC2_NUM_DMACH; i++) 	
		gEDMACC2Regs->TPCC_DCHMAP[i] = i<< CSL_TPCC_TPCC_DCHMAP0_PAENTRY_SHIFT;

	/*Assign TC/Queue for different channels*/
	gEDMACC0Regs->TPCC_DMAQNUM[0]= 0x10101010;
	gEDMACC0Regs->TPCC_DMAQNUM[1]= 0x10101010;

	gEDMACC1Regs->TPCC_DMAQNUM[0]= 0x32103210;
	gEDMACC1Regs->TPCC_DMAQNUM[1]= 0x32103210;
	gEDMACC1Regs->TPCC_DMAQNUM[2]= 0x32103210;
	gEDMACC1Regs->TPCC_DMAQNUM[3]= 0x32103210;
	gEDMACC1Regs->TPCC_DMAQNUM[4]= 0x32103210;
	gEDMACC1Regs->TPCC_DMAQNUM[5]= 0x32103210;
	gEDMACC1Regs->TPCC_DMAQNUM[6]= 0x32103210;
	gEDMACC1Regs->TPCC_DMAQNUM[7]= 0x32103210;

	gEDMACC2Regs->TPCC_DMAQNUM[0]= 0x32103210;
	gEDMACC2Regs->TPCC_DMAQNUM[1]= 0x32103210;
	gEDMACC2Regs->TPCC_DMAQNUM[2]= 0x32103210;
	gEDMACC2Regs->TPCC_DMAQNUM[3]= 0x32103210;
	gEDMACC2Regs->TPCC_DMAQNUM[4]= 0x32103210;
	gEDMACC2Regs->TPCC_DMAQNUM[5]= 0x32103210;
	gEDMACC2Regs->TPCC_DMAQNUM[6]= 0x32103210;
	gEDMACC2Regs->TPCC_DMAQNUM[7]= 0x32103210;

	/*clear any events and status*/
	gEDMACC0Regs->TPCC_ECR= 0xFFFFFFFF;
	gEDMACC0Regs->TPCC_EECR= 0xFFFFFFFF;
	gEDMACC0Regs->TPCC_ICR= 0xFFFFFFFF;
	gEDMACC0Regs->TPCC_IECR= 0xFFFFFFFF;
	gEDMACC0Regs->TPCC_EMCR= 0xFFFFFFFF;
	gEDMACC0Regs->TPCC_SECR= 0xFFFFFFFF;

	gEDMACC1Regs->TPCC_ECR= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_ECRH= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_EECR= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_EECRH= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_ICR= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_ICRH= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_IECR= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_IECRH= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_EMCR= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_EMCRH= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_SECR= 0xFFFFFFFF;
	gEDMACC1Regs->TPCC_SECRH= 0xFFFFFFFF;

	gEDMACC2Regs->TPCC_ECR= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_ECRH= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_EECR= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_EECRH= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_ICR= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_ICRH= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_IECR= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_IECRH= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_EMCR= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_EMCRH= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_SECR= 0xFFFFFFFF;
	gEDMACC2Regs->TPCC_SECRH= 0xFFFFFFFF;

}

Int32 Keystone_enable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum)
{
    /* Set Power domain to ON */
    CSL_PSC_enablePowerDomain (pwrDmnNum);

    /* Enable the clocks too*/
    CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_ENABLE);

    /* Start the state transition */
    CSL_PSC_startStateTransition (pwrDmnNum);

    /* Wait until the state transition process is completed. */
    while (!CSL_PSC_isStateTransitionDone (pwrDmnNum));

    /* Return PSC status */
    if ((CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_ON) &&
        (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_ENABLE))
    {
        /*Ready for use */
        return 0;
    }
    else
    {
        /*Return error */
        return -1;
    }
}

Int32 Keystone_disable_PSC_module (Uint32 pwrDmnNum, Uint32 moduleNum)
{
    /* disable the clocks*/
    CSL_PSC_setModuleNextState (moduleNum, PSC_MODSTATE_SWRSTDISABLE);

    /* Start the state transition */
    CSL_PSC_startStateTransition (pwrDmnNum);

    /* Wait until the state transition process is completed. */
    while (!CSL_PSC_isStateTransitionDone (pwrDmnNum));

    /* Return PSC status */
    if (CSL_PSC_getModuleState (moduleNum) == PSC_MODSTATE_SWRSTDISABLE)
    {
        /*Ready for use */
        return 0;
    }
    else
    {
        /*Return error */
        return -1;
    }

}

Int32 Keystone_disable_PSC_Power_Domain (Uint32 pwrDmnNum)
{
    /* Set Power domain to OFF */
    CSL_PSC_disablePowerDomain (pwrDmnNum);

    /* Start the state transition */
    CSL_PSC_startStateTransition (pwrDmnNum);

    /* Wait until the state transition process is completed. */
    while (!CSL_PSC_isStateTransitionDone (pwrDmnNum));

    /* Return PSC status */
    if (CSL_PSC_getPowerDomainState(pwrDmnNum) == PSC_PDSTATE_OFF)
    {
        /*Ready for use */
        return 0;
    }
    else
    {
        /*Return error */
        return -1;
    }

}

void Reset_Timer(int timer_num)
{
	if(timerRegs[timer_num]->TGCR)
	{
		timerRegs[timer_num]->TGCR= 0;
		timerRegs[timer_num]->TCR= 0;
	}
}

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

	timerRegs[timer_num]->CNTLO= 0;
	timerRegs[timer_num]->CNTHI= 0;

	timerRegs[timer_num]->PRDLO= _loll(period);
	timerRegs[timer_num]->PRDHI= _hill(period);

	timerRegs[timer_num]->TGCR= 
		/*Select 64-bit general timer mode*/
		(CSL_TMR_TIMMODE_GPT<<CSL_TMR_TGCR_TIMMODE_SHIFT)
		/*Remove the timer from reset*/
		|(CSL_TMR_TGCR_TIMLORS_RESET_OFF<<CSL_TMR_TGCR_TIMLORS_SHIFT)
		|(CSL_TMR_TGCR_TIMHIRS_RESET_OFF<<CSL_TMR_TGCR_TIMHIRS_SHIFT);

	/*make timer stop with emulation*/
	timerRegs[timer_num]->EMUMGT_CLKSPD = (timerRegs[timer_num]->EMUMGT_CLKSPD&
		~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK));

	timerRegs[timer_num]->TCR= 
		(CSL_TMR_CLOCK_INP_NOGATE<<CSL_TMR_TCR_TIEN_LO_SHIFT   ) 
		|(CSL_TMR_CLKSRC_INTERNAL<<CSL_TMR_TCR_CLKSRC_LO_SHIFT ) 
		/*The timer is enabled continuously*/
		|(CSL_TMR_ENAMODE_CONT<<CSL_TMR_TCR_ENAMODE_LO_SHIFT) 
		|(0<<CSL_TMR_TCR_PWID_LO_SHIFT   ) 
		/*select clock mode*/
		|(CSL_TMR_CP_CLOCK<<CSL_TMR_TCR_CP_LO_SHIFT     ) 
		|(CSL_TMR_INVINP_UNINVERTED<<CSL_TMR_TCR_INVINP_LO_SHIFT ) 
		|(CSL_TMR_INVOUTP_UNINVERTED<<CSL_TMR_TCR_INVOUTP_LO_SHIFT) 
		|(0<<CSL_TMR_TCR_TSTAT_LO_SHIFT  );
}

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

	timerRegs[timer_num]->CNTLO= 0;
	timerRegs[timer_num]->CNTHI= 0;

	timerRegs[timer_num]->PRDLO= _loll(delay);
	timerRegs[timer_num]->PRDHI= _hill(delay);

	timerRegs[timer_num]->TGCR= 
		/*Select 64-bit general timer mode*/
		(CSL_TMR_TIMMODE_GPT<<CSL_TMR_TGCR_TIMMODE_SHIFT)
		/*Remove the timer from reset*/
		|(CSL_TMR_TGCR_TIMLORS_RESET_OFF<<CSL_TMR_TGCR_TIMLORS_SHIFT)
		|(CSL_TMR_TGCR_TIMHIRS_RESET_OFF<<CSL_TMR_TGCR_TIMHIRS_SHIFT);

	/*make timer stop with emulation*/
	timerRegs[timer_num]->EMUMGT_CLKSPD = (timerRegs[timer_num]->EMUMGT_CLKSPD&
		~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK));

	timerRegs[timer_num]->TCR= 
		(CSL_TMR_CLOCK_INP_NOGATE<<CSL_TMR_TCR_TIEN_LO_SHIFT   ) 
		|(CSL_TMR_CLKSRC_INTERNAL<<CSL_TMR_TCR_CLKSRC_LO_SHIFT ) 
		/*The timer is enabled one-shot*/
		|(CSL_TMR_ENAMODE_ENABLE<<CSL_TMR_TCR_ENAMODE_LO_SHIFT) 
		|(3<<CSL_TMR_TCR_PWID_LO_SHIFT   ) 
		/*select pulse mode*/
		|(CSL_TMR_CP_PULSE<<CSL_TMR_TCR_CP_LO_SHIFT     ) 
		|(CSL_TMR_INVINP_UNINVERTED<<CSL_TMR_TCR_INVINP_LO_SHIFT ) 
		|(CSL_TMR_INVOUTP_UNINVERTED<<CSL_TMR_TCR_INVOUTP_LO_SHIFT) 
		|(0<<CSL_TMR_TCR_TSTAT_LO_SHIFT  );

}

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

	timerRegs[timer_num]->CNTLO= 0;
	timerRegs[timer_num]->CNTHI= 0;

	timerRegs[timer_num]->PRDLO= _loll(period);
	timerRegs[timer_num]->PRDHI= _hill(period);

	timerRegs[timer_num]->TGCR= 
		/*Select watch-dog mode*/
		(CSL_TMR_TIMMODE_WDT<<CSL_TMR_TGCR_TIMMODE_SHIFT)
		/*Remove the timer from reset*/
		|(CSL_TMR_TGCR_TIMLORS_RESET_OFF<<CSL_TMR_TGCR_TIMLORS_SHIFT)
		|(CSL_TMR_TGCR_TIMHIRS_RESET_OFF<<CSL_TMR_TGCR_TIMHIRS_SHIFT);

	/*make timer stop with emulation*/
	timerRegs[timer_num]->EMUMGT_CLKSPD = (timerRegs[timer_num]->EMUMGT_CLKSPD&
		~(CSL_TMR_EMUMGT_CLKSPD_FREE_MASK|CSL_TMR_EMUMGT_CLKSPD_SOFT_MASK));

	/*enable watchdog timer*/
	timerRegs[timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK
		|(CSL_TMR_WDTCR_WDKEY_CMD1<<CSL_TMR_WDTCR_WDKEY_SHIFT);

	timerRegs[timer_num]->TCR= 
		(CSL_TMR_CLOCK_INP_NOGATE<<CSL_TMR_TCR_TIEN_LO_SHIFT   ) 
		|(CSL_TMR_CLKSRC_INTERNAL<<CSL_TMR_TCR_CLKSRC_LO_SHIFT ) 
		/*The timer is enabled continuously*/
		|(CSL_TMR_ENAMODE_CONT<<CSL_TMR_TCR_ENAMODE_LO_SHIFT) 
		|(3<<CSL_TMR_TCR_PWID_LO_SHIFT   ) 
		/*select pulse mode*/
		|(CSL_TMR_CP_PULSE<<CSL_TMR_TCR_CP_LO_SHIFT     ) 
		|(CSL_TMR_INVINP_UNINVERTED<<CSL_TMR_TCR_INVINP_LO_SHIFT ) 
		|(CSL_TMR_INVOUTP_UNINVERTED<<CSL_TMR_TCR_INVOUTP_LO_SHIFT) 
		|(0<<CSL_TMR_TCR_TSTAT_LO_SHIFT  );

	/*active watchdog timer*/
	timerRegs[timer_num]->WDTCR = CSL_TMR_WDTCR_WDEN_MASK
		|(CSL_TMR_WDTCR_WDKEY_CMD2<<CSL_TMR_WDTCR_WDKEY_SHIFT);

}

/*write sequence of a A5C6h followed by a DA7Eh 
to services the watchdog timer.*/
void Service_Watchdog(int timer_num)
{
	timerRegs[timer_num]->WDTCR =
		(CSL_TMR_WDTCR_WDKEY_CMD1<<CSL_TMR_WDTCR_WDKEY_SHIFT);
	timerRegs[timer_num]->WDTCR =
		(CSL_TMR_WDTCR_WDKEY_CMD2<<CSL_TMR_WDTCR_WDKEY_SHIFT);
}

unsigned int cycle_measure_overhead=50;
void calc_cycle_measure_overhead()
{
	unsigned int cycle_cold, cycle_warm;
	cycle_cold= TSCL;
	cycle_cold = TSC_getDelay(cycle_cold);
	cycle_warm= TSCL;
	cycle_warm = TSC_getDelay(cycle_warm);
	cycle_measure_overhead = (cycle_cold + cycle_warm)/2;
}

/* Initialize Time stame counter to measure cycles*/
void TSC_init()
{
	TSCL = 0; 	/* Enable the TSC */
	calc_cycle_measure_overhead();
}

/*delay in millisecond*/
void TSC_delay_ms(Uint32 ms)
{
	volatile Uint32 preTSC;
	preTSC= TSCL; 
	while(TSC_count_cycle_from(preTSC)<(ms*(1000000000000/CPU_CLK_KHZ)));
}

/*delay in microsecond*/
void TSC_delay_us(Uint32 us)
{
	volatile Uint32 preTSC;
	preTSC= TSCL; 
	while(TSC_count_cycle_from(preTSC)<(us*(1000000000/CPU_CLK_KHZ)));
}

void Exception_cfg()
{
	puts("Enable Exception handling for NMI, memory protection, interrupt drop and bus error");

	TSCL = 0; 	/* Enable the TSC */
	
	/*clear all exception events*/
	CGEM_regs->EVTCLR[0] = 0xFFFFFFFF;
	CGEM_regs->EVTCLR[1] = 0xFFFFFFFF;
	CGEM_regs->EVTCLR[2] = 0xFFFFFFFF;
	CGEM_regs->EVTCLR[3] = 0xFFFFFFFF;

	/*clear memory falut*/
	CGEM_regs->L1PMPFCR = 1;
	CGEM_regs->L1DMPFCR = 1;
	CGEM_regs->L2MPFCR = 1;
	XMC_regs->XMPFCR = 1;

	/*clear interrupt drop staus*/
	CGEM_regs->INTXCLR = 1;

	/*enable events:
	10 MSMC_mpf_error_n Memory protection fault indicators for local CorePac
	96 INTERR Dropped CPU interrupt event
	119 SYS_CMPA CPU Memory Protection Fault
	120 PMC_CMPA CPU memory protection fault
	121 PMC_DMPA DMA memory protection fault
	122 DMC_CMPA CPU memory protection fault
	123 DMC_DMPA DMA memory protection fault
	124 UMC_CMPA CPU memory protection fault
	125 UMC_DMPA DMA memory protection fault
	126 EMC_CMPA CPU memory protection fault
	127 EMC_BUSERR Bus Error Interrupt
	*/
	CGEM_regs->EXPMASK[0]= ~(1<<10);
	CGEM_regs->EXPMASK[1]= 0xFFFFFFFF;
	CGEM_regs->EXPMASK[2]= 0xFFFFFFFF;
	CGEM_regs->EXPMASK[3]= ~(1|
		(1<<(119-96))|
		(1<<(120-96))|
		(1<<(121-96))|
		(1<<(122-96))|
		(1<<(123-96))|
		(1<<(124-96))|
		(1<<(125-96))|
		(1<<(126-96))|
		(1<<(127-96)));

	/*clear exception flag*/
	ECR = EFR;
	IERR = 0; 

	/*Eanble external exception, global exception enable*/
	TSR = TSR|
		(1<<CSL_CHIP_TSR_XEN_SHIFT)|
		(1<<CSL_CHIP_TSR_GEE_SHIFT);

	/*enable NMI exception*/
	IER = IER|(1<<CSL_CHIP_IER_NMI_SHIFT);
	
}

void memory_protection_exception(unsigned int MPFAR, 
	unsigned int MPFSR)
{
	unsigned int master_id;

	if(0 == MPFSR)
		return;

	master_id = (MPFSR&CSL_CGEM_L2MPFSR_FID_MASK)>>
		CSL_CGEM_L2MPFSR_FID_SHIFT;

	printf("memory protection exception caused by master %d at 0x%x\n", 
		master_id, MPFAR);

	if (MPFSR & CSL_CGEM_L2MPFSR_LOCAL_MASK) {
		puts("  local access violation");
	}
	if (MPFSR & CSL_CGEM_L2MPFSR_UX_MASK) {
		puts("  User Execute violation");
	}
	if (MPFSR & CSL_CGEM_L2MPFSR_UW_MASK) {
		puts("  User Write violation");
	}
	if (MPFSR & CSL_CGEM_L2MPFSR_UR_MASK) {
		puts("  User Read violation");
	}
	if (MPFSR & CSL_CGEM_L2MPFSR_SX_MASK) {
		puts("  Supervisor Execute violation");
	}
	if (MPFSR & CSL_CGEM_L2MPFSR_SW_MASK) {
		puts("  Supervisor Write violation");
	}
	if (MPFSR & CSL_CGEM_L2MPFSR_SR_MASK) {
		puts("  Supervisor Read violation");
	}
	
}

void EXC_external(void)
{
	unsigned int INTXSTAT, flag[4];

	flag[0] = CGEM_regs->MEXPFLAG[0];
	flag[1] = CGEM_regs->MEXPFLAG[1];
	flag[2] = CGEM_regs->MEXPFLAG[2];
	flag[3] = CGEM_regs->MEXPFLAG[3];
	puts("External exception happened");
	if(flag[0])
		printf("External exception flag MEXPFLAG[0]=0x%x\n", flag[0]);
	if(flag[1])
		printf("External exception flag MEXPFLAG[1]=0x%x\n", flag[1]);
	if(flag[2])
		printf("External exception flag MEXPFLAG[2]=0x%x\n", flag[2]);
	if(flag[3])
		printf("External exception flag MEXPFLAG[3]=0x%x\n", flag[3]);

	/*10 MSMC_mpf_error_n Memory protection fault indicators for local CorePac*/
	if(flag[0]&(1<<10))
	{
		memory_protection_exception(XMC_regs->XMPFAR, XMC_regs->XMPFSR);
	}

	/*96 INTERR Dropped CPU interrupt event   */
	if(flag[3]&1)
	{
		INTXSTAT= CGEM_regs->INTXSTAT;
		if(INTXSTAT&CSL_CGEM_INTXSTAT_DROP_MASK)
			printf("DSPINT %d dropped, System Event number = %d\n",
				(INTXSTAT&CSL_CGEM_INTXSTAT_CPUINT_MASK)>>CSL_CGEM_INTXSTAT_CPUINT_SHIFT,
				(INTXSTAT&CSL_CGEM_INTXSTAT_SYSINT_MASK)>>CSL_CGEM_INTXSTAT_SYSINT_SHIFT);
	}

	/*119 SYS_CMPA CPU Memory Protection Fault*/
	if(flag[3]&(3<<(119-96)))
	{
		puts("local registers (INTC, PowerDown...) are accessed illeagely");
	}

	/*120 PMC_CMPA CPU memory protection fault*/
	/*121 PMC_DMPA DMA memory protection fault*/
	if(flag[3]&(3<<(120-96)))
	{
		memory_protection_exception(CGEM_regs->L1PMPFAR, CGEM_regs->L1PMPFSR);
	}
	/*122 DMC_CMPA CPU memory protection fault*/
	/*123 DMC_DMPA DMA memory protection fault*/
	if(flag[3]&(3<<(122-96)))
	{
		memory_protection_exception(CGEM_regs->L1DMPFAR, CGEM_regs->L1DMPFSR);
	}
	/*124 UMC_CMPA CPU memory protection fault*/
	/*125 UMC_DMPA DMA memory protection fault*/
	if(flag[3]&(3<<(124-96)))
	{
		memory_protection_exception(CGEM_regs->L2MPFAR, CGEM_regs->L2MPFSR);
	}

}

/*internal exception handler*/
void EXC_internal(void)
{
	unsigned int ierr;

	/*record IERR */    
	ierr = IERR;
	
	if (ierr & CSL_CHIP_IERR_IFX_MASK) {
		puts("Instruction fetch exception happened");
	}
	else if (ierr & CSL_CHIP_IERR_FPX_MASK) {
		puts("Fetch packet exception happened");
	}
	else if (ierr & CSL_CHIP_IERR_EPX_MASK) {
		puts("Execute patcket exception happened");
	}
	else if (ierr & CSL_CHIP_IERR_OPX_MASK) {
		puts("Opcode exception happened");
	}
	else if (ierr & CSL_CHIP_IERR_RCX_MASK) {
		puts("Resource conflict exception happened");
	}
	else if (ierr & CSL_CHIP_IERR_RAX_MASK) {
		puts("Resource access exception happened");
	}
	else if (ierr & CSL_CHIP_IERR_PRX_MASK) {
		puts("Privilege exception happened");
	}
	else if (ierr & CSL_CHIP_IERR_LBX_MASK) {
		puts("Loop buffer exception happened");
	}
	else {
		printf("internal exception. IERR= 0x%x\n", ierr);
	}
	
}

void EXC_nmi(void)
{
	puts("NMI exception happened, normally you should reset the DSP to recover from the problem!");
}

/*software generated exception handler*/
void EXC_swgen(void)
{	
	puts("Software generated exception happened.");
}

void interrupt Exeception_ISR(void)
{
	unsigned int efr, nrp, ntsr, tscl, tsch;

	/*record timestamp*/
	tscl = TSCL;
	tsch = TSCH;
	
	nrp = NRP;   /*record NRP */
	ntsr = NTSR; /*record NTSR */
	efr = EFR;   /*record EFR */
	
	/*check all possible exceptions*/
	if (efr & CSL_CHIP_EFR_OXF_MASK) {
		/* S/W generated exception */
		EXC_swgen();		
	}
	else if (efr & CSL_CHIP_EFR_IXF_MASK) {
		/* internal exception */
		EXC_internal();		
	}
	else if (efr & CSL_CHIP_EFR_EXF_MASK) {
		/* external exception */
		EXC_external();		
	}
	else if (efr & CSL_CHIP_EFR_NXF_MASK) {
		/* legacy NMI exception */
		EXC_nmi();		
	}
	else {
		printf("Exception happened. EFR = 0x%x\n", efr);
	}

	printf("NRP=0x%x, NTSR=0x%x, TSCH= 0x%x, TSCL= 0x%x\n", 
		nrp, ntsr, tsch, tscl);

	while(1);		//trap
}



