#include "ucp_cpri.h"
#include "ape_cnt.h"
#include "ape_csu.h"
#include "stc_timer.h"
#include "ucp_cpri.h"
#include "ucp_js_subcrg.h"
#include "ucp_js_ctrl.h"
#include "ucp_sfr_c.h"
#include "phy_para.h"
#include "ape_cpri_timer.h"
#include "ucp_drv_common.h"
#include "ucp_utility.h"
#include "ucp_printf.h"
#include "smartos.h"

extern void osp_timer_call_task();
extern void osp_timer_call_task_spe(uint8_t u8slot, uint8_t u8taskidx);        /* ?¡§¨º¡À¦Ì?¨¨???¡ä¨®¨º¡Á???a¨º? */

stStcTimerPara gStcTimerPara;
extern stPhyScsPara* phyPara;
extern uint32_t			gScsId;

void ape_stc_init()
{
    int32_t apeId = get_core_id();
#ifdef PALLADIUM_TEST
    int32_t flag = 1;
    debug_write((DBG_DDR_IDX_DRV_BASE+1+(apeId<<2)), flag);	// 0x4
#endif

    uint32_t pClk = stc_pclk_init();
    if (0 == pClk)
    {
        UCP_PRINT_EMPTY("stc_init: pClk get error! \r\n");
#ifdef PALLADIUM_TEST
        flag = -1;
        debug_write((DBG_DDR_IDX_DRV_BASE+1+(apeId<<2)), flag);
#endif
    return;
    }

#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+1+(apeId<<2)), flag);
#endif
    stc_timer_init(pClk, STC_RT);

#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+1+(apeId<<2)), flag);
#endif

    do_write(&(TOD_REG_NF), (0xC0000000 | pClk)); // init finished
}

