#include "ucp_cpri.h"
#include "hw_cpri.h"
#include "cpri_driver.h"
#include "cpri_timer.h"
#include "cpri_delay.h"
#include "phy_para.h"
#include "ucp_utility.h"
#include "ucp_printf.h"
#include "inter_vector.h"
#include "ucp_js_ctrl.h"
#include "ecs_rfm_dm_mgt.h"
#include "cpri_csu.h"
#include "cpri_csu_api.h"
#include "cpri_csu_nr_7ds2u.h"
#include "ecpri_driver.h"
#include "phy_para.h"

//stCpriPara cpriPara;
//extern stCpriTimerPara 			gCpriTimerPara;
volatile stCpriIntStat					gCpriIntStatus;
extern uint32_t reCfgFlag;
extern volatile uint32_t gVendorFlag;

void cpri_init(uint32_t option, uint32_t MappingMode)
{
#ifdef PALLADIUM_TEST
    int32_t apeId = get_core_id();
    int32_t flag = 1;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);	// 0xB8
#endif
	phy_para_init(PROTOCOL_CPRI, option);

    do_write(&JECS_CRG_PLLSEL,  0xC21);
    ucp_nop(400);
#if 0
    // temp, to be change
    /**********************************************************************/
    //JECS_CTRL_QOS_M3_SRIO_AXIM |= BIT19;

	//                             gnss_sel     stc_sel     cpri_sel
	//JECS_CTRL_CPRI_GMAC_PHY_INT = (0x0 << 4) | (0x5 << 7) | (0x6<<10);
	//do_write(RF_LVDS_PMUX1_REG_ADDR, (do_read_volatile(RF_LVDS_PMUX1_REG_ADDR)|0x000C0000));	// pinmux, GPIO1B25, gpio func, 0x3
	//do_write(GPIO1B_DIR_REG_ADDR, (do_read_volatile(GPIO1B_DIR_REG_ADDR)|BIT25));				// GPIO1B25, output, 10ms trigger for phy
	do_write(PB14_CTRL_REG_ADDR, (do_read_volatile(PB14_CTRL_REG_ADDR)|(1<<7)|(1<<6)));
	do_write(GPIO0_A29_PINMUX_REG_ADDR, (do_read_volatile(GPIO0_A29_PINMUX_REG_ADDR)|0x20000000));	// pinmux, GPIO0A29, gnss pps int func, 0x2
	//do_write(RF_LVDS_PMUX1_REG_ADDR, (do_read_volatile(RF_LVDS_PMUX1_REG_ADDR)|0x30000000));	// pinmux, GPIO1B30, gpio func, 0x3
	do_write(RF_LVDS_PMUX1_REG_ADDR, (do_read_volatile(RF_LVDS_PMUX1_REG_ADDR)|0x30000000));	// pinmux, GPIO1B30, gpio func, 0x3
//	do_write(&JECS_CTRL_QOS_M3_SRIO_AXIM, do_read_volatile(&JECS_CTRL_QOS_M3_SRIO_AXIM) | BIT19); 
	do_write(&JECS_CTRL_CPRI_GMAC_PHY_INT, (0x0 << 4) | (0x5 << 7) | (0x5<<10));
	
    /**********************************************************************/
#endif

    cpri_para_init(option);
    cpri_delay_init();
    cpri_link_status_init();

    UCP_PRINT_EMPTY("cpri para init finished.\r\n");
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

    init_cpri(option);
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif
    cpri_int_init();

    UCP_PRINT_EMPTY("cpri ip init finished.\r\n");
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

	//if (LTE_MODE == NetType)
	{
        //cpri_mtimer_init(LTE_SCS_ID, 10); // slot:1000us, one tdd has 10 slots
	}
	//if (NR_MODE == NetType)
	{
        cpri_mtimer_init(NR_SCS_30K, 10); // slot:500us, one tdd has 10 slots
	}

    UCP_PRINT_EMPTY("cpri_timer init.\r\n");
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

