int tsensor_init(struct platform_device *pdev)
{

    gstTempPrtInfo.virt_base_addr = (void __iomem  *)HISI_VA_ADDRESS(SOC_PERI_SCTRL_BASE_ADDR);
    if(!gstTempPrtInfo.virt_base_addr)
    {
        printk(KERN_ERR "tsensor baseaddr ioremap error.\n");
        return TSENSOR_ERR;
    }

    /* tsensor配置初始化 */
    (void)tsensor_config_init(pdev);

    if (gstTempPrtInfo.enable == 0)
    {
        printk(KERN_ERR "Tsensor is not enabled.\n");
	    return TSENSOR_ERR;
	}

    mutex_init(&gstTempPrtInfo.get_tmp_lock);

    tsensor_init_config();

    /*待late_init初始化完成后置位为ok*/
    gstTempPrtInfo.init_flag = TSENSOR_INIT_NOT_OK;

	printk(KERN_INFO "Tsensor early init ok.\n");

    return TSENSOR_OK;
}
/*****************************************************************************
 函 数 名  : ccorereset_enable_wdt_irq
 功能描述  : 通过写寄存器实现其他核中断到a核
 输入参数  : 无
 输出参数  : 无
 返 回 值  : int
*****************************************************************************/
static int ccorereset_enable_wdt_irq(void)
{
#ifdef _DRV_LLT_
#else
	unsigned long sctrl_on  = (unsigned long)HISI_VA_ADDRESS(SOC_AO_SCTRL_BASE_ADDR);

    unsigned long uvalue = 0;


    /*WatchDog1 HIFI WatchDog超时复位请求*/
    uvalue = readl((void __iomem *)SOC_AO_SCTRL_SC_MCU_WKUP_INT_EN1_ADDR(sctrl_on));
    printk(KERN_INFO "%s: org val = 0x%lx\n", __FUNCTION__, uvalue);

    writel((uvalue | (1 << 6)), (void __iomem *)SOC_AO_SCTRL_SC_MCU_WKUP_INT_EN1_ADDR(sctrl_on));
    uvalue = readl((void __iomem *)SOC_AO_SCTRL_SC_MCU_WKUP_INT_EN1_ADDR(sctrl_on));
    printk(KERN_INFO "%s: new val = 0x%lx\n", __FUNCTION__, uvalue);

#if 0
        unsigned int  sc_int_en0_0awd           : 1;  /* bit[0] : [0]: ACPU Watchdog复位请求中断,送给MCU。 */
        unsigned int  sc_int_en0_1cm3wdg0       : 1;  /* bit[1] : [1]: CM3 Watchdog0复位请求中断,送给ACPU。 */
        unsigned int  sc_int_en0_2hifiwd        : 1;  /* bit[2] : [2]: HIFI Watchdog复位请求中断,送给MCU和ACPU。 */
        unsigned int  sc_int_en0_3bakwd         : 1;  /* bit[3] : [3]: 备份Watchdog复位请求中断,送给MCU和ACPU。 */
        unsigned int  sc_int_en0_4acpu_sft_fiq  : 1;  /* bit[4] : [4]: acpu fiq int,送给acpu,用于调试,由acpu_sft_fiq_req配置产生。 */
#endif
    writel(0x1f, (void __iomem *)SOC_AO_SCTRL_SC_INT_EN_SET_ADDR(sctrl_on));
    uvalue = readl((void __iomem *)SOC_AO_SCTRL_SC_INT_EN_SET_ADDR(sctrl_on));
    printk(KERN_INFO "%s: new uvalue = 0x%lx\n", __FUNCTION__, uvalue);

#endif
    return 0;
}
/*****************************************************************************
 函 数 名  : BSP_DDR_GetSectInfo
 功能描述  : DDR内存段查询接口
 输入参数  : pstSectQuery: 需要查询的内存段类型、属性
 输出参数  : pstSectInfo:  查询到的内存段信息
 返回值    :BSP_OK/BSP_ERROR
*****************************************************************************/
BSP_S32 BSP_DDR_GetSectInfo(BSP_DDR_SECT_QUERY_S *pstSectQuery, BSP_DDR_SECT_INFO_S *pstSectInfo)
{
    int i = 0;
    int NUM_TMP = sizeof(g_stDdrSectInfo)/sizeof(g_stDdrSectInfo[0]);
    if((BSP_NULL == pstSectQuery) || (BSP_NULL == pstSectInfo))
    {
        return BSP_ERROR;
    }

    for (i = 0;i < NUM_TMP;i++)
    {

        if (pstSectQuery->enSectType == g_stDdrSectInfo[i].enSectType)
        {
            memcpy((void *)pstSectInfo, (const void *)(&g_stDdrSectInfo[i]), sizeof(BSP_DDR_SECT_INFO_S));
#if (defined BSP_CORE_APP)
            if (pstSectInfo->pSectPhysAddr != 0)
            {
                pstSectInfo->pSectVirtAddr = (BSP_VOID*)HISI_VA_ADDRESS(pstSectInfo->pSectPhysAddr);
            }
#endif
            return BSP_OK;
        }
    }

    return BSP_ERROR;
}
/*****************************************************************************
* 函 数 名  : IPF_WaitResume
*
* 功能描述  : 提供的低功耗接口,用于等待IPF恢复OK
*
* 输入参数  : 无
*
* 输出参数  : 无
* 返 回 值  : 无
*
* 修改记录  : 2012年11月29日   z00212992  创建
*****************************************************************************/
int IPF_WaitResume(void)
{
    unsigned int u32Times = 0;
    IPF_RESTORE_STATE_E IPF_Restore_flag = (IPF_RESTORE_STATE_E)0;

    unsigned long ipf_restore_flag_addr = HISI_VA_ADDRESS(MEMORY_RAM_CORESHARE_IPF_FLAG_ADDR);

    IPF_Restore_flag= (IPF_RESTORE_STATE_E)(*(volatile unsigned int*)ipf_restore_flag_addr);

    /* 获取IPF状态标识 */
    if(IPF_STATE_RESTORED == IPF_Restore_flag)
    {
        return IPF_SUCCESS;
    }

    /* 等待IPF_Restore_flag等于IPF_STATE_RESTORED,加入2ms超时机制 */
    do{
        IPF_Restore_flag = (IPF_RESTORE_STATE_E)(*(volatile unsigned int*)ipf_restore_flag_addr);
        udelay(10);
        u32Times++;
    }while((IPF_STATE_RESTORED != IPF_Restore_flag) && (u32Times < IPF_RESUME_COUNT));

    if(IPF_RESUME_COUNT == u32Times)
    {
        return IPF_ERROR;
    }

    return IPF_SUCCESS;
}
/*****************************************************************************
 函 数 名  : DRV_GET_BBP_TIMER_VALUE
 功能描述  : 获取BBP定时器的值。用于OAM 时戳
 输入参数  : 无。
 输出参数  : pulHigh32bitValue:BBP定时器的值获取高32bit,本参数如为空,
                                                      则只返回低32bit的值
                            pulLow32bitValue:BBP定时器的值获取低 32bit,不能为空,否则会返回失败。
 返 回 值  : 0-成功
                       -1 -失败

*****************************************************************************/
 int DRV_GET_BBP_TIMER_VALUE(unsigned int  *pulHigh32bitValue,  unsigned int  *pulLow32bitValue)
 {
    BSP_U64 u64TempTime[4];
    unsigned long sctrl_addr = (unsigned long)HISI_VA_ADDRESS(SOC_SC_OFF_BASE_ADDR);

    if (NULL == pulLow32bitValue)
    {
        printk("DRV_GET_BBP_TIMER_VALUE Wrong Para. line:%d\n", __LINE__);
        return BSP_ERR_INVALID_PARA;
    }

    u64TempTime[0] = readl(SOC_SCTRL_SC_BBPABB_SUBSYS_STAT3_ADDR(sctrl_addr));
    u64TempTime[1] = readl(SOC_SCTRL_SC_BBPABB_SUBSYS_STAT4_ADDR(sctrl_addr));
    u64TempTime[2] = readl(SOC_SCTRL_SC_BBPABB_SUBSYS_STAT3_ADDR(sctrl_addr));
    u64TempTime[3] = readl(SOC_SCTRL_SC_BBPABB_SUBSYS_STAT4_ADDR(sctrl_addr));

    if (u64TempTime[2] < u64TempTime[0])
    {
        if (pulHigh32bitValue != NULL) {
            *pulHigh32bitValue = (u64TempTime[3] - 1);
        }

        *pulLow32bitValue = u64TempTime[0];
    }
    else
    {
        if (pulHigh32bitValue != NULL) {
            *pulHigh32bitValue = u64TempTime[1];
        }

        *pulLow32bitValue = u64TempTime[0];
    }

    return 0;
 }