uint32_t stc_pclk_init()
{
	uint32_t pClk = 0;
	int32_t protoSel = get_protocol_sel();
	int32_t protoOpt = get_protocol_opt();
	if (PROTOCOL_CPRI == protoSel)
	{
		while (1 != (do_read_volatile(SERDES_INIT_FLAG_ADDR))); 	// wait cpri serdes clk init finished
		
		uint32_t serdesTxClk = 0;
		switch (protoOpt)
		{
		case (CPRI_OPTION_7):
		{
			serdesTxClk = 491520000;
			break;
		}
		case (CPRI_OPTION_8):
		{
			serdesTxClk = 316800000;
			break;
		}
		case (CPRI_OPTION_9):
		{
			serdesTxClk = 380160000;
			break;
		}
		case (CPRI_OPTION_10):
		{
			serdesTxClk = 760320000;
			break;
		}
		default:
		{
			serdesTxClk = 316800000;
			break;
		}
		}
		JECS_CRG_PLLSEL &= (~(1 << 22));	// cpri_tx_clk_sel = 0, sel jecs_serdes_tx_clk as cpri_serdes_tx_clk
		JECS_CTRL_PROTOCOL_SEL &= (~0x1);	// jecs_protocol_sel = 0, sel cpri protocol
		JECS_CTRL_REG39 |= (1 << 6);		// enable ecpri_serdes_tx_clk
		JECS_CRG_PLLSEL &= (~(1 << 6));		// pma_clk_sel2 = 0, sel jecs_ecpri_serdes_tx_clk
		JECS_CRG_PLLSEL |= (0x7 << 7);		// stc_src_clk_sel[2:0]=0x7
		JECS_CRG_CLK_CTRL3 = 0x520000;		// jecs3_div=1, stc pclk = cpri_serdes_tx_clk
		pClk = serdesTxClk;
	}
	else if (PROTOCOL_ECPRI == protoSel)
	{
		uint32_t serdesTxClk = 0;
		switch (protoOpt)
		{
		case (ECPRI_OPTION_10G):
		{
			serdesTxClk = 156250000;
			break;
		}
		case (ECPRI_OPTION_25G):
		{
			serdesTxClk = 390625000;
			break;
		}
		default:
		{
			serdesTxClk = 156250000;
			break;
		}
		}
//		JECS_CRG_PLLSEL &= (~(1 << 22));	// cpri_tx_clk_sel = 0, sel jecs_serdes_tx_clk as cpri_serdes_tx_clk
		JECS_CTRL_PROTOCOL_SEL |= 0x1;		// jecs_protocol_sel = 1, sel ecpri protocol
		JECS_CTRL_REG39 |= (1 << 6);		// enable ecpri_serdes_tx_clk
		JECS_CRG_PLLSEL &= (~(1 << 6));		// pma_clk_sel2 = 0, sel jecs_ecpri_serdes_tx_clk
		JECS_CRG_PLLSEL |= (0x7 << 7);		// stc_src_clk_sel[2:0]=0x7
		JECS_CRG_CLK_CTRL3 = 0x520000;		// jecs3_div=1, stc pclk = cpri_serdes_tx_clk
		pClk = serdesTxClk;
	}
	else if (PROTOCOL_JESD == protoSel)
	{
		while (1 != (do_read_volatile(SERDES_INIT_FLAG_ADDR))); 	// wait jesd serdes clk init finished
		JECS_CRG_PLLSEL |= (0x6 << 7);		// stc_src_clk_sel[2:0]=0x6
		JECS_CRG_CLK_CTRL3 = 0x520000;		// jecs3_div=1, stc pclk = cpri_serdes_tx_clk
		// laneRate = IQ_sample_rate * M * N' * (10/8)/L // max_laneRate = 12.5Gbps
		// serdesTxClk = laneRate/40;
		// pClk = serdesTxClk;
		uint32_t samClk = do_read_volatile(JESD_TX_SAMPLE_RATE);
		uint32_t jesdPara = do_read_volatile(JESD_TX_CH_PARA);
		uint8_t paraL = jesdPara & 0xFF;
		uint8_t paraM = (jesdPara >> 8) & 0xFF;
		uint8_t paraN = (jesdPara >> 16) & 0xFF;
		pClk = (uint64_t)(samClk/paraL/40)*paraM*paraN*10/8; // (uint64_t)(122880000/4/40)*8*16*10/8;
	}
	else
	{
		PETP_CLK_CFG_REG	 = 0x523000;	// ECS_PCLK=1G/4=250M
		JECS_CRG_CLK_CTRL3	 = 0x520000;	// STC_PCLK=ECS_PCLK/1=250M
//		JECS_CRG_PLLSEL		&= (~(1 << 9));	// stc_src_clk_sel2=0
		pClk = 250000000; // 100000000;

		UCP_PRINT_EMPTY("stc_pclk_init: use soc_crg to generate pclk, 250M. \r\n");
	}

	return pClk;
}

int32_t gcd_stein(uint32_t x, uint32_t y)
{
	if (x < y)
	{
		int32_t tmp = x;
		x = y;
		y = tmp;
	}
	if (0 == (x%y))
	{
		return y;
	}
	if ((0 == (x%2)) && (0 == (y%2)))
	{
		return (2*gcd_stein(x>>1, y>>1));
	}
	else if ((0 == (x%2)) && (0 != (y%2)))
	{
		return (gcd_stein(x>>1, y));
	}
	else if ((0 != (x%2)) && (0 == (y%2)))
	{
		return (gcd_stein(x, y>>1));
	}
	else if ((0 != (x%2)) && (0 != (y%2)))
	{
		return (gcd_stein(x, ((x-y)>>1)));
	}
	else
	{
		return 0;
	}
}

void stc_timer_init(uint32_t pClk, uint32_t valR)
{
    int32_t apeId = get_core_id();
#ifdef PALLADIUM_TEST
    int32_t flag = 1;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag); // 0x8
#endif
    stc_timer_tod_init(pClk);
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif
#if 0
	stc_pp1s_src_init(STC_PP1S_SRC_GPS);	// select gps pp1s as stc ppls input
#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+64+2+(apeId<<2)), flag);
#endif
#endif
    stc_timer_para_init(pClk, valR);
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

    stc_timer_local_init();
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

    stc_timer0_para_init();
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

    stc_timer1_para_init();
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif
}

