#include "mtimer_cell.h"
#include "phy_para.h"
#include "ucp_utility.h"
//#ifdef DISTRIBUTED_BS
#include "cpri_timer.h"
#include "ecpri_timer.h"
//#endif
//#ifdef INTEGRATED_BS
#include "jesd_timer.h"
//#endif

stPhyCellPara* pPhyCellPara = (stPhyCellPara*)PHY_CELL_ADDR;
extern uint32_t				gScsId;
extern uint32_t				gMtimerId;
//extern stSfnPara			gCellSfnPara[2]; // cell para
extern stPhyScsPara*		phyPara;
extern uint32_t				reCfgFlag;

extern int32_t check_phy_cell(void);

int32_t mtimer_init4phy(phy_timer_config_ind_t *mtmr)
{
	uint8_t nBsType = get_protocol_sel(); 
	//phy_cell_para_init(mtmr->scsId);
	
	memcpy_ucp((void*)(&pPhyCellPara->phyPara), (void*)mtmr, sizeof(phy_timer_config_ind_t));
	__ucps2_synch(f_SM);
	gScsId = mtmr->scsId;
    if (PROTOCOL_JESD == nBsType)
	{
		gMtimerId = MTIMER_JESD_RX0_ID;
	}
	else
	{
		gMtimerId = MTIMER_CPRI_ID;
	}
	do_write((&(pPhyCellPara->flag)), PHY_CELL_FLAG);
	__ucps2_synch(f_SM);

	return check_phy_cell();
}

