/*****************************************************************************
 函 数 名  : bsp_sci_get_nv
 功能描述  : 获取SCI的NV项值
 输入参数  : 
 输出参数  : 无
 返 回 值  : int
 调用函数  :
 被调函数  :

 修改历史      :

*****************************************************************************/
int bsp_sci_get_nv(unsigned int *value)
{
    /*调用NV读接口*/
    if(BSP_OK == bsp_nvm_read(NV_ID_DRV_SCI_DSDA_SELECT, (u8*)&g_SciNVValue, NV_SCI_LEN)) 
    {
#if (FEATURE_ON==FEATURE_MULTI_MODEM)
        if(0x802 !=g_SciNVValue && 0x102 !=g_SciNVValue)
        {
            g_SciNVValue = 0x802;
        }
#endif
        /*读取成功*/
        *value = g_SciNVValue;
        
        sci_print_debug("nv value:0x%x\r\n",g_SciNVValue);
        return BSP_OK;
    }
    else 
	{
#if (FEATURE_ON==FEATURE_MULTI_MODEM)
        *value = 0x802;
#else 
        /*读取失败,默认是单卡0*/
        *value = 0x0;
#endif
        sci_print_error("default value is 0x%x\r\n", 0);
        return BSP_ERROR;
    }
    
}
int bsp_sci_cfg_init(void)
{
    unsigned int i = 0;
    unsigned int init_func_num;
    /* coverity[assign] */
    int *p_init_start = (int *)&_sci_init_data_start;
    int call_addr;
    NV_SCI_CFG_UNION nv_sci;
    SCI_INIT_FUNCP p_func_sci_init;
    int card_type = 0;
#if (FEATURE_ON == FEATURE_MULTI_MODEM)
    /*读取NV_SCI的值*/
    (void)bsp_sci_get_nv(&nv_sci.value);
#else
    nv_sci.value = g_SciNVValue;
#endif
    /*解析NV_SCI*/
    if (BSP_ERROR == bsp_sci_parse_nv(&nv_sci)) 
	{
		sci_print_error("parse nv failed!\n");
        return BSP_ERROR;
    }
    init_func_num = &_sci_init_data_end - &_sci_init_data_start;

    card_type = ((NV_SCI_CFG_UNION *)&g_SciNVValue)->cfg.card_num; 
    if(SCI_SINGLE == card_type)
    {
        init_func_num= 1;
    }
    else if (SCI_SINGLE_MODLEM1 == card_type)
    {
         init_func_num= 1;
         /* coverity[ptr_arith] */
         p_init_start++;
    }
    
    sci_print_debug("init_func_num %d  start_add_opp 0x%0x\r\n", init_func_num,(p_init_start-(int*)&_sci_init_data_start));
        
    /*调用SCI的初始化*/
    for (i = 0; i < init_func_num; i++) 
	{
        call_addr = *(volatile int *)p_init_start;
        p_func_sci_init = (SCI_INIT_FUNCP)call_addr;
        sci_print_debug("call init function of card%d, address is 0x%x\r\n",i, call_addr);
        p_func_sci_init();
        /* coverity[ptr_arith] */
        p_init_start++;
    }

    return BSP_OK;
}
int bsp_sci_parse_nv(NV_SCI_CFG_UNION * nv)
{
    NV_SCI_CFG_UNION *p_nv_sci = nv;

    if (SCI_SINGLE == p_nv_sci->cfg.card_num) 
	{
        /*单卡0场景*/
        if (p_nv_sci->cfg.card0 <= CARD_CONNECT_SCI1) 
        {
            sci_print_debug("card0 connect sci%d\r\n",p_nv_sci->cfg.card0);
            if(BSP_OK != bsp_sci_cfg(CARD0, p_nv_sci->cfg.card0))
            {
            	sci_print_error("cfg sci%d failed! \r\n",p_nv_sci->cfg.card0);
				return BSP_ERROR;
			}
        }
        else 
		{
            /*暂不支持多卡*/
			sci_print_error("do not support multi card! case 1\n");
            return ERROR;
        }
    }
    else if(SCI_SINGLE_MODLEM1 == p_nv_sci->cfg.card_num)
    { /*单卡1场景*/
        if (p_nv_sci->cfg.card1 <= CARD_CONNECT_SCI1) 
        {
            sci_print_debug("SCI_SINGLE_MODLEM1  connect sci%d\r\n",p_nv_sci->cfg.card1);
			if(BSP_OK != bsp_sci_cfg(CARD1, p_nv_sci->cfg.card1))
            {
            	sci_print_error("cfg sci%d failed! \r\n",p_nv_sci->cfg.card1);
				return BSP_ERROR;
			}
        }
        else 
		{
            /*暂不支持多卡*/
			sci_print_error("do not support multi card! case 2\n");
            return ERROR;
        }
    }
    else if (SCI_DUAL == p_nv_sci->cfg.card_num) 
    {
        /*双卡场景*/
        if ((p_nv_sci->cfg.card0 <= CARD_CONNECT_SCI1) &&
            (p_nv_sci->cfg.card1 <= CARD_CONNECT_SCI1) &&
            (p_nv_sci->cfg.card0 != p_nv_sci->cfg.card1)) 
        {
            sci_print_debug("dual cards, card0 connect sci%d,card1 connect sci%d\r\n",p_nv_sci->cfg.card0, p_nv_sci->cfg.card1);
			if(BSP_OK != bsp_sci_cfg(CARD0, p_nv_sci->cfg.card0))
            {
            	sci_print_error("bsp_sci_parse_nv, total cfg sci%d failed! \r\n",p_nv_sci->cfg.card0);
				return BSP_ERROR;
			}
			if(BSP_OK != bsp_sci_cfg(CARD1, p_nv_sci->cfg.card1))
            {
            	sci_print_error(" total cfg sci%d failed! \r\n",p_nv_sci->cfg.card1);
				return BSP_ERROR;
			}
        }
        else 
		{
            /*暂不支持多卡*/
			sci_print_error("do not support multi card! case 3\n");
            return BSP_ERROR;
        }
    }
    else 
	{
        /*暂不支持多卡*/
		sci_print_error(" do not support multi card! case 4\n");
        return BSP_ERROR;
    }

    return BSP_OK;
}
/*****************************************************************************
 函 数 名  : bsp_sci_cfg
 功能描述  : 进行硬件相关的配置
 输入参数  : unsigned int card_id
             unsigned int sci_id
 输出参数  : 无
 返 回 值  : int
 调用函数  :
 被调函数  : BSP_SCI_ParseNV

 修改历史      :

*****************************************************************************/
int bsp_sci_cfg(unsigned int card_id, unsigned int sci_id)
{
    SCI_CFG_STRU * p_sci_cfg;

    if (card_id >= (unsigned int)(&_sci_init_data_end - &_sci_init_data_start)) 
	{
		sci_print_error("card_id is too large!\r\n");
        return BSP_ERROR;
    }

    p_sci_cfg = (SCI_CFG_STRU *)((int)&_sci_cfg_data_start + \
                                (int)(sizeof(SCI_CFG_STRU)*card_id));
    p_sci_cfg->card_id = card_id;
    if (CARD_CONNECT_SCI0 == sci_id) 
    {  
        /* regs base\ int \ clk */
        p_sci_cfg->base_addr  = HI_SCI0_REGBASE_ADDR;
        p_sci_cfg->int_number = INT_LVL_SCI0;
        p_sci_cfg->sci_id     = sci_id;
        p_sci_cfg->dma_chan   = EDMA_SCI0_RX;     
        p_sci_cfg->clk_en_reg  = HI_CRG_CLKEN4_OFFSET;
        p_sci_cfg->clk_en_bit  = SCI0_CLK_SET_BIT_SHIFT;
        p_sci_cfg->clk_dis_reg = HI_CRG_CLKDIS4_OFFSET;        
        p_sci_cfg->clk_dis_bit = SCI0_CLK_SET_BIT_SHIFT; 

        /* PMU */
        p_sci_cfg->pwr_type = CARD_PM_TYPE_SIM0;

        /*异常记录相关的配置,包括记录区的基地址以及记录文件路径*/
        p_sci_cfg->record_enum= CARD0_EXCP_RECORD_ADDR_NUM;

        p_sci_cfg->m3c_icc_chnl = ((ICC_CHN_MCORE_CCORE << 16) | MCORE_CCORE_FUNC_SIM0);

        p_sci_cfg->ac_icc_chnl  = ((ICC_CHN_IFC<< 16) | IFC_RECV_FUNC_SIM0);

        p_sci_cfg->record_file= (char *)g_pcCardRecordFileName[card_id];

        /* task */
        p_sci_cfg->syncTaskName   = (char *)g_pcCardTaskName[card_id];

        /*卡0投票*/
        p_sci_cfg->sleep_vote = PWRCTRL_SLEEP_SCI0;
        p_sci_cfg->slot_switch_flag = SCI_SLOT_SWITCH_NONE;
        p_sci_cfg->sci_pmu = NULL;
        p_sci_cfg->task_id = 0;
        p_sci_cfg->sci_int_handler = NULL;
        
    }
    else if (CARD_CONNECT_SCI1 == sci_id) {
        p_sci_cfg->base_addr  = HI_SCI1_REGBASE_ADDR;
        p_sci_cfg->sci_id     = sci_id;
        p_sci_cfg->int_number = INT_LVL_SCI1;
        p_sci_cfg->dma_chan    = EDMA_SCI1_RX;  
        p_sci_cfg->clk_en_reg  = HI_CRG_CLKEN4_OFFSET;
        p_sci_cfg->clk_en_bit  = SCI1_CLK_SET_BIT_SHIFT;
        p_sci_cfg->clk_dis_reg = HI_CRG_CLKDIS4_OFFSET;        
        p_sci_cfg->clk_dis_bit = SCI1_CLK_SET_BIT_SHIFT;

        /* PMU */
        p_sci_cfg->pwr_type = CARD_PM_TYPE_SIM1;

        /*异常记录相关的配置,包括记录区的基地址以及记录文件路径*/
        p_sci_cfg->record_enum = CARD1_EXCP_RECORD_ADDR_NUM;
        p_sci_cfg->m3c_icc_chnl = ((ICC_CHN_MCORE_CCORE << 16) | MCORE_CCORE_FUNC_SIM1);
        p_sci_cfg->ac_icc_chnl  = ((ICC_CHN_IFC<< 16) | IFC_RECV_FUNC_SIM1);

		
            
        p_sci_cfg->record_file = (char *)g_pcCardRecordFileName[card_id];

        /* task */
        p_sci_cfg->syncTaskName   = (char *)g_pcCardTaskName[card_id];

        /*卡0投票*/
        p_sci_cfg->sleep_vote = PWRCTRL_SLEEP_SCI1;
        p_sci_cfg->slot_switch_flag = SCI_SLOT_SWITCH_NONE;        
        p_sci_cfg->sci_pmu = NULL;
        p_sci_cfg->task_id = 0;
        p_sci_cfg->sci_int_handler = NULL;
        
        
    }
    else 
    {
    	sci_print_error("card_id error!\r\n");
        return BSP_ERROR;
    }
    

    return BSP_OK;
}
void sci_print_cfg(SCI_CFG_STRU* p_sci_cfg)
{
    sci_print_error("card_id = %d\n",p_sci_cfg->card_id);
        
    sci_print_error("sci_id = %d\n",p_sci_cfg->sci_id);
        
    sci_print_error("base_addr = 0x%x\n",p_sci_cfg->base_addr);
        
    sci_print_error("int_number = 0x%x\n",p_sci_cfg->int_number);
    
    sci_print_error("icc_chnl = 0x%x\n",p_sci_cfg->icc_chnl);
    
    sci_print_error("pwr_type = %s\n",p_sci_cfg->pwr_type);
        
    sci_print_error("syncTaskName = %s\n",p_sci_cfg->syncTaskName);
        
    sci_print_error("hotPlugTaskName = %s\n",p_sci_cfg->hotPlugTaskName);
        
    sci_print_error("sci_int_handler = 0x%x\n",p_sci_cfg->sci_int_handler);

    sci_print_error("sync_task_id = %d\n",p_sci_cfg->sync_task_id);
        
    sci_print_error("hotplug_task_id = %d\n",p_sci_cfg->hotplug_task_id);


}
/*****************************************************************************
 函 数 名  : bsp_sci_cfg
 功能描述  : 进行硬件相关的配置
 输入参数  : unsigned int card_id
             unsigned int sci_id
 输出参数  : 无
 返 回 值  : int
 调用函数  :
 被调函数  : BSP_SCI_ParseNV

 修改历史      :

*****************************************************************************/
int bsp_sci_cfg(unsigned int card_id, unsigned int sci_id)
{
    SCI_CFG_STRU * p_sci_cfg;
    struct device_node* dev = NULL;
    const char* name[] = {"hisilicon,sci0_balong","hisilicon,sci1_balong","null"};
    sci_freq_str sci_freq = {0,};
    s32 irq = 0;
    char* base_addr = NULL;
    
#if(FEATURE_ON == FEATURE_MULTI_MODEM)
    NV_SCI_CFG_UNION * nv_val = (NV_SCI_CFG_UNION *)(&g_SciNVValue);
#endif

    enum ICC_RECV_FUNC_ID ac_channel[2] = {IFC_RECV_FUNC_SIM0,IFC_RECV_FUNC_SIM1};

    p_sci_cfg = (SCI_CFG_STRU *)((int)&_sci_cfg_data_start + \
                                (int)(sizeof(SCI_CFG_STRU)*card_id));

    if (card_id >= (unsigned int)(&_sci_init_data_end - &_sci_init_data_start)) 
	{
		sci_print_error("card_id is too large!\r\n");
        return BSP_ERROR;
    }
    
    if(sci_id != CARD_CONNECT_SCI0  && sci_id != CARD_CONNECT_SCI1 && sci_id != CARD_CONNECT_SCI2)
    {
    	sci_print_error("card_id error!\r\n");
        return BSP_ERROR;
    }
    
    if(card_id > CARD2)
    {
        sci_print_error("card_id bigger than card2!\r\n");
        return BSP_ERROR;
    }
    
#if(FEATURE_ON == FEATURE_MULTI_MODEM)
    if(MULTI_MODEM_NUMBER == 3)
    {
        if(nv_val->cfg.sci0 ==nv_val->cfg.sci1  || nv_val->cfg.sci0 ==nv_val->cfg.sci2 || nv_val->cfg.sci2 ==nv_val->cfg.sci1  ) 
        {
            sci_print("in three modem the cfg can not same\n");
            return BSP_ERROR;
        }
    }
    else if(MULTI_MODEM_NUMBER == 2)
    {
        if(nv_val->cfg.sci0 ==nv_val->cfg.sci1)
        {
            sci_print("in double modem the cfg can not same\n");
            return BSP_ERROR;
        }
    }

#endif

    if(sci_id == CARD_CONNECT_SCI2)
    {
       p_sci_cfg->sci_id = sci_id;      
       p_sci_cfg->card_id = card_id;
       return BSP_OK;
    }

    dev = of_find_compatible_node(NULL,NULL,name[sci_id]);
    if(NULL == dev)
    {
        sci_print_error("sci not find\n");
        return BSP_ERROR;
    }
    irq = (int)irq_of_parse_and_map(dev,0);
    sci_print_error("irq is 0x%x\n",irq);
    base_addr = of_iomap(dev,0);
    if(NULL == base_addr)
    {
        sci_print_error("sci base addr not find\n");
        return BSP_ERROR;
    }
    
    (void)of_property_read_u32_index(dev, "sci_ref_freq", 0,&sci_freq.sci_ref_freq);
    if(sci_freq.sci_ref_freq == 0)
    {
        sci_print_error("sci get ref freq fail\n");
        return BSP_ERROR;
    }

    (void)of_property_read_u32_index(dev, "sci_work_freq", 0,&sci_freq.sci_work_freq);
    if(sci_freq.sci_work_freq == 0)
    {
        sci_print_error("sci get work freq fail\n");
        return BSP_ERROR;
    }



    p_sci_cfg->card_id = card_id;

    
    if (CARD_CONNECT_SCI0 == sci_id) 
    {  
        /* regs base\ int \ clk */
        p_sci_cfg->base_addr  = (unsigned int)base_addr;
        p_sci_cfg->int_number = (u32)irq;
        p_sci_cfg->sci_id     = sci_id;
        p_sci_cfg->dma_chan   = EDMA_SCI0_RX;     

        p_sci_cfg->clk_en_bit  = SCI0_CLK_SET_BIT_SHIFT;
  
        p_sci_cfg->clk_dis_bit = SCI0_CLK_SET_BIT_SHIFT; 

        /* PMU */
        p_sci_cfg->pwr_type = CARD_PM_TYPE_SIM0;

        /*异常记录相关的配置,包括记录区的基地址以及记录文件路径*/
        p_sci_cfg->record_enum= CARD0_EXCP_RECORD_ADDR_NUM;

        
        p_sci_cfg->icc_chnl     = ((ICC_CHN_IFC<< 16) | ac_channel[sci_id]);

        p_sci_cfg->record_file= (char *)g_pcCardRecordFileName[sci_id];

        /* task */
        p_sci_cfg->syncTaskName   = (char *)g_pcCardTaskName[sci_id];
        
        p_sci_cfg->hotPlugTaskName= (char *)g_pcCardHOTPLUGTaskName[sci_id];

        /*卡0投票*/
        p_sci_cfg->sleep_vote = PWRCTRL_SLEEP_SCI0;

        /*卡0时钟*/
        p_sci_cfg->clk        = (struct clk*)clk_get(NULL,"sci0_clk");
        p_sci_cfg->sci_freq.sci_work_freq= sci_freq.sci_work_freq;
        p_sci_cfg->sci_freq.sci_ref_freq = sci_freq.sci_ref_freq;
		p_sci_cfg->slot_switch_flag = SCI_SLOT_SWITCH_NONE;
        p_sci_cfg->sci_pmu = NULL;
        p_sci_cfg->sync_task_id = 0;       
        p_sci_cfg->hotplug_task_id = 0;       
        p_sci_cfg->sci_int_handler = NULL;
        memset_s(&(p_sci_cfg->sci_sem),sizeof(SCI_SEM_S),0,sizeof(SCI_SEM_S));
        sci_parse_ap_sys_ctrl(p_sci_cfg);
        
    }
    else if (CARD_CONNECT_SCI1 == sci_id) 
    {  

        /* regs base\ int \ clk */
        p_sci_cfg->base_addr  = (unsigned int)base_addr;
        p_sci_cfg->int_number = (u32)irq;
        p_sci_cfg->sci_id     = sci_id;
        p_sci_cfg->dma_chan   = EDMA_SCI1_RX;     

        p_sci_cfg->clk_en_bit  = SCI1_CLK_SET_BIT_SHIFT;
  
        p_sci_cfg->clk_dis_bit = SCI1_CLK_SET_BIT_SHIFT; 

        /* PMU */
        p_sci_cfg->pwr_type = CARD_PM_TYPE_SIM1;

        /*异常记录相关的配置,包括记录区的基地址以及记录文件路径*/
        p_sci_cfg->record_enum= CARD1_EXCP_RECORD_ADDR_NUM;

        
        p_sci_cfg->icc_chnl     = ((ICC_CHN_IFC<< 16) | ac_channel[sci_id]);
        
        p_sci_cfg->record_file= (char *)g_pcCardRecordFileName[sci_id];

        /* task */
        p_sci_cfg->syncTaskName   = (char *)g_pcCardTaskName[sci_id];
        
        p_sci_cfg->hotPlugTaskName= (char *)g_pcCardHOTPLUGTaskName[sci_id];

        /*卡0投票*/
        p_sci_cfg->sleep_vote = PWRCTRL_SLEEP_SCI1;


        /*卡0时钟*/
        p_sci_cfg->clk        = (struct clk*)clk_get(NULL,"sci1_clk");
        p_sci_cfg->sci_freq.sci_work_freq= sci_freq.sci_work_freq;
        p_sci_cfg->sci_freq.sci_ref_freq = sci_freq.sci_ref_freq;
		p_sci_cfg->slot_switch_flag = SCI_SLOT_SWITCH_NONE;        
        p_sci_cfg->sci_pmu = NULL;
        p_sci_cfg->sync_task_id = 0;
        p_sci_cfg->hotplug_task_id = 0;       
        p_sci_cfg->sci_int_handler = NULL;
        memset_s(&(p_sci_cfg->sci_sem),sizeof(SCI_SEM_S),0,sizeof(SCI_SEM_S));
        sci_parse_ap_sys_ctrl(p_sci_cfg);


        
    }
    return BSP_OK;
}