void stc_timer_para_init(uint32_t pClk, uint32_t valR)
{
    //int apeId = get_core_id();
    uint32_t remain = 0;
    uint32_t gcd = 0;

    memset(&gStcTimerPara, 0, sizeof(stStcTimerPara));
    gStcTimerPara.pClk = pClk;
    gStcTimerPara.R = valR;
    gStcTimerPara.usR = valR / 1000000;
    gStcTimerPara.N1 = valR/pClk;
    if (gStcTimerPara.N1 * pClk == valR)
    {
        gStcTimerPara.N1 -= 1;
    }
    gStcTimerPara.N = gStcTimerPara.N1 + 1;
    remain = valR-gStcTimerPara.N1*pClk;
    gcd = gcd_stein(pClk, remain);
    if (0 == gcd)
    {
        UCP_PRINT_EMPTY("gcd error! \r\n");
        return;
    }
    gStcTimerPara.A = remain / gcd;
    gStcTimerPara.C = pClk / gcd;

    UCP_PRINT_EMPTY("pclk = 0x%x. \r\n", gStcTimerPara.pClk);
    UCP_PRINT_EMPTY("R = 0x%x. \r\n", gStcTimerPara.R);
    UCP_PRINT_EMPTY("N = 0x%x. \r\n", gStcTimerPara.N);
    UCP_PRINT_EMPTY("N1 = 0x%x. \r\n", gStcTimerPara.N1);
    UCP_PRINT_EMPTY("A = 0x%x. \r\n", gStcTimerPara.A);
    UCP_PRINT_EMPTY("C = 0x%x. \r\n", gStcTimerPara.C);
#if 0 // def PALLADIUM_TEST
    debug_write((DBG_DDR_IDX_DRV_BASE+24), gStcTimerPara.pClk); // 0x60
    debug_write((DBG_DDR_IDX_DRV_BASE+25), gStcTimerPara.N);	// 0x64
    debug_write((DBG_DDR_IDX_DRV_BASE+26), gStcTimerPara.A);	// 0x68
    debug_write((DBG_DDR_IDX_DRV_BASE+27), gStcTimerPara.C);	// 0x6c
#endif
}

void stc_timer_tod_init(uint32_t pClk)
{
    JECS_CRG_STC_RST_CTRL |= BIT24;

    stc_tod_para_init(pClk);
    //stc_timer_todint_init();

    //do_write(STC_TOD_INT_ADDR, 0);	// clear tod int flag
}

void stc_pp1s_src_init(uint8_t srcId)
{
	//                             gnss_sel     stc_sel     cpri_sel
	//JECS_CTRL_CPRI_GMAC_PHY_INT = (0x0 << 4) | (0x5 << 7) | (0x6<<10);
	JECS_CTRL_CPRI_GMAC_PHY_INT &= ~(0x7 << 7);
	JECS_CTRL_CPRI_GMAC_PHY_INT |= (srcId << 7);	// select gps pp1s as stc ppls input
}

void stc_timer_local_init()
{
    LTBG_REG_R = gStcTimerPara.R;
    LTBG_TIME_SET = 0;
    LTBG_REG_A = gStcTimerPara.A;
    LTBG_REG_C = gStcTimerPara.C;
    LTBG_REG_N = gStcTimerPara.N;
    LTBG_REG_N1 = gStcTimerPara.N1;
}

void stc_timer0_para_init()
{
    LTBG0_REG_R = gStcTimerPara.R;
    LTBG0_TIME_SET = 0;
    LTBG0_REG_A = gStcTimerPara.A;
    LTBG0_REG_C = gStcTimerPara.C;
    LTBG0_REG_N = gStcTimerPara.N;
    LTBG0_REG_N1 = gStcTimerPara.N1;
}

void stc_timer1_para_init()
{
    LTBG1_REG_R = gStcTimerPara.R;
    LTBG1_TIME_SET = 0;
    LTBG1_REG_A = gStcTimerPara.A;
    LTBG1_REG_C = gStcTimerPara.C;
    LTBG1_REG_N = gStcTimerPara.N;
    LTBG1_REG_N1 = gStcTimerPara.N1;
}

