/* ********************************************************************************************************* * clk_init * *Description: clock management initialise. * *Arguments : none * *Return : result * 0, initialise successed; * -1, initialise failed; * *Notes : * ********************************************************************************************************* */ int clk_init(void) { __s32 i, tmpFreq; struct clk *tmpSclk; char *script_base = (char *)(PAGE_OFFSET + 0x3000000); CCU_DBG("aw clock manager init!\n"); //initialise clock controller unit if(AW_CCU_ERR_NONE != aw_ccu_init()) { CCU_ERR("csp ccmu initial failed!\n"); return -1; } //clear the data structure SysClkCnt = 0; memset((void *)&ccu_sys_clk, 0, sizeof(ccu_sys_clk)); ModClkCnt = 0; memset((void *)&ccu_mod_clk, 0, sizeof(ccu_mod_clk)); //get system clock information SysClkCnt = aw_ccu_get_sys_clk_cnt(); if(SysClkCnt > MAX_SYSTEM_CLK_CNT) { CCU_ERR("system clock count define (%d) is invalid! actule is:%d\n", MAX_SYSTEM_CLK_CNT, SysClkCnt); return -1; } for(i=0; i<SysClkCnt; i++) { ccu_sys_clk[i].clk = aw_ccu_get_sys_clk((__aw_ccu_sys_clk_e)i); if(ccu_sys_clk[i].clk) { tmpSclk = &ccu_sys_clk[ccu_sys_clk[i].clk->parent]; ccu_sys_clk[i].parent = tmpSclk; ccu_sys_clk[i].set_clk = &aw_ccu_set_sys_clk; ccu_sys_clk[i].get_clk = (__aw_ccu_clk_t * (*)(__s32))&aw_ccu_get_sys_clk; ccu_sys_clk[i].hash = ccu_clk_calc_hash(ccu_sys_clk[i].clk->name); if(ccu_sys_clk[i].clk->onoff == AW_CCU_CLK_ON) { tmpSclk->usr_cnt++; } } } //get module clock information ModClkCnt = aw_ccu_get_mod_clk_cnt(); if(ModClkCnt > MAX_MODULE_CLK_CNT) { CCU_ERR("module clock count define (%d) is invalid! actule is:%d\n", MAX_MODULE_CLK_CNT, ModClkCnt); return -1; } for(i=0; i<ModClkCnt; i++) { ccu_mod_clk[i].clk = aw_ccu_get_mod_clk((__aw_ccu_sys_clk_e)i); if(ccu_mod_clk[i].clk) { tmpSclk = &ccu_sys_clk[ccu_mod_clk[i].clk->parent]; ccu_mod_clk[i].parent = tmpSclk; ccu_mod_clk[i].set_clk = &aw_ccu_set_mod_clk; ccu_mod_clk[i].get_clk = (__aw_ccu_clk_t * (*)(__s32))&aw_ccu_get_mod_clk; ccu_mod_clk[i].hash = ccu_clk_calc_hash(ccu_mod_clk[i].clk->name); if(ccu_mod_clk[i].clk->onoff == AW_CCU_CLK_ON) { tmpSclk->usr_cnt++; } if(tmpSclk->child) { ccu_mod_clk[i].right = tmpSclk->child; tmpSclk->child->left = &ccu_mod_clk[i]; } tmpSclk->child = &ccu_mod_clk[i]; } } /* enable pll for use, it need be modified to dynamic */ tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL2]; tmpSclk->clk->onoff = AW_CCU_CLK_ON; tmpSclk->set_clk(tmpSclk->clk); tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL3]; tmpSclk->clk->onoff = AW_CCU_CLK_ON; tmpSclk->set_clk(tmpSclk->clk); /* init pll4 frequency */ if((MAGIC_VER_C == sw_get_ic_ver()) && USE_PLL6M_REPLACE_PLL4) { tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL4]; tmpSclk->clk->onoff = AW_CCU_CLK_OFF; tmpSclk->set_clk(tmpSclk->clk); } else { tmpFreq = sw_cfg_get_int(script_base, "target", "pll4_freq"); if (tmpFreq == -1) { /* try to get pll4 frequency failed, set to default value */ CCU_ERR("try to parse pll4 frequency from script faild!\n"); tmpFreq = 960; } else { /* check if the value is valid */ if ((tmpFreq < 120) || (tmpFreq > 1200)) { /* pll4 frequency is invalid, set to default value */ CCU_ERR("pll4 frequency config is invalid!\n"); tmpFreq = 960; } CCU_DBG("pll4 frequency is configed to %dMhz!\n", tmpFreq); } tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL4]; tmpSclk->clk->rate = tmpFreq * 1000000; tmpSclk->set_clk(tmpSclk->clk); tmpSclk->clk->onoff = AW_CCU_CLK_ON; tmpSclk->set_clk(tmpSclk->clk); } /* init pll6 frequency */ tmpFreq = sw_cfg_get_int(script_base, "target", "pll6_freq"); if (tmpFreq == -1) { /* try to get pll6 frequency failed, set to default value */ CCU_ERR("try to parse pll6 frequency from script faild!\n"); tmpFreq = 600; } else { /* check if the value is valid */ if ((tmpFreq < 120) || (tmpFreq > 2000)) { /* pll6 frequency is invalid, set to default value */ CCU_ERR("pll6 frequency config is invalid!\n"); tmpFreq = 600; } CCU_DBG("pll6 frequency is configed to %dMhz!\n", tmpFreq); } tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL6]; tmpSclk->clk->rate = tmpFreq * 1000000; tmpSclk->set_clk(tmpSclk->clk); tmpSclk->clk->onoff = AW_CCU_CLK_ON; tmpSclk->set_clk(tmpSclk->clk); tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL6M]; if((tmpFreq/100)*100 == tmpFreq) { /* set cloce to 100Mhz */ tmpSclk->clk->rate = 100 * 1000000; } else { /* not divide the clock */ tmpSclk->clk->rate = (tmpFreq/6) * 1000000; } tmpSclk->set_clk(tmpSclk->clk); tmpSclk->clk->onoff = AW_CCU_CLK_ON; tmpSclk->set_clk(tmpSclk->clk); tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL62]; tmpSclk->clk->rate = (tmpFreq/2) * 1000000; tmpSclk->set_clk(tmpSclk->clk); tmpSclk->clk->onoff = AW_CCU_CLK_ON; tmpSclk->set_clk(tmpSclk->clk); tmpSclk = &ccu_sys_clk[AW_SYS_CLK_PLL7]; tmpSclk->clk->onoff = AW_CCU_CLK_ON; tmpSclk->set_clk(tmpSclk->clk); tmpFreq = sw_cfg_get_int(script_base, "target", "apb_freq"); if (tmpFreq == -1) { /* try to get apb frequency failed, set to default value */ CCU_ERR("try to parse apb frequency from script faild!\n"); tmpFreq = 24; } else { /* check if the value is valid */ if ((tmpFreq < 6) || (tmpFreq > 120)) { /* apb frequency is invalid, set to default value */ CCU_ERR("apb frequency config is invalid!\n"); tmpFreq = 24; } CCU_DBG("apb frequency is configed to %dMhz!\n", tmpFreq); } tmpSclk = clk_get(NULL, "apb1"); if(tmpSclk) { struct clk *tmpClk; if(tmpFreq == 24) { /* config apb clock source to OSC24M */ tmpClk = clk_get(NULL, "hosc"); if(tmpClk) { clk_set_parent(tmpSclk, tmpClk); clk_set_rate(tmpSclk, tmpFreq*1000000); } else { CCU_ERR("try to get hosc clock handle failed!\n"); } } else { /* config apb clock source to PLL6 */ tmpClk = clk_get(NULL, "sata_pll_2"); if(tmpClk) { clk_set_rate(tmpSclk, 1000000); clk_set_parent(tmpSclk, tmpClk); clk_set_rate(tmpSclk, tmpFreq*1000000); } else { CCU_ERR("try to get hosc clock handle failed!\n"); } } } else { CCU_ERR("try to get apb1 clock handle failed!\n"); } return 0; }