#if 0
    while (1 >= gCpriIntStatus.syncIntCnt)
    {
		//debug_write((DBG_DDR_IDX_DRV_BASE+126), gCpriIntStatus.syncIntCnt);
    }
    //smart_irq_disable(APC_CPRI_SUB_INTR0);
    UCP_PRINT_EMPTY("AUX CNT0: 0x%x \r\n", AUX_CNT0);
    UCP_PRINT_EMPTY("AUX CNT1: 0x%x \r\n", AUX_CNT1);
    UCP_PRINT_EMPTY("AUX CNT2: 0x%x \r\n", AUX_CNT2);
    UCP_PRINT_EMPTY("SELF SYNC finish.\r\n");
#endif

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

    config_cpri_map_directed(option,MappingMode);

    UCP_PRINT_EMPTY("CPRI map config finished.\r\n");
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

	HeaderTxRam_init(MappingMode);
#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag); // 0xB4
#endif

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

#if 0
#ifdef CPRI_TIMING_TEST
    cpri_csu_init();

    UCP_PRINT_EMPTY("CPRI csu init finished.\r\n");
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif
#endif

#ifdef CPRI_NOTIMING_TEST
    cpri_csu_axcctrl_init_notiming();
    UCP_PRINT_EMPTY("Csu axcctrl init: notiming.\r\n");

    cpri_csu_axc_init_notiming();
    UCP_PRINT_EMPTY("csu axc init: notiming.\r\n");
#endif


#ifdef CPRI_TIMING_TEST
    cpri_csu_axcctrl_init_timing();

    UCP_PRINT_EMPTY("Csu axcctrl init: timing.\r\n");
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif

    cpri_csu_axc_init_timing();

    UCP_PRINT_EMPTY("csu axc init: timing.\r\n");
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif
#endif

#ifdef CPRI_TIMING_7D2U_TEST
    cpri_csu_axc_init_nr_7ds2u(CPRI_DUMMY_USE_DDR_ADDR, &txCmdFifo, &rxCmdFifo);
#ifdef TEST_ENABLE
#ifdef DISTRIBUTED_BS
    cpri_csu_axcctrl_init_timing();
#endif
#endif
#ifdef PALLADIUM_TEST
    flag++;
    debug_write((DBG_DDR_IDX_DRV_BASE+2+(apeId<<2)), flag);
#endif
#endif

#endif
}

void cpri_ecprimode_init()
{
	cpri_timer_ecprimode_clk_init();
	cpri_mtimer_init(NR_SCS_30K, 10); // slot:500us, one tdd has 10 slots
}