void stc_tod_para_init(uint32_t pClk)
{
    //TOD_REG_FT_LO = 0;    // 0xB0AAAAAA;  // 0x11AAAAAA; //
    //TOD_REG_FT_HI = 40;   // 40;          //4;  //
    double nsOfClk = 1000000000.0 / pClk;
    uint32_t hiOfFt = 1000000000 / pClk;
    uint64_t coff = (1ULL<<32);
    uint32_t loOfFt = (uint32_t)((double)(nsOfClk - hiOfFt) * coff); // ???

#ifdef PALLADIUM_TEST
	debug_write((DBG_DDR_IDX_DRV_BASE+5), loOfFt); // 0x8
	debug_write((DBG_DDR_IDX_DRV_BASE+6), hiOfFt); // 0xc
#endif
    do_write((&TOD_REG_FT_LO), loOfFt);
    do_write((&TOD_REG_FT_HI), hiOfFt);

    uint32_t loOfRt = 0;
    uint32_t hiOfRt = 0;
    //#ifdef PALLADIUM_TEST
    //  hiOfRt = STC_RT_PALLADIUM; // one tod period: 100ms
    //  do_write(STC_RT_ADDR, STC_RT_PALLADIUM);
    //#else
    hiOfRt = STC_RT;
    do_write(STC_RT_ADDR, STC_RT);
    //#endif

    UCP_PRINT_EMPTY("RT LO = 0x%x. \r\n", loOfRt);
    UCP_PRINT_EMPTY("RT HI = 0x%x. \r\n", hiOfRt);

    do_write((&TOD_REG_RT_LO), loOfRt);
    do_write((&TOD_REG_RT_HI), hiOfRt);

    TOD_REG_CONFIG |= (1<<3);	// onepps_output_enable
    do_write(STC_ONEPPS_OUT_ADDR, 1);
}

void stc_timer_sync(int32_t nScsId)
{
    gStcTimerPara.slotTddNumMax = do_read_volatile_short(&(phyPara[nScsId].slotNumOfTdd));
    __ucps2_synch(f_SMR);
    gStcTimerPara.slotPointNum = TDD_TMR_POINT_MAX / TDD_SLOT_NUM_MAX; // 500/10=50 // gStcTimerPara.slotTddNumMax;
}

void stc_timer_set_tmrpoint(stStcTimerPoint* pTmrPoint)
{
	stc_timer_ctwint_disable();

	gStcTimerPara.slotTddNumMax = do_read_volatile_short(&(phyPara[gScsId].slotNumOfTdd));
	__ucps2_synch(f_SMR);
	gStcTimerPara.slotPointNum = TDD_TMR_POINT_MAX / TDD_SLOT_NUM_MAX; // 500/10=50 // gStcTimerPara.slotTddNumMax;
	gStcTimerPara.R = STC_RT;
	gStcTimerPara.usR = STC_RT / 1000000;
	gStcTimerPara.ctwSetFinished = 0;
	gStcTimerPara.ctwStartFlag = 0;
	gStcTimerPara.tmrPointTotalNum = 0;
	memset(gStcTimerPara.tmrPointNum, 0, TDD_SLOT_NUM_MAX);
	memset(gStcTimerPara.tmrPoint, 0, sizeof(stStcTimerPoint)*TDD_SLOT_NUM_MAX);
	gStcTimerPara.curSlotNum = 0;
	gStcTimerPara.curSlotTmrPointId = 0;
	
	int32_t apeId = get_core_id();
	if (NULL == pTmrPoint)
	{
		UCP_PRINT_ERROR("pTmrPoint NULL! \r\n");
		return;
	}
    UCP_PRINT_LOG("stc timer set tmrpoint start. \r\n");

	int32_t idx = 0;
	for (int32_t i = 0; i < gStcTimerPara.slotTddNumMax; i++)
	{
		for (int32_t j = 0; j < gStcTimerPara.slotPointNum; j++)
		{
			idx = i*gStcTimerPara.slotPointNum+j;
			gStcTimerPara.tmrPoint[idx].pointVal = pTmrPoint[idx].pointVal*gStcTimerPara.usR;
			gStcTimerPara.tmrPoint[idx].lastFlag = pTmrPoint[idx].lastFlag;
			gStcTimerPara.tmrPointNum[i]++;
			gStcTimerPara.tmrPointTotalNum++;
#ifdef PALLADIUM_TEST
			debug_write((DBG_DDR_IDX_DRV_BASE+5120+(apeId<<10) + (idx<<1)), gStcTimerPara.tmrPoint[idx].pointVal); // 0x5000
			debug_write((DBG_DDR_IDX_DRV_BASE+5120+(apeId<<10) + ((idx<<1) + 1)), gStcTimerPara.tmrPoint[idx].lastFlag); // 0x5000
#endif
			if (1 == pTmrPoint[idx].lastFlag)
			{
				break;
			}
		}
	}
	if (0 < gStcTimerPara.tmrPointTotalNum)
	{
		gStcTimerPara.ctwSetFinished = 1;
	}
}