// cell building, first build cell on ecs rfm1, and then inform ape cores
int32_t mtimer_reconfig(phy_timer_config_ind_t *my_mtmr)
{
	int32_t nScsId = my_mtmr->scsId;
	short timerId = 0; // do_read_volatile_short(&(phyPara[nScsId].mtimerId));
	uint8_t nBsType = get_protocol_sel(); 
	short runCore = do_read_volatile_short(&(phyPara[nScsId].runCoreId));
	__ucps2_synch(f_SMR);
	
#ifdef PALLADIUM_TEST
	int32_t flag = 1;
	debug_write((DBG_DDR_IDX_DRV_BASE+32), flag); 		// 0xb7e06080
#endif
	int32_t i = 0;
	int32_t j = 0;
	for (i = 0; i < PHY_SCS_MAX_NUM; i++)
	{
		if (SCS_1st_MTIMER_ID == do_read_volatile_short(&(phyPara[i].mtimerId))) // already building the first scs id cell 
		{
			break;
		}
	}
	
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+32), flag); 		// 0xb7e06080
	debug_write((DBG_DDR_IDX_DRV_BASE+33), i);		    // 0xb7e06084

	// no cell built on any scs id
	if (PHY_SCS_MAX_NUM == i)		// no cell on cpri timer, build cell on cpri timer
	{
		do_write_short((&(phyPara[nScsId].mtimerId)), SCS_1st_MTIMER_ID);
		if (PROTOCOL_JESD == nBsType)
		{
			jesd_timer_reconfig(MTIMER_JESD_RX0_ID, my_mtmr);
			if (-1 == set_jesd_ape_slot_offset(MTIMER_JESD_RX0_ID, my_mtmr->runCoreId))
			{
				debug_write((DBG_DDR_IDX_DRV_BASE+37), -2); 		// 0xb7e06094
				return -2; // coreId error, ape slot int set error
			}
		}
		else
		{
			cpri_timer_reconfig(my_mtmr);
			if (-1 == set_cpri_ape_slot_offset(my_mtmr->runCoreId))
			{
				debug_write((DBG_DDR_IDX_DRV_BASE+37), -2); 		// 0xb7e06094
				return -2; // coreId error, ape slot int set error
			}
		}
		timerId = SCS_1st_MTIMER_ID;
		
		flag++;
		debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);					// 0xb7e06080
		debug_write((DBG_DDR_IDX_DRV_BASE+34), my_mtmr->runCoreId); 	// 0xb7e06088
	}
	else // have cell built
	{
		flag++;
		debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);					// 0xb7e06080
		if (my_mtmr->scsId == do_read_volatile_short(&(phyPara[i].scsId))) // continue building cell on the first scs id
		{
			flag++;
			debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);				// 0xb7e06080
			debug_write((DBG_DDR_IDX_DRV_BASE+35), my_mtmr->runCoreId);	// 0xb7e0608c
			if (0 != (my_mtmr->runCoreId & runCore))
			{
				debug_write((DBG_DDR_IDX_DRV_BASE+36), runCore);		// 0xb7e06090
				return -1; // this cell has been built
			}
			else
			{
				flag++;
				debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);			// 0xb7e06080
				while (0 != reCfgFlag)	// wait last cell built finished
				{
					debug_write((DBG_DDR_IDX_DRV_BASE+36), reCfgFlag);		// 0xb7e06090
				}
				if (PROTOCOL_JESD == nBsType)
				{
					if (-1 == set_jesd_ape_slot_offset(MTIMER_JESD_RX0_ID, my_mtmr->runCoreId))
					{
						flag++;
						debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);		// 0xb7e06080
						debug_write((DBG_DDR_IDX_DRV_BASE+37), -2); 		// 0xb7e06094
						return -2; // the input coreId is not correct
					}
				}
				else
				{
					if (-1 == set_cpri_ape_slot_offset(my_mtmr->runCoreId))
					{
						flag++;
						debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);		// 0xb7e06080
						debug_write((DBG_DDR_IDX_DRV_BASE+37), -2);			// 0xb7e06094
						return -2; // the input coreId is not correct
					}
				}
			}
		}
		else // the second scs id
		{
			flag++;
			debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);				// 0xb7e06080
			for (j = 0; j < PHY_SCS_MAX_NUM; j++)
			{
				if (SCS_2nd_MTIMER_ID == do_read_volatile_short(&(phyPara[j].mtimerId))) // already building the second scs id cell
				{
					break;
				}
			}
			
			flag++;
			debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);		// 0xb7e06080
			debug_write((DBG_DDR_IDX_DRV_BASE+38), j);			// 0xb7e06098
			if (PHY_SCS_MAX_NUM == j)	// no cell on ecpri timer, build cell on ecpri timer
			{
				do_write_short((&(phyPara[nScsId].mtimerId)), SCS_2nd_MTIMER_ID);
				while (0 != reCfgFlag)	// wait last cell built finished
				{
					debug_write((DBG_DDR_IDX_DRV_BASE+36), reCfgFlag);		// 0xb7e06090
				}
				if (PROTOCOL_JESD == nBsType)
				{
					jesd_timer_reconfig(MTIMER_JESD_RX1_ID, my_mtmr);
					if (-1 == set_jesd_ape_slot_offset(MTIMER_JESD_RX1_ID, my_mtmr->runCoreId))
					{
						debug_write((DBG_DDR_IDX_DRV_BASE+37), -2);			// 0xb7e06094
						return -2; // coreId error, ape slot int set error
					}
				}
				else
				{
					ecpri_timer_reconfig(my_mtmr);
					if (-1 == set_ecpri_ape_slot_offset(my_mtmr->runCoreId))
					{
						debug_write((DBG_DDR_IDX_DRV_BASE+41), my_mtmr->runCoreId); 		// 0xb7e060A4
						debug_write((DBG_DDR_IDX_DRV_BASE+37), -2);			// 0xb7e06094
						return -2; // coreId error, ape slot int set error
					}
				}
				timerId = SCS_2nd_MTIMER_ID;
				flag++;
				debug_write((DBG_DDR_IDX_DRV_BASE+32), flag);		// 0xb7e06080
				debug_write((DBG_DDR_IDX_DRV_BASE+39), my_mtmr->runCoreId); 		// 0xb7e0609C
			}
			else
			{
				if (my_mtmr->scsId == do_read_volatile_short(&(phyPara[j].scsId))) // continue building cell on the first scs id
				{
					if (0 != (my_mtmr->runCoreId & runCore))
					{
						return -1; // this cell has been built
					}
					else
					{
						while (0 != reCfgFlag)	// wait last cell built finished
						{
							debug_write((DBG_DDR_IDX_DRV_BASE+36), reCfgFlag);		// 0xb7e06090
						}
						if (PROTOCOL_JESD == nBsType)
						{
							if (-1 == set_jesd_ape_slot_offset(MTIMER_JESD_RX1_ID, my_mtmr->runCoreId))
							{
								return -2; // the input coreId is not correct
							}
						}
						else
						{
							if (-1 == set_ecpri_ape_slot_offset(my_mtmr->runCoreId))
							{
								return -2; // the input coreId is not correct
							}
						}
					}
				}
			}
		}
	}

	return timerId;
}