void cpri_para_init(uint32_t option)
{
    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt = get_ecs_rfm_dm_local_mgt();
	stCpriPara* pCpriPara = NULL; // pEcsDmLocalMgt->pCpriPara;
//#ifdef DISTRIBUTED_BS
	pCpriPara = pEcsDmLocalMgt->pCpriPara;
//#endif
	if (NULL == pCpriPara)
	{
		return;
	}
	stFhAlarmStat* pAlarmStatus = pEcsDmLocalMgt->pAlarmStatus;

	memset(pCpriPara, 0, sizeof(stCpriPara));
	memset((void*)(&gCpriIntStatus), 0, sizeof(stCpriIntStat));
	pAlarmStatus->alarmFlag = FH_NO_ALARM;
	switch (option)
	{
	case (7):
	{
		pCpriPara->option_num = option;
		pCpriPara->core_clk = 245760000;
		pCpriPara->pcs_core_clk = 245760000;
		pCpriPara->cpu_clk = 200000000;
		pCpriPara->gmii_tx_rx_clk = 125000000;
		pCpriPara->pcs_fine_delay_clk = 250000000;
		pCpriPara->pcs_serdes_clk = 491520000;
		pCpriPara->serdes_data_width = 20; // bit
		pCpriPara->cpri_rate_coff = 16;
		pCpriPara->line_rate = 9830400000;
		pCpriPara->valid_line_rate = pCpriPara->cpri_rate_coff * 491500000;
		pCpriPara->encode_flag = 0; 			// 0:8B/10B; 1:64B/66B
		pCpriPara->rs_fec_flag = 0;
		pCpriPara->len_word = 128;
		pCpriPara->len_ctrl_word = 128;
		pCpriPara->aux_cnt_pos_max = 64;
		break;
	}
	case (8):
	{
		pCpriPara->option_num = option;
		pCpriPara->core_clk = 307200000;
		pCpriPara->pcs_core_clk = 153600000;
		pCpriPara->cpu_clk = 200000000;
		pCpriPara->gmii_tx_rx_clk = 125000000;
		pCpriPara->pcs_fine_delay_clk = 250000000;
		pCpriPara->pcs_serdes_clk = 316800000;
		pCpriPara->serdes_data_width = 32; // bit
		pCpriPara->cpri_rate_coff = 20;
		pCpriPara->line_rate = 10137600000;
		pCpriPara->valid_line_rate = pCpriPara->cpri_rate_coff * 491500000;
		pCpriPara->encode_flag = 1; 			// 0:8B/10B; 1:64B/66B
		pCpriPara->rs_fec_flag = 0; // 1;
		pCpriPara->len_word = 160;
		pCpriPara->len_ctrl_word = 128;
		pCpriPara->aux_cnt_pos_max = 80;
		break;
	}
	case (9):
	{
		pCpriPara->option_num = option;
		pCpriPara->core_clk = 368640000;
		pCpriPara->pcs_core_clk = 184320000;
		pCpriPara->cpu_clk = 200000000;
		pCpriPara->gmii_tx_rx_clk = 125000000;
		pCpriPara->pcs_fine_delay_clk = 250000000;
		pCpriPara->pcs_serdes_clk = 380160000;
		pCpriPara->serdes_data_width = 32; // bit
		pCpriPara->cpri_rate_coff = 24;
		pCpriPara->line_rate = 12165120000;
		pCpriPara->valid_line_rate = pCpriPara->cpri_rate_coff * 491500000;
		pCpriPara->encode_flag = 1; 			// 0:8B/10B; 1:64B/66B
		pCpriPara->rs_fec_flag = 0; //1;
		pCpriPara->len_word = 192;
		pCpriPara->len_ctrl_word = 128;
		pCpriPara->aux_cnt_pos_max = 96;
		break;
	}
	case (10):
	{
		pCpriPara->option_num = option;
		pCpriPara->core_clk = 737280000;
		pCpriPara->pcs_core_clk = 368640000;
		pCpriPara->cpu_clk = 200000000;
		pCpriPara->gmii_tx_rx_clk = 125000000;
		pCpriPara->pcs_fine_delay_clk = 250000000;
		pCpriPara->pcs_serdes_clk = 760320000;
		pCpriPara->serdes_data_width = 32; // bit
		pCpriPara->cpri_rate_coff = 48;
		pCpriPara->line_rate = 24330240000;
		pCpriPara->valid_line_rate = pCpriPara->cpri_rate_coff * 491500000;
		pCpriPara->encode_flag = 1; 			// 0:8B/10B; 1:64B/66B
		pCpriPara->rs_fec_flag = 0; //1;
		pCpriPara->len_word = 384;
		pCpriPara->len_ctrl_word = 128;
		pCpriPara->aux_cnt_pos_max = 192;
		break;
	}
	default:
	{
		break;
	}
	}
	
	debug_write((DBG_DDR_IDX_DRV_BASE+41), pCpriPara->core_clk); 		// 0xb7e060A4
}

void cpri_int_init(void)
{
    int32_t apeId = get_core_id(); // Get_ApcId(); //

    AUX_INT_EN = 0x01FF0007;       // sync int, gmac int
    AUX_RFP_INT_EN = 0x3;   // rfp_tx_en, rfp_rx_en
#if 0
    AUX_INT_EN = 0xFF003F;  // 16~24bit, gamc int
    ALARM_INTEN = 0xFFFFFFFF; // axc iq_buffer full
#endif

    uint32_t intNum = APC_CPRI_SUB_INTR0;
    // attach interrupt func
    int32_t ret = smart_irq_request(intNum, isr_cpri_int);
    if (0 != ret)// only ape0
    {
        UCP_PRINT_EMPTY("attach int num: 0x%x error. errno = 0x%x. \r\n", intNum, ret);
        debug_write(DBG_DDR_ERR_IDX(apeId, 4), ret);
    }

#if 0
    intNum = APC_CPRI_SUB_INTR1;
#ifndef NO_OSP_TEST
    // attach interrupt func
    ret = smart_irq_request(intNum, isr_gmac_int);
    if (0 != ret) // only ape0
    {
        UCP_PRINT_EMPTY("attach int num: 0x%x error. errno = 0x%x. \r\n", intNum, ret);
    }
#else
    // int enable
    EN_APCIRQ(intNum, 0);
#endif
#endif
}