/*****************************************************************************
* 函 数 名  : BBPGetCurTime
*
* 功能描述  : 被PS调用,用来获取系统精确时间
*
* 输入参数  : 无
* 输出参数  : BSP_U32 u32CurTime:当前时刻
*
* 返 回 值  : BSP_OK : 获取成功
*                        BSP_ERR_INVALID_PARA  :获取失败
*
* 修改记录  : 2011年3月7日  wangjing  creat
*****************************************************************************/
BSP_U32 BBPGetCurTime(BSP_U64 *pCurTime)
{
    BSP_U64 u64TempTime[4];
    void __iomem* sctrl_addr = (void __iomem*)HISI_VA_ADDRESS(SOC_AO_SCTRL_BASE_ADDR);

    if (NULL == pCurTime)
    {
        printk("BSP_BBPGetCurTime Wrong Para. line:%d\n", __LINE__);
        return BSP_ERR_INVALID_PARA;
    }

    u64TempTime[0] = readl(SOC_AO_SCTRL_SC_SYSTEST_SLICER_CNT0_ADDR(sctrl_addr));
    u64TempTime[1] = readl(SOC_AO_SCTRL_SC_SYSTEST_SLICER_CNT1_ADDR(sctrl_addr));
    u64TempTime[2] = readl(SOC_AO_SCTRL_SC_SYSTEST_SLICER_CNT0_ADDR(sctrl_addr));
    u64TempTime[3] = readl(SOC_AO_SCTRL_SC_SYSTEST_SLICER_CNT1_ADDR(sctrl_addr));

    if (u64TempTime[2] < u64TempTime[0])
    {
        *pCurTime = ((u64TempTime[3] - 1) << 32) | u64TempTime[0];
    }
    else
    {
        *pCurTime = (u64TempTime[1] << 32) | u64TempTime[0];
    }

    return 0;
}
int pwrctrl_dfs_init(void)
{
    void __iomem *reg_addr;
    struct acpufreqinfo *p_freqinfo;

    reg_addr = (void __iomem *)HISI_VA_ADDRESS(SOC_PERI_SCTRL_SC_RESERVED8_ADDR(SOC_PERI_SCTRL_BASE_ADDR));
    g_dfs_data_addr = ioremap(ACPU_DFS_FREQ_ADDR, ACPU_DFS_FREQ_ADDR_SIZE);

    p_freqinfo = (struct acpufreqinfo *)g_dfs_data_addr;
    p_freqinfo->dfs_flag = 0;
    p_freqinfo->dfs_acpu_freq = 0;
    p_freqinfo->dfs_temp_freq = 0;

    g_stPwcSwitch = (ST_PWC_SWITCH_STRU *)(reg_addr);

	dt_insmod_buslow();
	dt_insmod_bus_dfs();
	if(!dt_insmod_dvfs()){g_adfs_module = 1;}

    wake_lock_init(&acpu_freq_lock,WAKE_LOCK_SUSPEND,"acpu_freq_lock");

    ddr_min_req.pm_qos_class = 0;
    ddr_max_req.pm_qos_class = 0;
    pm_qos_add_request(&ddr_min_req, DFS_QOS_ID_DDR_MINFREQ, QOS_DDR_MIN_DEFAULT_VALUE + 2);
    pm_qos_add_request(&ddr_max_req, DFS_QOS_ID_DDR_MAXFREQ, QOS_DDR_MAX_DEFAULT_VALUE - 2);

    return RET_OK;
}
BSP_S32 BSP_IPF_BDInfo(IPF_CHANNEL_TYPE_E eChnType, BSP_U32 u32BdqPtr)
{
    BSP_U32 u32CdPtr;
    if(u32BdqPtr >= IPF_ULBD_DESC_SIZE)
    {
        return IPF_ERROR;
    }
    switch(eChnType)
    {
        case IPF_CHANNEL_UP:

                IPF_PRINT_ERROR("==========BD Info=========\n");
                IPF_PRINT_ERROR("BD位置:         %d\n",u32BdqPtr);
                IPF_PRINT_ERROR("u16Attribute:   %d\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u16Attribute);
                IPF_PRINT_ERROR("u16PktLen:      %d\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u16PktLen);
                IPF_PRINT_ERROR("u32InPtr:       0x%x\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u32InPtr);
                IPF_PRINT_ERROR("u32OutPtr:      0x%x\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u32OutPtr);
                IPF_PRINT_ERROR("u16Resv:        %d\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u16Result);
                IPF_PRINT_ERROR("u16UsrField1:   %d\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u16UsrField1);
                IPF_PRINT_ERROR("u32UsrField2:   0x%x\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u32UsrField2);
                IPF_PRINT_ERROR("u32UsrField3:   0x%x\n",g_stIpfUl.pstIpfBDQ[u32BdqPtr].u32UsrField3);
            break;
       case IPF_CHANNEL_DOWN:
                IPF_PRINT_ERROR("==========BD Info=========\n");
                IPF_PRINT_ERROR("BD位置:         %d\n",u32BdqPtr);
                IPF_PRINT_ERROR("u16Attribute:   %d\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u16Attribute);
                IPF_PRINT_ERROR("u16PktLen:      %d\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u16PktLen);
                IPF_PRINT_ERROR("u32InPtr:       0x%x\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u32InPtr);
                IPF_PRINT_ERROR("u32OutPtr:      0x%x\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u32OutPtr);
                IPF_PRINT_ERROR("u16Resv:        %d\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u16Result);
                IPF_PRINT_ERROR("u16UsrField1:   %d\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u16UsrField1);
                IPF_PRINT_ERROR("u32UsrField2:   0x%x\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u32UsrField2);
                IPF_PRINT_ERROR("u32UsrField3:   0x%x\n",g_stIpfDl.pstIpfBDQ[u32BdqPtr].u32UsrField3);
                u32CdPtr = (BSP_U32)((char*)HISI_VA_ADDRESS(g_stIpfDl.pstIpfBDQ[u32BdqPtr].u32InPtr)-(char*)g_stIpfDl.pstIpfCDQ);
                u32CdPtr = u32CdPtr/sizeof(IPF_CD_DESC_S);
                while(g_stIpfDl.pstIpfDebugCDQ[u32CdPtr].u16Attribute != 1)
                {
                    IPF_PRINT_ERROR("==========CD Info=========\n");
                    IPF_PRINT_ERROR("CD位置:             %d\n",u32CdPtr);
                    IPF_PRINT_ERROR("u16Attribute:       %d\n",g_stIpfDl.pstIpfDebugCDQ[u32CdPtr].u16Attribute);
                    IPF_PRINT_ERROR("u16PktLen:          %d\n",g_stIpfDl.pstIpfDebugCDQ[u32CdPtr].u16PktLen);
                    IPF_PRINT_ERROR("u32Ptr:             0x%x\n",g_stIpfDl.pstIpfDebugCDQ[u32CdPtr].u32Ptr);
                    u32CdPtr = ((u32CdPtr+1) < IPF_DLCD_DESC_SIZE)?(u32CdPtr+1):0;
                };
                IPF_PRINT_ERROR("==========CD Info=========\n");
                IPF_PRINT_ERROR("CD位置:             %d\n",u32CdPtr);
                IPF_PRINT_ERROR("u16Attribute:       %d\n",g_stIpfDl.pstIpfDebugCDQ[u32CdPtr].u16Attribute);
                IPF_PRINT_ERROR("u16PktLen:          %d\n",g_stIpfDl.pstIpfDebugCDQ[u32CdPtr].u16PktLen);
                IPF_PRINT_ERROR("u32Ptr:             0x%x\n",g_stIpfDl.pstIpfDebugCDQ[u32CdPtr].u32Ptr);
            break;
        default:
            break;
    }
    IPF_PRINT_ERROR("************************\n");
    return 0;
}
int buslow_minfreq_handle(unsigned int req_value)
{
    unsigned int reg_val;
    void __iomem *reg_addr;
    u32 busdfs = 0;
    struct device_node *root;

	root = of_find_compatible_node(NULL,NULL,"hisilicon,hi6210");
	if (!root){
		pr_err("[%s] find root node fail!\n",
			__func__);
		return RET_ERR;
	}

	if (of_property_read_u32(root, "power,busdfs", &busdfs)) {
		pr_err("[%s] node doesn't have this property!\n",
			__func__);
		return RET_ERR;
	}

	if (busdfs == 0){
		return RET_OK;
	}else{
        /*get dfs switch flag*/

        if(DFS_BUSLOW_FREQ_MIN >= req_value)
        {
            reg_addr = (void __iomem *)HISI_VA_ADDRESS(SOC_AO_SCTRL_SC_MCU_VOTE2DIS_ADDR(SOC_AO_SCTRL_BASE_ADDR));
            /*set SC_MCU_VOTE2DIS bit,vote lock,enable bus100M dfs*/
            reg_val = readl(reg_addr);
            writel((reg_val | BIT(BUS_DFS_BIT_ACPU)), reg_addr);
        }
        else
        {
            reg_addr = (void __iomem *)HISI_VA_ADDRESS(SOC_AO_SCTRL_SC_MCU_VOTE2EN_ADDR(SOC_AO_SCTRL_BASE_ADDR));
            /*set SC_MCU_VOTE2EN bit,vote unlock,disable bus100M dfs*/
            reg_val = readl(reg_addr);
            writel((reg_val | BIT(BUS_DFS_BIT_ACPU)), reg_addr);
        }
    }
    return RET_OK;

}
/*runinstall hifi*/
void do_hifi_runstall(void)
{
    SOC_PERI_SCTRL_SC_DSP_SUBSYS_CTRL0_UNION runstall_val;
    unsigned long sctrl_off = (unsigned long)HISI_VA_ADDRESS(SOC_PERI_SCTRL_BASE_ADDR);

    /* runstall hifi */
    runstall_val.value             = 0x0;
    runstall_val.reg.hifi_runstall = 0x1;

    *(volatile unsigned int *)SOC_PERI_SCTRL_SC_DSP_SUBSYS_CTRL0_ADDR(sctrl_off) = runstall_val.value;
}
static __init int addr_init(void)
{
	g_cci_base = (void __iomem *)ioremap(SOC_ACPU_CCI_BASE_ADDR+0x90000,SZ_128K) - 0x90000;
	printk(KERN_INFO"%s g_cci_base:0x%p.\n", __FUNCTION__, g_cci_base);

	g_acpu_sc_base_map = (void __iomem *)HISI_VA_ADDRESS(SOC_ACPU_SCTRL_BASE_ADDR);
	printk(KERN_INFO"%s g_acpu_sc_base_map:0x%p.\n", __FUNCTION__, g_acpu_sc_base_map);

	g_acpu_subsys_powerdown_flag_base = (void __iomem *)HISI_VA_ADDRESS(ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR);
	printk(KERN_INFO"%s acpu subsys power flag addr:0x%p.\n", __FUNCTION__, g_acpu_subsys_powerdown_flag_base);
#if 0
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU0_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 0 cpu 0*/
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU1_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 0 cpu 1*/
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU2_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 0 cpu 2*/
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU3_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 0 cpu 3*/
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU4_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 1 cpu 0*/
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU5_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 1 cpu 1*/
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU6_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 1 cpu 2*/
	writel( PWRCTRL_ACPU_ASM_CODE_BASE >> 2, SOC_ACPU_SCTRL_ACPU_SC_CPU7_RVBARADDR_ADDR((unsigned long)g_acpu_sc_base_map)); /*cluster 1 cpu 3*/
#endif
	return 0;
}
int bus_minfreq_handle(unsigned int req_value)
{
    unsigned int reg_val;
    void __iomem *reg_addr;

    if(DFS_BUS_FREQ_MIN >= req_value)
    {
        reg_addr = (void __iomem *)HISI_VA_ADDRESS(SOC_AO_SCTRL_SC_MCU_VOTE1DIS_ADDR(SOC_AO_SCTRL_BASE_ADDR));
        /*set SC_MCU_VOTE1DIS bit,vote lock,enable bus150M dfs*/
        reg_val = readl(reg_addr);
        writel((reg_val | BIT(BUS_DFS_BIT_ACPU)), reg_addr);
    }
    else
    {
        reg_addr = (void __iomem *)HISI_VA_ADDRESS(SOC_AO_SCTRL_SC_MCU_VOTE1EN_ADDR(SOC_AO_SCTRL_BASE_ADDR));
        /*set SC_MCU_VOTE1EN bit,vote unlock,disable bus150M dfs*/
        reg_val = readl(reg_addr);
        writel((reg_val | BIT(BUS_DFS_BIT_ACPU)), reg_addr);
    }
    return RET_OK;

}
static void modem_wdt_disable(void)
{
    unsigned char* ulBaseAddr = NULL;
    unsigned long ulBaseAddr_ao = 0;
    unsigned int uRegvalue = 0;
    ulBaseAddr_ao = HISI_VA_ADDRESS(SOC_AO_SCTRL_BASE_ADDR);
    uRegvalue = *(unsigned int *)(SOC_AO_SCTRL_SC_PW_MTCMOS_TIMEOUT_STAT0_ADDR(ulBaseAddr_ao));
    pr_info("Balong_power : modem_wdt_disable.\n");
    /*关闭C核狗的时钟*/
    if(uRegvalue & BIT(SOC_AO_SCTRL_SC_PW_MTCMOS_TIMEOUT_STAT0_pw_mtcmos_timeout_stat0_4mcpu_START))
    {
    ulBaseAddr = ioremap(SOC_MODEM_SCTRL_BASE_ADDR,SZ_8K);
    writel(BIT(SOC_MODEM_SCTRL_MDMSC_AO_CLKDIS_ao_peri_clkdis_watchdog0_pclk_START),
              SOC_MODEM_SCTRL_MDMSC_AO_CLKDIS_ADDR(ulBaseAddr));
    }
}
static int __init platform_hotplug_init(void)
{
    acpu_sctrl_base_addr = (unsigned long)HISI_VA_ADDRESS(SOC_ACPU_SCTRL_BASE_ADDR);

    g_acpu_core_sc_baseaddr[0] = SOC_ACPU_SCTRL_ACPU_SC_CPU0_CTRL_ADDR(acpu_sctrl_base_addr);
    g_acpu_core_sc_baseaddr[1] = SOC_ACPU_SCTRL_ACPU_SC_CPU1_CTRL_ADDR(acpu_sctrl_base_addr);
    g_acpu_core_sc_baseaddr[2] = SOC_ACPU_SCTRL_ACPU_SC_CPU2_CTRL_ADDR(acpu_sctrl_base_addr);
    g_acpu_core_sc_baseaddr[3] = SOC_ACPU_SCTRL_ACPU_SC_CPU3_CTRL_ADDR(acpu_sctrl_base_addr);
    g_acpu_core_sc_baseaddr[4] = SOC_ACPU_SCTRL_ACPU_SC_CPU4_CTRL_ADDR(acpu_sctrl_base_addr);
    g_acpu_core_sc_baseaddr[5] = SOC_ACPU_SCTRL_ACPU_SC_CPU5_CTRL_ADDR(acpu_sctrl_base_addr);
    g_acpu_core_sc_baseaddr[6] = SOC_ACPU_SCTRL_ACPU_SC_CPU6_CTRL_ADDR(acpu_sctrl_base_addr);
    g_acpu_core_sc_baseaddr[7] = SOC_ACPU_SCTRL_ACPU_SC_CPU7_CTRL_ADDR(acpu_sctrl_base_addr);
    printk("%s: %lu %lu %lu %lu\n", __FUNCTION__, g_acpu_core_sc_baseaddr[0],
        g_acpu_core_sc_baseaddr[1], g_acpu_core_sc_baseaddr[2],
        g_acpu_core_sc_baseaddr[3]);
    printk("%s: %lu %lu %lu %lu\n", __FUNCTION__, g_acpu_core_sc_baseaddr[4],
        g_acpu_core_sc_baseaddr[5], g_acpu_core_sc_baseaddr[6],
        g_acpu_core_sc_baseaddr[7]);
#ifndef CONFIG_ARM64
    register_hotcpu_notifier(&platform_cpu_up_notifier);
    register_hotcpu_notifier(&platform_cpu_down_notifier);
#endif
    return 0;
}
/*****************************************************************************
 函 数 名  : init_om_hardware_timer
 功能描述  : 初始化OM使用的timer
 输入参数  : 无
 输出参数  : 无
 返 回 值  : int
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2012年9月7日
    作    者   : 王振伟 176398
    修改内容   : 新生成函数

*****************************************************************************/
int __init init_om_hardware_timer(void)
{
    volatile unsigned int tmp_val = 0;
    unsigned long timer1_addr = 0;
    unsigned long sctrl_addr = HISI_VA_ADDRESS(SOC_AO_SCTRL_BASE_ADDR);

    timer1_base = (unsigned long)ioremap(OSA_TIMER_REG_BASE, OSA_TIMER_REG_SIZE);
    if (!timer1_base)
    {
        printk(KERN_ERR "timer1 reg ioremap error.\n");
        return -1;
    }

    timer1_addr = timer1_base;

    /*对系统控制器的操作,使用spin_lock锁住*/
    spin_lock(&g_sysctrl_lock);

    /*选择32K时钟*/
    tmp_val = readl(SOC_AO_SCTRL_SC_TIMER_EN0_ADDR(sctrl_addr));
    tmp_val = (tmp_val & SC_TIMER_EN0_MSK_TIMER1_0_MSK) | (TIMER_32K << SC_TIMER_EN0_MSK_TIMER1_0_START_BIT); /* DTS2013012804205 lkf71598 2013-3-4 */
    tmp_val = (tmp_val & SC_TIMER_EN0_TIMER1_0_MSK) | (TIMER_32K << SC_TIMER_EN0_TIMER1_0_START_BIT);
    writel(tmp_val, SOC_AO_SCTRL_SC_TIMER_EN0_ADDR(sctrl_addr));
    /*释放中断互斥*/
    spin_unlock(&g_sysctrl_lock);

    /*初始化timer*/
    tmp_val = TIMER_DEF_TC_DISABLE | TIMER_DEF_TC_PERIODIC | TIMER_DEF_TC_INTDISABLE |\
            TIMER_DEF_TC_CLK_DIV_1 | TIMER_DEF_TC_32BITS_MODE;
    tmp_val = (tmp_val & TIMER_DEF_TC_ONESHOT_MODE_BIT_MSK) | TIMER_DEF_TC_ONCE_MODE;
    writel(tmp_val, SOC_TIMER_TIMERN_CONTROL_ADDR(timer1_addr, OSA_TIMER_INDEX));

    g_om_timer_inited = TIMER_INITED;

    return 0;
}
/*****************************************************************************
 函 数 名  : drv_hifi_power_up
 功能描述  : 设置HIFI系统控制器
 输入参数  : 无
 输出参数  : 无
 返 回 值  : void
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2012年8月29日
    作    者   : 刘慈红 lKF71598
    修改内容   : 新生成函数

*****************************************************************************/
void drv_hifi_power_up(void)
{
    /*虚实地址转换*/
    unsigned long sctrl_on  = (unsigned long)HISI_VA_ADDRESS(SOC_AO_SCTRL_BASE_ADDR);
    unsigned long sctrl_off = (unsigned long)HISI_VA_ADDRESS(SOC_PERI_SCTRL_BASE_ADDR);

#ifdef CONFIG_ARCH_HI6XXX
    /* 加载前先复位hifi */
    writel(1 << SOC_PERI_SCTRL_SC_PERIPH_RSTEN1_periph_rsten1_hifi_START,
           SOC_PERI_SCTRL_SC_PERIPH_RSTEN1_ADDR(sctrl_off));

    /* PW EN 寄存器已不存在*/

    /* PW ISO DIS */
    writel(1 << SOC_AO_SCTRL_SC_PW_ISODIS0_pw_isodis0_8hifi_START,
           SOC_AO_SCTRL_SC_PW_ISODIS0_ADDR(sctrl_on));

    mdelay(1);

    /* 外设时钟使能 */
    writel(1 << SOC_PERI_SCTRL_SC_PERIPH_CLKEN1_periph_clken1_hifi_START,
           SOC_PERI_SCTRL_SC_PERIPH_CLKEN1_ADDR(sctrl_off));

    /* 打开掉电区总时钟 */
    writel(1 << SOC_AO_SCTRL_SC_PW_CLKEN0_pw_clken0_8hifi_START,
           SOC_AO_SCTRL_SC_PW_CLKEN0_ADDR(sctrl_on));

    /* 下电区总解复位 */
    writel(1 << SOC_AO_SCTRL_SC_PW_RSTDIS0_pw_rstdis0_8hifi_START,
           SOC_AO_SCTRL_SC_PW_RSTDIS0_ADDR(sctrl_on));

    /* 解复位IP */
    writel(1 << SOC_PERI_SCTRL_SC_PERIPH_RSTDIS1_periph_rstdis1_hifi_START,
           SOC_PERI_SCTRL_SC_PERIPH_RSTDIS1_ADDR(sctrl_off));

#else

    unsigned long pmctrl    = (unsigned long)HISI_VA_ADDRESS(SOC_PMCTRL_BASE_ADDR);

    /* 加载前先复位hifi */
    writel(0x1<<6, (void __iomem *)SOC_SCTRL_SC_PERIPH_RSTEN0_ADDR(sctrl_off));

    /* PW EN,默认已打开 */

    /* 关闭时钟 */
    writel(0x1<<27,  (void __iomem *)SOC_SCTRL_SC_PERIPH_CLKDIS12_ADDR(sctrl_off));

    /* 选择HIFI的PLL,源自PERIPH_PLL */
    writel(0x90, (void __iomem *)SOC_PMCTRL_CLKCFG4BIT1_ADDR(pmctrl));

    /* 配置4分频,输出360MHz */
    writel(0x83, (void __iomem *)SOC_SCTRL_SC_CLKCFG8BIT4_ADDR(sctrl_off));

    /* 外设时钟使能 */
    writel(0x1<<27,  (void __iomem *)SOC_SCTRL_SC_PERIPH_CLKEN12_ADDR(sctrl_off));

    /* 打开下电区总时钟 */
    writel(0x1<<8, (void __iomem *)SOC_AO_SCTRL_SC_PW_CLKEN0_ADDR(sctrl_on));

    mdelay(1);

    /* PW ISO DIS */
    writel(0x1<<8,  (void __iomem *)SOC_AO_SCTRL_SC_PW_ISODIS0_ADDR(sctrl_on));

    /* 下电区总解复位 */
    writel(0x1<<8,  (void __iomem *)SOC_AO_SCTRL_SC_PW_RSTDIS0_ADDR(sctrl_on));

    /* 解复位IP */
    writel(0x1<<6, (void __iomem *)SOC_SCTRL_SC_PERIPH_RSTDIS0_ADDR(sctrl_off));

    mdelay(1);
#endif
}
/*****************************************************************************
 函 数 名  : DRV_DDR_PHY_TO_VIRT
 功能描述  : DDR内存虚地址往实地址转换
 输入参数  : ulPAddr;实地址
 输出参数  : 无
 返回值    :虚地址
*****************************************************************************/
void* DRV_DDR_PHY_TO_VIRT(void* ulPAddr)
{
    return (void*)HISI_VA_ADDRESS((unsigned long)ulPAddr);
}
示例#18
0
/*****************************************************************************
* 函 数 名  : BSP_IPF_GetDlRd
*
* 功能描述  : 该接口用于读取下行BD, 支持一次读取多个BD
*
* 输入参数  : unsigned int* pu32Num
*             IPF_RD_DESC_S *pstRd
*
* 输出参数  : unsigned int* pu32Num    实际读取的RD数目
*
* 返 回 值  : IPF_SUCCESS               操作成功
*             IPF_ERROR                   操作失败
*
* 修改记录  :2011年11月30日   鲁婷  创建
*   1.修改日期 : 2012年8月4日
*     修改作者 : z00212992
*     修改记录 : 源地址内存释放上移修改
*****************************************************************************/
void BSP_IPF_GetDlRd(unsigned int* pu32Num, IPF_RD_DESC_S *pstRd)
{
    SOC_IPF_CH1_DQ_DEPTH_UNION unDqDepth;
    unsigned int u32CdqRptr = 0;
    unsigned int u32RdqRptr = 0;
    unsigned int u32RdqDepth = 0;
    unsigned int u32Num = 0;
    unsigned int i = 0;

    if((NULL == pu32Num) || (NULL == pstRd))
    {
        IPF_PRINT_ERROR("parameter is error\n");
        return;
    }

    /* 读取RD深度 */
    unDqDepth.value = 0;
    IPF_REG_READ(SOC_IPF_CH1_DQ_DEPTH_ADDR(IPF_REGBASE_ADR), unDqDepth.value);
    u32RdqDepth = unDqDepth.reg.dl_rdq_depth;

    u32Num = (u32RdqDepth < *pu32Num)?u32RdqDepth:*pu32Num;
    if(u32Num > 0)
    {
        g_stIPFDebugInfo->u32DlRdNum += u32Num;
        for(i = 0; i < u32Num; i++)
        {
            /* 读取RD读指针 */
            IPF_REG_READ(SOC_IPF_CH1_RDQ_RPTR_ADDR(IPF_REGBASE_ADR), u32RdqRptr);
            if(u32RdqRptr >= IPF_DLRD_DESC_SIZE)
            {
                IPF_PRINT_ERROR("u32RdqRptr = %d\n", u32RdqRptr);
            }

            /* 获取RD */
            pstRd[i].u16Attribute = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u16Attribute;
            pstRd[i].u16PktLen = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u16PktLen;
            pstRd[i].u16Result = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u16Result;
            pstRd[i].u32InPtr = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u32InPtr;
            pstRd[i].u32OutPtr = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u32OutPtr;
            if((0 == pstRd[i].u32OutPtr)/* || (0x55555555 == pstRd[i].u32OutPtr) || (0xAAAAAAAA == pstRd[i].u32OutPtr)*/)
            {
                IPF_PRINT_ERROR("invalid rd of dl\n");
                IPF_Assert(BSP_ERR_IPF_INVALID_DLRD);
            }
            pstRd[i].u16UsrField1 = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u16UsrField1;
            pstRd[i].u32UsrField2 = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u32UsrField2;
            pstRd[i].u32UsrField3 = g_stIpfDl.pstIpfRDQ[u32RdqRptr].u32UsrField3;

            u32RdqRptr = ((u32RdqRptr+1) < IPF_DLRD_DESC_SIZE)?(u32RdqRptr+1):0;

            /* 更新RD读指针 */
            IPF_REG_WRITE(SOC_IPF_CH1_RDQ_RPTR_ADDR(IPF_REGBASE_ADR), u32RdqRptr);
            /* 更新CD读指针 */
            u32CdqRptr = (unsigned int)((char *)(HISI_VA_ADDRESS(pstRd[i].u32InPtr)) - (char *)g_stIpfDl.pstIpfCDQ)/sizeof(IPF_CD_DESC_S);
            while(g_stIpfDl.pstIpfCDQ[u32CdqRptr].u16Attribute != 1)
            {
                /* 将释放的CD清0 */
                g_stIpfDl.pstIpfCDQ[u32CdqRptr].u16Attribute = 0;
                g_stIpfDl.pstIpfCDQ[u32CdqRptr].u16PktLen = 0;
                g_stIpfDl.pstIpfCDQ[u32CdqRptr].u32Ptr = 0;
                u32CdqRptr = ((u32CdqRptr+1) < IPF_DLCD_DESC_SIZE)?(u32CdqRptr+1):0;
            }
            u32CdqRptr = ((u32CdqRptr+1) < IPF_DLCD_DESC_SIZE)?(u32CdqRptr+1):0;
            *(g_stIpfDl.u32IpfCdRptr) = u32CdqRptr;
        }
    }
    *pu32Num = u32Num;
}
示例#19
0
/*****************************************************************************
* 函 数 名  : IPF_Init
*
* 功能描述  : IPF初始化     内部使用,不作为接口函数
*
* 输入参数  : void
* 输出参数  : 无
* 返 回 值  : IPF_SUCCESS    初始化成功
*             IPF_ERROR      初始化失败
*
* 修改记录  :2011年1月21日   鲁婷  创建
*   1.修改日期 : 2012年11月29日
*     修改作者 : z00212992
*     修改记录 : 增加ADQ初始化
*****************************************************************************/
int IPF_Init(void)
{
    int s32Ret = 0;

    /* IPF内存配置越界检查 */
    if(IPF_MEM_USED_SIZE > IPF_AXI_MEM_SIZE)
    {
        IPF_PRINT_ERROR("memory overstep the boundary\n");
        return IPF_ERROR;
    }


    hisi_io_memset((BSP_VOID*)&g_stIpfCtx, 0x0, sizeof(IPF_CONTEXT_S));

    IPF_ULBD_MEM_ADDR = HISI_VA_ADDRESS(IPF_AXI_MEM_ADDR);

    if (0 == (IPF_REGBASE_ADR = (unsigned long)ioremap(REG_BASE_IPF,REG_IPF_IOSIZE))){
        BUG_ON(1);
        return IPF_ERROR;
    }

    /* 为上行BD、RD描述符分配一段连续的物理地址 */
    g_stIpfUl.pstIpfBDQ = (IPF_BD_DESC_S*)IPF_ULBD_MEM_ADDR;
    g_stIpfUl.pstIpfRDQ = (IPF_RD_DESC_S*)IPF_ULRD_MEM_ADDR;

    /* 为上行AD描述符分配一段连续内存(首地址8字节对齐)*/
    g_stIpfUl.pstIpfADQ0 = (IPF_AD_DESC_S*)IPF_ULAD0_MEM_ADDR;
    g_stIpfUl.pstIpfADQ1 = (IPF_AD_DESC_S*)IPF_ULAD1_MEM_ADDR;

    /* 为下行BD、RD描述符分配一段连续的物理地址 */
    g_stIpfDl.pstIpfBDQ = (IPF_BD_DESC_S*)IPF_DLBD_MEM_ADDR;
    g_stIpfDl.pstIpfRDQ = (IPF_RD_DESC_S*)IPF_DLRD_MEM_ADDR;

    /* 为下行AD描述符分配一段连续内存(首地址8字节对齐)*/
    g_stIpfDl.pstIpfADQ0 = (IPF_AD_DESC_S*)IPF_DLAD0_MEM_ADDR;
    g_stIpfDl.pstIpfADQ1 = (IPF_AD_DESC_S*)IPF_DLAD1_MEM_ADDR;

    /* 为下行CD描述符分配一段连续的物理地址 */
    g_stIpfDl.pstIpfCDQ = (IPF_CD_DESC_S*)IPF_DLCD_MEM_ADDR;

    /* 记录IPF上行空闲BD个数 */
    g_stIpfUl.pu32IdleBd = (unsigned int*)IPF_ULBD_IDLENUM_ADDR;

#ifdef __BSP_IPF_DEBUG__
    /* 记录IPF debug信息 */
    g_stIPFDebugInfo = (IPF_DEBUG_INFO_S*)IPF_DEBUG_INFO_ADDR;

    /* 记录IPF 下行CDdebug信息 */
    g_stIpfDl.pstIpfDebugCDQ = (IPF_CD_DESC_S*)IPF_DEBUG_DLCD_ADDR;
#endif

    /* 记录IPF 下行CD读写指针 */
    g_stIpfDl.u32IpfCdRptr = (unsigned int*)IPF_DLCD_PTR_ADDR;
    g_stIpfDl.u32IpfCdWptr = (unsigned int*)(IPF_DLCD_PTR_ADDR+4);

    /* 挂接IPF中断 */
    IPF_Int_Connect();

    /* 注册IPF设备 */
    s32Ret = platform_device_register(&ipf_pfdev);
    if(s32Ret)
    {
        IPF_PRINT_ERROR("ipf device register fail\n");
        return s32Ret;
    }

    /* 注册IPF驱动 */
    s32Ret = platform_driver_register(&ipf_pfdrv);
    if(s32Ret)
    {
        platform_device_unregister(&ipf_pfdev);
        IPF_PRINT_ERROR("ipf driver register fail\n");
        return s32Ret;
    }

    ipf_peri_ctrl_base = (unsigned long)HISI_VA_ADDRESS(SOC_PERI_SCTRL_BASE_ADDR);
	if (!ipf_peri_ctrl_base)
	{
        IPF_PRINT_ERROR("unable to ioremap ipf peri ctrl\n");
	}

    /* 打开IPF hclk时钟、axi总线时钟 */
    IPF_REG_WRITE(SOC_PERI_SCTRL_SC_PERIPH_CLKEN2_ADDR(ipf_peri_ctrl_base), \
                (0x1 << SOC_PERI_SCTRL_SC_PERIPH_CLKEN2_periph_clken2_ipf_acpu_START));

    /* 等待另外一个core ipf初始化同步完成 */
    s32Ret = BSP_SYNC_Wait(SYNC_MODULE_IPF, 5000);
    if(s32Ret != BSP_OK)
    {
        IPF_PRINT_ERROR("BSP_SYNC_Wait timeout\n");
        return IPF_ERROR;
    }

    /* IPF初始化完成 */
    g_stIpfCtx.isInit = BSP_TRUE;


    IPF_PRINT_ERROR("success\n");
    return IPF_SUCCESS;
}
/*****************************************************************************
 函 数 名  : drv_hifi_load_sec
 功能描述  : Hifi按每段加载到内存
 输入参数  : img_head 镜像头指针
             img_buf 镜像读到内存的指针
             share_mem 存放非单次加载段信息的内存
 输出参数  : 无
 返 回 值  : int
             成功返回 0,失败返回 -1
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2012年8月30日
    作    者   : 刘慈红 lKF71598
    修改内容   : 新生成函数

*****************************************************************************/
int drv_hifi_load_sec(void *img_buf, unsigned int* share_mem)
{
    struct drv_hifi_sec_load_info *sec_info;
    struct drv_hifi_image_head    *head;
    struct drv_hifi_sec_addr      *dynamic_sec;
    unsigned long   iviraddr     = 0;
    unsigned long   iviraddr_src = 0;

    SOC_PERI_SCTRL_SC_DSP_SUBSYS_CTRL0_UNION runstall_val;

    unsigned int  dynamic_sec_num = 0;
    unsigned long sec_data_num    = 0;

    unsigned int i = 0;
    unsigned long sctrl_off = (unsigned long)HISI_VA_ADDRESS(SOC_PERI_SCTRL_BASE_ADDR);

    int ret;

    unsigned long share_mem_base_addr = HIFI_SHARE_ADDR_BASE;
    unsigned long data_addr_offset = sizeof(struct drv_hifi_sec_addr) * HIFI_DYNAMIC_SEC_MAX_NUM + sizeof(unsigned int) * 2;

    if (NULL == img_buf) {
        printk(KERN_INFO"drv_hifi_load_sec: img_buf is NULL.\n");
    	return BSP_RESET_ERROR;
    }

    head = (struct drv_hifi_image_head *)img_buf;

    printk("drv_hifi_load_sec: sections_num = %d, image_size = %u.\n",\
                head->sections_num,head->image_size);

    /* initial share memery */
    drv_hifi_init_mem(share_mem);

    drv_hifi_power_up();

    sec_info = (struct drv_hifi_sec_load_info*)share_mem;

    for (i = 0; i < head->sections_num; i++) {
        printk("drv_hifi_load_sec:head->sections_num = %d, i = %d.\n",head->sections_num,i);

        printk("drv_hifi_load_sec:des_addr = 0x%x, load_attib = %d, size = %u, sn = %d, src_offset = %u, type = %d\n", \
                          head->sections[i].des_addr,\
                          head->sections[i].load_attib,\
                          head->sections[i].size,\
                          head->sections[i].sn,\
                          head->sections[i].src_offset,\
                          head->sections[i].type);

        /* check the sections */
        ret = drv_hifi_check_sections(head, &(head->sections[i]));
        if (ret != 0) {
        	(void)printk("drv_hifi_load_sec:Invalid hifi section.\n");
            return BSP_RESET_ERROR;
        }

        /*如果段的目的地址是在0xC0000000到0xEFFFFFFF,则进行hifi虚实地址转换*/
        drv_hifi_phy2virt((unsigned int*)(&(head->sections[i].des_addr)));

        iviraddr = (unsigned long)(ioremap_wc((head->sections[i].des_addr),head->sections[i].size));
        printk("drv_hifi_load_sec00:iviraddr is 0x%p, phy addr is 0x%p.\n",(void*)iviraddr, (void*)head->sections[i].des_addr);
        if ((unsigned char)DRV_HIFI_IMAGE_SEC_LOAD_STATIC == head->sections[i].load_attib) {

            /* copy the sections */
            hisi_io_memcpy((void*)iviraddr,
                   (void*)((char*)head + head->sections[i].src_offset),
                   head->sections[i].size);

        } else if ((unsigned char)DRV_HIFI_IMAGE_SEC_LOAD_DYNAMIC == head->sections[i].load_attib) {

            dynamic_sec = &(sec_info->sec_addr_info[dynamic_sec_num]);
            printk("drv_hifi_load_sec02:dynamic step1, head = 0x%p dynamic_sec = 0x%p\n", (void*)head,  (void*)dynamic_sec);
            /* copy the sections */
            memcpy_local((void*)iviraddr,
                       (void*)((char*)head + head->sections[i].src_offset),
                       head->sections[i].size);
            printk("drv_hifi_load_sec02:dynamic step2\n");
            /* 填充段信息头 */
            dynamic_sec->sec_source_addr
                = (unsigned long)(&(sec_info->sec_data[sec_data_num]));
            dynamic_sec->sec_length    = head->sections[i].size;
            dynamic_sec->sec_dest_addr = head->sections[i].des_addr;

            printk("drv_hifi_load_sec02:dynamic step3\n");
            /* 拷贝段数据到共享内存 */
            iviraddr_src = dynamic_sec->sec_source_addr;
            printk("drv_hifi_load_sec02:iviraddr is 0x%p phy addr is 0x%p.\n",(void*)iviraddr_src, (void*)dynamic_sec->sec_source_addr);
            hisi_io_memcpy((void*)iviraddr_src,
               (void*)((char*)head + head->sections[i].src_offset),
                head->sections[i].size);

            /*保存share_mem的段数据源地址的物理地址,供mcu使用加载hifi*/
            dynamic_sec->sec_source_addr = share_mem_base_addr + data_addr_offset;
            data_addr_offset += head->sections[i].size;
            /* 更新段数据地址 */
            sec_data_num += head->sections[i].size;

            /* 更新非单次加载段的个数 */
            dynamic_sec_num++;

        } else if ((unsigned char)DRV_HIFI_IMAGE_SEC_UNLOAD == head->sections[i].load_attib) {

            /* 不需要加载的段,填充Hifi邮箱地址信息 */
            drv_hifi_fill_mb_info(iviraddr);

            printk("drv_hifi_load_sec:hifi unload sections.\n");
        } else {
            /*just for pclint*/
        }
        iounmap((void*)iviraddr);
    }

    /* 填充段信息头,非单次加载段的个数 */
    sec_info->sec_num = dynamic_sec_num;

    /*配置系统控制器拉高HiFi的输入信号RunStall*/
    runstall_val.value             = 0x0;
    runstall_val.reg.hifi_runstall = 0x0;

    writel(runstall_val.value, (void __iomem *)SOC_PERI_SCTRL_SC_DSP_SUBSYS_CTRL0_ADDR(sctrl_off));
    return OK;

}