// 删小区，先通知APE删除任务和定时点，再走ecs rfm1的删小区流程
int32_t mtimer_del_cell_cfg(stPhyDelCell* delCell)
{
	uint8_t nBsType = get_protocol_sel(); 
#ifdef PALLADIUM_TEST
	int32_t flag = 1;
	debug_write((DBG_DDR_IDX_DRV_BASE+53), flag);		// 0xb7e060d4
#endif
	if (NULL == delCell)
	{
		return -1;	// input para error
	}

	if ((PHY_SCS_MAX_NUM <= delCell->scsId) || (0 != (delCell->delCoreId & 0xFFFFFF00)))
	{
		return -1;	// input para error
	}

#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+53), flag);		// 0xb7e060d4
#endif
	int32_t nScsId = delCell->scsId;
	short timerId = do_read_volatile_short(&(phyPara[nScsId].mtimerId));
	short runCore = do_read_volatile_short(&(phyPara[nScsId].runCoreId));
	__ucps2_synch(f_SMR);

	while (0 != (runCore & delCell->delCoreId))
	{
		runCore = do_read_volatile_short(&(phyPara[nScsId].runCoreId));
	}
#ifdef PALLADIUM_TEST
	flag++;
	debug_write((DBG_DDR_IDX_DRV_BASE+53), flag);		// 0xb7e060d4
#endif

	if (SCS_1st_MTIMER_ID == timerId)
	{
#ifdef PALLADIUM_TEST
		flag++;
		debug_write((DBG_DDR_IDX_DRV_BASE+53), flag);		// 0xb7e060d4
#endif
        if (PROTOCOL_JESD == nBsType)
    	{
			clear_jesd_ape_slot_offset(MTIMER_JESD_RX0_ID, delCell->delCoreId);
    	}
		else
		{
			clear_cpri_ape_slot_offset(delCell->delCoreId);
		}
		if (0 == runCore)	// delete all the interrupts on this mtimer other than pp1s and 10ms offset int
		{
#ifdef PALLADIUM_TEST
			flag++;
			debug_write((DBG_DDR_IDX_DRV_BASE+53), flag);		// 0xb7e060d4
			debug_write((DBG_DDR_IDX_DRV_BASE+54), delCell->delCoreId);		// 0xb7e060d8
#endif
			if (PROTOCOL_JESD == nBsType)
			{
				jesd_timer_clear_cell(MTIMER_JESD_RX0_ID, delCell->scsId);
			}
			else
			{
				cpri_timer_clear_cell(delCell->scsId);
			}
			do_write_short(&(phyPara[nScsId].mtimerId), MTIMER_NULL);
		}
	}
	else if (SCS_2nd_MTIMER_ID == timerId) // ecpri timer
	{
        if (PROTOCOL_JESD == nBsType)
    	{
			clear_jesd_ape_slot_offset(MTIMER_JESD_RX1_ID, delCell->delCoreId);
    	}
		else
		{
			clear_ecpri_ape_slot_offset(delCell->delCoreId);
		}
		if (0 == runCore)	// delete all the interrupts on this mtimer other than pp1s and 10ms offset int
		{
			if (PROTOCOL_JESD == nBsType)
			{
				jesd_timer_clear_cell(MTIMER_JESD_RX1_ID, delCell->scsId);
			}
			else
			{
				ecpri_timer_clear_cell(delCell->scsId);
			}
			do_write_short(&(phyPara[nScsId].mtimerId), MTIMER_NULL);
		}
	}
	else
	{
		return -2; // drv phy para error
	}
	
	return 0;
}