int32_t setCnt = 0;
void stc_timer_set_next_ctw(int32_t setFlag)
{
	setCnt++;
	int32_t apeId = get_core_id();
	if (1 == setFlag) // set in the slot int function
	{
		uint32_t addr = 0;
		if (apeId & 0x4)
		{
			addr = (uint32_t)(&LTBG1_TIME_BASE);
		}
		else
		{
			addr = (uint32_t)(&LTBG0_TIME_BASE);
		}
		gStcTimerPara.ctwVal = do_read_volatile(addr);
	}
	gStcTimerPara.curSlotTmrPointId++;
	int32_t slotNum = gStcTimerPara.curSlotNum;
	if (gStcTimerPara.curSlotTmrPointId >= gStcTimerPara.tmrPointNum[slotNum]) //gStcTimerPara.slotPointNum)
	{
		UCP_PRINT_ERROR("gStcTimerPara.curSlotTmrPointId: 0x%x error. \r\n", gStcTimerPara.curSlotTmrPointId);
	}
	int32_t idx = slotNum * gStcTimerPara.slotPointNum + gStcTimerPara.curSlotTmrPointId;
#if 0 //def PALLADIUM_TEST
	debug_write((DBG_DDR_IDX_DRV_BASE+384+(apeId<<6)+(setCnt&0x3F)), idx); // 0x600
	debug_write((DBG_DDR_IDX_DRV_BASE+256+(apeId<<6)+(setCnt&0x3F)), gStcTimerPara.tmrPoint[idx].lastFlag); // 0x400
#endif
	gStcTimerPara.ctwVal += gStcTimerPara.tmrPoint[idx].pointVal;
	if (gStcTimerPara.ctwVal >= STC_RT)
	{
		gStcTimerPara.ctwVal -= STC_RT;
	}
	
	do_write(((uint32_t*)(&CTW_REG_TIMER_0_0) + apeId), gStcTimerPara.ctwVal); // set ctw reg, clear ctw int
#if 0 //def PALLADIUM_TEST
	debug_write((DBG_DDR_IDX_DRV_BASE+1024 + (gStcTimerPara.ctwIntCnt&0x1FF) + (apeId << 9)), gStcTimerPara.ctwVal);		// 0x1000
//	debug_write((DBG_DDR_IDX_DRV_BASE+6144 + (setCnt&0x1FF) + (apeId << 9)), gStcTimerPara.ctwVal);		// 0x6000
#endif
}

void stc_timer_todint_init(void)
{
	int32_t apeId = get_core_id();

#ifndef GPS_PP1S_SYNC
	TOD_REG_IRQ_EN |= 0x1;		// set tod int enable
#endif

	uint32_t intNum = APC_STC_INTR8;
	// attach interrupt func
	int32_t ret = smart_irq_request(intNum, isr_stc_tod_int);
	if (0 != ret)
	{
		UCP_PRINT_ERROR("attach int num: 0x%x error. errno = 0x%x. \r\n", intNum, ret);
		debug_write(DBG_DDR_ERR_IDX(apeId, 8), ret);
	}
}