void isr_cpri_int(void)
{
	uint32_t auxFlag = AUX_INT_FLAG & 0x7;
	uint32_t rfpFlag = AUX_RFP_INT_FLAG;
	//uint32_t auxFlag = AUX_INT_FLAG & 0x3F;
	uint32_t alarmFlag = ALARM_FLAG;

	AUX_INT_FLAG = auxFlag;
	AUX_RFP_INT_FLAG = rfpFlag;
//	ALARM_FLAG = alarmFlag;

	if (rfpFlag & 0x1) // rx_rfp
	{
		gCpriIntStatus.rxRfpIntCnt++;
		debug_write((DBG_DDR_IDX_DRV_BASE+120), gCpriIntStatus.rxRfpIntCnt);
		//gScrRxRfpValL = CPRI_TMR_RX_SCRL_REG;
		//gScrRxRfpValH = CPRI_TMR_RX_SCRH_REG;
	}
	if (rfpFlag & 0x2)
	{
		gCpriIntStatus.txRfpIntCnt++;
		debug_write((DBG_DDR_IDX_DRV_BASE+121), gCpriIntStatus.txRfpIntCnt);
	}

	if (alarmFlag)
	{
		gCpriIntStatus.alarmIntCnt++; // iq buffer full
		debug_write((DBG_DDR_IDX_DRV_BASE+116), gCpriIntStatus.alarmIntCnt); // 0x1d0
		if (4 > gCpriIntStatus.alarmIntCnt)
		{
			debug_write((DBG_DDR_IDX_DRV_BASE+116+gCpriIntStatus.alarmIntCnt), alarmFlag);// 0x1d0
		}
		//debug_write((DBG_DDR_IDX_CPRI_BASE+403+((2*gCpriAlarmIntCnt)&0xFF)), gCpriTimerPara.tddOffsetIntCnt);
		do_write(&ALARM_FLAG, alarmFlag);
	}
	
#if 0
//	4	buffer1_full	RWC 1’b0	ddr buffer1写满标志
//	3	buffer0_full	RWC 1’b0	ddr buffer0写满标志
//	2	hfnsync_flag	RWC 1’b0	aux_hfnsync标志
//	1	lof_flag		RWC 1’b0	aux_lof标志
//	0	l1_reset_flag	RWC 1’b0	aux_l1_reset标志
	if (auxFlag & 0x18)
	{
		gCpriIntStatus.ddrFifoIntCnt++;
	}
	if (auxFlag & 0x20)
	{
		gCpriIntStatus.rxFifoIntCnt++;
	}
#endif

	if (auxFlag & 0x1)
	{
		gCpriIntStatus.l1ResetIntCnt++;
		debug_write((DBG_DDR_IDX_DRV_BASE+123), gCpriIntStatus.l1ResetIntCnt);
	}
	if (auxFlag & 0x2)
	{
		gCpriIntStatus.lofIntCnt++;
		gCpriIntStatus.cpriSyncFlag = 0;
		do_write(CSU_STOP_CMD_ADDR, 1);
		debug_write((DBG_DDR_IDX_DRV_BASE+124), gCpriIntStatus.lofIntCnt);
	}
	if (auxFlag & 0x4)
	{
		gCpriIntStatus.syncIntCnt++;
		if (1 < gCpriIntStatus.syncIntCnt)
		{
			gCpriIntStatus.cpriSyncFlag = 1;
			if (1 == reCfgFlag)
			{
				reCfgFlag = 2;
				debug_write((DBG_DDR_IDX_DRV_BASE+16), 2);
			}
			debug_write((DBG_DDR_IDX_DRV_BASE+125), gCpriIntStatus.syncIntCnt);
			debug_write((DBG_DDR_IDX_DRV_BASE+126), GET_STC_CNT());
		}
	}
}

void isr_gmac_int(void)
{
	uint32_t gmacFlag = AUX_INT_FLAG & 0xFF0000;

	if (gmacFlag)
	{
		gCpriIntStatus.gmacIntCnt++;
	}
}



