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); }
/***************************************************************************** * 函 数 名 : 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; }
/***************************************************************************** * 函 数 名 : 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; }