ddr_spinlock_t gSpinLockCtwInit;
void stc_timer_ctwint_init()
{
    int32_t apeId = get_core_id();
	
	gSpinLockCtwInit.lock_addr = 0xB7FD1400;
	gSpinLockCtwInit.flag_addr = 0xB7FD1404;
	//gSpinLockCtwInit.spin_lock_addr = 0xB7FD1408;
	//gSpinLockCtwInit.lock_w_addr = 0xB7FD140C;
	//gSpinLockCtwInit.lock_loop_addr = 0xB7FD1410;
	//gSpinLockCtwInit.unlock_loop_addr = 0xB7FD1410;
	//gSpinLockCtwInit.unlock_addr = 0xB7FD1418;
    smart_ddr_spin_lock_init(&gSpinLockCtwInit);

    uint32_t intNum = APC_STC_INTR0 + apeId;
    // attach interrupt func
    smart_ddr_spinlock(&gSpinLockCtwInit);
    int32_t ret = smart_irq_request(intNum, isr_stc_timer_int);
	smart_ddr_spinunlock(&gSpinLockCtwInit);
    if (0 != ret)
    {
        UCP_PRINT_EMPTY("attach int num: 0x%x error. errno = 0x%x. \r\n", intNum, ret);
        debug_write(DBG_DDR_ERR_IDX(apeId, 9), ret);
    }
}

void stc_timer_ctwint_enable()
{
	int32_t apeId = get_core_id();

	do_write(((uint32_t*)(&CTW_REG_IRQ_0_0) + apeId), 0x1); // set ctw irq enable
}

void stc_timer_ctwint_disable()
{
	int32_t apeId = get_core_id();

	do_write(((uint32_t*)(&CTW_REG_IRQ_0_0) + apeId), 0x0); // set ctw irq disable
}

//uint32_t stcCnt = 0;
//UINT32 gApe0CtwIntCnt = 0;
void isr_stc_timer_int()
{
	int32_t apeId = get_core_id();
#if 0 //def PALLADIUM_TEST
	gApe0CtwIntCnt++;
	debug_write((DBG_DDR_IDX_DRV_BASE+63+apeId), gApe0CtwIntCnt); // 0xfc
#endif	
	stCoreInt* apeCoreIntInfo = (stCoreInt*)APE_INT_INFO_ADDR + APE_INT_MAXNUM*apeId;

	int32_t status = do_read_volatile(&CTW_REG_STATUS);
	__ucps2_synch(0);
	if (status & (1 << apeId))
	{
#if 0 //def PALLADIUM_TEST
		uint32_t addr = 0;
		if (apeId & 0x4)
		{
			addr = (uint32_t)(&LTBG1_TIME_BASE);
		}
		else
		{
			addr = (uint32_t)(&LTBG0_TIME_BASE);
		}
		debug_write(((DBG_DDR_IDX_DRV_BASE+2048) + (gStcTimerPara.ctwIntCnt&0x1FF) + (apeId<<9)), do_read_volatile(addr));	// 0x2000
#endif
		gStcTimerPara.ctwIntCnt++;
		int32_t idx = gStcTimerPara.curSlotNum * gStcTimerPara.slotPointNum + gStcTimerPara.curSlotTmrPointId;
		if (1 != gStcTimerPara.tmrPoint[idx].lastFlag)
		{
#ifdef PALLADIUM_TEST
//			debug_write((DBG_DDR_IDX_DRV_BASE+192+(apeId<<6)+gStcTimerPara.curSlotNum), idx);			// 0x300
#endif
			stc_timer_set_next_ctw(0);
		}
		else
		{
#ifdef PALLADIUM_TEST
//			debug_write((DBG_DDR_IDX_DRV_BASE+224+(apeId<<6)+gStcTimerPara.curSlotNum), idx);			// 0x380
#endif
			stc_timer_ctwint_disable();
		}
//        debug_write(((DBG_DDR_IDX_DRV_BASE+10240) + ((gStcTimerPara.ctwIntCnt)&0x1FF) + (apeId<<9)), get_tx_nr_slot(1));         		// 0xa000
//        debug_write(((DBG_DDR_IDX_DRV_BASE+11264) + (gStcTimerPara.ctwIntCnt&0x1FF) + (apeId<<9)), do_read_volatile(&LTBG_TIME_BASE));  // 0xb000
		//osp_timer_call_task();	// start task
		osp_timer_call_task_spe(gStcTimerPara.curSlotNum, gStcTimerPara.curSlotTmrPointId);
        //debug_write(((DBG_DDR_IDX_DRV_BASE+12288) + (gStcTimerPara.ctwIntCnt&0x1FF) + (apeId<<9)), do_read_volatile(&LTBG_TIME_BASE));  // 0xc000
		
#ifdef PALLADIUM_TEST
//		if (1 < gStcTimerPara.ctwIntCnt)
		{
//			uint32_t period = GET_STC_CNT() - stcCnt;// GET_CNT_VAL(apeId)-stcCnt;// 
//			debug_write(((DBG_DDR_IDX_DRV_BASE+3072)+(gStcTimerPara.ctwIntCnt&0x1FF) + (apeId<<9)), period);				// 0x3000
		}
//		stcCnt = GET_STC_CNT();// GET_CNT_VAL(apeId); // 
		debug_write((DBG_DDR_IDX_DRV_BASE+101+(apeId<<1)), gStcTimerPara.ctwIntCnt);	// 0x194
		// write sm
		do_write(&(apeCoreIntInfo[APE_INT_STC].intNum), APE_INT_STC);
		do_write(&(apeCoreIntInfo[APE_INT_STC].intCnt), gStcTimerPara.ctwIntCnt);
		
		//debug_write(((DBG_DDR_IDX_DRV_BASE+6144) + (gStcTimerPara.ctwIntCnt&0x1FF) + (apeId<<9)), do_read_volatile(addr));	// 0x6000
#endif
		status = do_read_volatile(&CTW_REG_STATUS);
	}
}

//extern UINT8 waitTodInt;
//uint32_t gApe0TodIntCnt = 0;
void isr_stc_tod_int()
{
	//int32_t apeId = get_core_id();
#ifdef PALLADIUM_TEST
	//gApe0TodIntCnt++;
	//debug_write((DBG_DDR_IDX_DRV_BASE+62), gApe0TodIntCnt);	// 0xf8
#endif	

	int32_t status = do_read_volatile(&TOD_REG_INT_STATUS);
	__ucps2_synch(0);
	if (status & 0x1)
	{
		do_write((&TOD_REG_INT_STATUS), 0x1);
#if 0 //def PALLADIUM_TEST
		uint32_t addr = 0;
		if (apeId & 0x4)
		{
			addr = (uint32_t)(&LTBG1_TIME_BASE);
		}
		else
		{
			addr = (uint32_t)(&LTBG0_TIME_BASE);
		}
		debug_write(((DBG_DDR_IDX_DRV_BASE+4096) + (gStcTimerPara.todIntCnt&0x3FF)), do_read_volatile(addr)); // 0x4000
#endif

#ifndef ENABLE_SFNCAL
		if (0 == gStcTimerPara.todIntCnt)
#else
		if (1 == do_read_volatile(ARM_LOCK_FLAG_ADDR))
#endif
		{
			do_write((uint32_t*)(&TOD_REG_RT_LO), 0);
			do_write((uint32_t*)(&TOD_REG_RT_HI), STC_RT);
 			do_write(STC_RT_ADDR, STC_RT);
		}

#if 0 //def PALLADIUM_TEST
		if (0 < gStcTimerPara.todIntCnt)
		{
			uint64_t temp = GET_CNT_VAL(apeId) + 0xFFFFFFFF;
			uint32_t period = temp - gStcTimerPara.todLastStcCnt;
			debug_write(((DBG_DDR_IDX_DRV_BASE+128)+((gStcTimerPara.todIntCnt-1)&0x3F)), period);	// 0x200
		}
		gStcTimerPara.todLastStcCnt = GET_CNT_VAL(apeId);
#endif
		gStcTimerPara.todIntCnt++;
#ifdef PALLADIUM_TEST
		debug_write((DBG_DDR_IDX_DRV_BASE+64), gStcTimerPara.todIntCnt); // 0x100
#endif
		status = do_read_volatile(&TOD_REG_INT_STATUS);
	}
}



