/* * Copyright (c) 2007-2017 Allwinnertech Co., Ltd. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include "pm_i.h" /*#define CHECK_RESTORE_STATUS*/ static __ccmu_reg_list_t *CmuReg; /* ********************************************************************************************************* * mem_clk_init * *Description: ccu init for platform mem, after switch mmu state, u need to re init. * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __ccmu_reg_list_t *mem_clk_init(__u32 mmu_flag) { if (1 == mmu_flag) { CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); } else { CmuReg = (__ccmu_reg_list_t *) (AW_CCM_BASE); } return CmuReg; } /* ********************************************************************************************************* * mem_get_ba * *Description: get ccu mod base. * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __ccmu_reg_list_t *mem_get_ba(void) { return CmuReg; } #if defined(CONFIG_ARCH_SUN8I) || \ defined(CONFIG_ARCH_SUN50IW1P1) || \ defined(CONFIG_ARCH_SUN50IW2P1) || \ defined(CONFIG_ARCH_SUN50IW3P1) || \ defined(CONFIG_ARCH_SUN50IW6P1) #ifdef CONFIG_ARCH_SUN8IW17P1 /* ********************************************************************************************************* * mem_clk_save * *Description: save ccu for platform mem * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __s32 mem_clk_save(struct clk_state *ccm_reg) { return 0; } /* ********************************************************************************************************* * mem_clk_exit * *Description: restore ccu for platform mem * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __s32 mem_clk_restore(struct clk_state *ccm_reg) { return 0; } /* ********************************************************************************************************* * mem_clk_setdiv * * Description: set div ratio * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_setdiv(struct clk_div_t *clk_div) { return 0; } /* ********************************************************************************************************* * mem_clk_getdiv * * Description: * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_getdiv(struct clk_div_t *clk_div) { return 0; } /* ********************************************************************************************************* * mem_clk_set_pll_factor * * Description: set pll factor, target cpu freq is ?M hz * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_set_pll_factor(struct pll_factor_t *pll_factor) { return 0; } /* ********************************************************************************************************* * mem_clk_get_pll_factor * * Description: get pll factor * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_get_pll_factor(struct pll_factor_t *pll_factor) { return 0; } /* ********************************************************************************************************* * mem_clk_set_misc * * Description: set clk_misc * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_set_misc(struct clk_misc_t *clk_misc) { return 0; } /* ********************************************************************************************************* * mem_clk_get_misc * * Description: get clk_misc * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_get_misc(struct clk_misc_t *clk_misc) { return 0; } /* ********************************************************************************************************* * mem_clk_get_cpu_freq * * Description: get current cpu freq * * Arguments : none * * Returns : cpu freq. ********************************************************************************************************* */ __u32 mem_clk_get_cpu_freq(void) { return 0; } #else static __ccmu_pll1_reg0000_t CmuReg_Pll1Ctl_tmp; static __ccmu_sysclk_ratio_reg0050_t CmuReg_SysClkDiv_tmp; #ifdef CONFIG_ARCH_SUN8IW8P1 #define PIO_INT_DEB_REG (AW_GPIO_BASE_PA + 0x258) static __u32 pio_int_deb_back; void mem_pio_clk_src_init(void) { pio_int_deb_back = *(__u32 *) PIO_INT_DEB_REG; *(__u32 *) PIO_INT_DEB_REG = pio_int_deb_back & (~1); } void mem_pio_clk_src_exit(void) { *(__u32 *) PIO_INT_DEB_REG = pio_int_deb_back; } #endif /* ********************************************************************************************************* * mem_clk_save * *Description: save ccu for platform mem * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __s32 mem_clk_save(struct clk_state *pclk_state) { pclk_state->CmuReg = CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); /*backup clk src and ldo */ pclk_state->ccu_reg_back[0] = *(volatile __u32 *)&CmuReg->SysClkDiv; pclk_state->ccu_reg_back[1] = *(volatile __u32 *)&CmuReg->Apb2Div; pclk_state->ccu_reg_back[2] = *(volatile __u32 *)&CmuReg->Ahb1Div; return 0; } /* ********************************************************************************************************* * mem_clk_exit * *Description: restore ccu for platform mem * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __s32 mem_clk_restore(struct clk_state *pclk_state) { /* initialise the CCU io base */ CmuReg = pclk_state->CmuReg; /* * consider: pll6 already configed. * config the bus to orginal status */ /*restore clk src */ *(volatile __u32 *)&CmuReg->SysClkDiv = pclk_state->ccu_reg_back[0]; *(volatile __u32 *)&CmuReg->Apb2Div = pclk_state->ccu_reg_back[1]; *(volatile __u32 *)&CmuReg->Ahb1Div = pclk_state->ccu_reg_back[2]; return 0; } /* ********************************************************************************************************* * mem_clk_setdiv * * Description: set div ratio * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_setdiv(struct clk_div_t *clk_div) { if (!clk_div) { return -1; } CmuReg = (__ccmu_reg_list_t *) (AW_CCM_BASE); /*1st: set axi ratio */ CmuReg_SysClkDiv_tmp.dwval = CmuReg->SysClkDiv.dwval; CmuReg_SysClkDiv_tmp.bits.AXIClkDiv = clk_div->axi_div; CmuReg->SysClkDiv.dwval = CmuReg_SysClkDiv_tmp.dwval; /*set ahb1/apb1 clock divide ratio */ /*first, config ratio; */ *(volatile __u32 *)(&CmuReg->Ahb1Div) = (((clk_div->ahb_apb_div) & (~0x3000)) | (0x1000)); #if defined(CONFIG_ARCH_SUN8IW10P1) || defined(CONFIG_ARCH_SUN8IW11P1) change_runtime_env(); delay_us(5); #else udelay(5); #endif /*sec, config src. */ *(volatile __u32 *)(&CmuReg->Ahb1Div) = (clk_div->ahb_apb_div); #if defined(CONFIG_ARCH_SUN8IW10P1) || defined(CONFIG_ARCH_SUN8IW11P1) delay_us(5); #else udelay(5); #endif /*notice: pll6 is enabled by cpus. */ /*the relationship between pll6 & mbus & dram? */ return 0; } /* ********************************************************************************************************* * mem_clk_getdiv * * Description: * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_getdiv(struct clk_div_t *clk_div) { if (!clk_div) { return -1; } CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); CmuReg_SysClkDiv_tmp.dwval = CmuReg->SysClkDiv.dwval; clk_div->axi_div = CmuReg_SysClkDiv_tmp.bits.AXIClkDiv; clk_div->ahb_apb_div = *(volatile __u32 *)(&CmuReg->Ahb1Div); return 0; } /* ********************************************************************************************************* * mem_clk_set_pll_factor * * Description: set pll factor, target cpu freq is ?M hz * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_set_pll_factor(struct pll_factor_t *pll_factor) { CmuReg = (__ccmu_reg_list_t *) (AW_CCM_BASE); CmuReg_Pll1Ctl_tmp.dwval = CmuReg->Pll1Ctl.dwval; /*set pll factor: notice: when raise freq, N must be the last to set */ #if defined(CONFIG_ARCH_SUN8IW3P1) || defined(CONFIG_ARCH_SUN8IW5P1) || defined(CONFIG_ARCH_SUN8IW6P1) CmuReg_Pll1Ctl_tmp.bits.FactorP = pll_factor->FactorP; #endif CmuReg_Pll1Ctl_tmp.bits.FactorM = pll_factor->FactorM; #ifndef CONFIG_ARCH_SUN8IW6P1 CmuReg_Pll1Ctl_tmp.bits.FactorK = pll_factor->FactorK; #endif CmuReg_Pll1Ctl_tmp.bits.FactorN = pll_factor->FactorN; CmuReg->Pll1Ctl.dwval = CmuReg_Pll1Ctl_tmp.dwval; /*need delay? */ /*busy_waiting(); */ return 0; } /* ********************************************************************************************************* * mem_clk_get_pll_factor * * Description: get pll factor * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_get_pll_factor(struct pll_factor_t *pll_factor) { CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); CmuReg_Pll1Ctl_tmp.dwval = CmuReg->Pll1Ctl.dwval; pll_factor->FactorN = CmuReg_Pll1Ctl_tmp.bits.FactorN; #ifndef CONFIG_ARCH_SUN8IW6P1 pll_factor->FactorK = CmuReg_Pll1Ctl_tmp.bits.FactorK; #endif pll_factor->FactorM = CmuReg_Pll1Ctl_tmp.bits.FactorM; #if defined(CONFIG_ARCH_SUN8IW3P1) || defined(CONFIG_ARCH_SUN8IW5P1) || defined(CONFIG_ARCH_SUN8IW6P1) pll_factor->FactorP = CmuReg_Pll1Ctl_tmp.bits.FactorP; #endif /*busy_waiting(); */ return 0; } /* ********************************************************************************************************* * mem_clk_set_misc * * Description: set clk_misc * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_set_misc(struct clk_misc_t *clk_misc) { CmuReg = (__ccmu_reg_list_t *) (AW_CCM_BASE); CmuReg->PllxBias[0] = clk_misc->pll1_bias; /*pll_periph's bias do not need config? */ CmuReg->Pll1Tun = clk_misc->pll1_tun; #ifdef CONFIG_ARCH_SUN8IW5P1 CmuReg->PllVedioBias = clk_misc->PllVedioBias; /*0x228, pll vedio bias reg */ CmuReg->PllVeBias = clk_misc->PllVeBias; /*0x22c, pll ve bias reg */ CmuReg->PllVedioPattern = clk_misc->PllVedioPattern; /*0x288, pll vedio pattern reg */ CmuReg->PllVePattern = clk_misc->PllVePattern; /*0x28c, pll ve pattern reg */ CmuReg->Pll3Ctl = clk_misc->Pll3Ctl; /*0x10, vedio */ CmuReg->Pll4Ctl = clk_misc->Pll4Ctl; /*0x18, ve */ #endif #ifdef CONFIG_ARCH_SUN8IW6P1 CmuReg->PllC1CpuxBias = clk_misc->Pll_C1_Bias; CmuReg->PllC1Tun = clk_misc->PllC1Tun; CmuReg->PllC1Ctl = clk_misc->PllC1Ctl; CmuReg->PllVideo0Bias = clk_misc->PllVideo0Bias; /*0x228, pll vedio bias reg */ CmuReg->PllVeBias = clk_misc->PllVeBias; /*0x22c, pll ve bias reg */ CmuReg->PllPeriphBias = clk_misc->PllPeriphBias; /*0x234, pll periph bias */ CmuReg->PllVideo0Reg0Pattern = clk_misc->PllVideo0Reg0Pattern; /*0x288, pll vedio pattern reg */ CmuReg->PllVideo0Reg1Pattern = clk_misc->PllVideo0Reg1Pattern; /*0x288, pll vedio pattern reg */ CmuReg->Pll3Ctl = clk_misc->Pll3Ctl; /*0x10, vedio */ CmuReg->Pll4Ctl = clk_misc->Pll4Ctl; /*0x18, ve */ CmuReg->Pll6Ctl = clk_misc->Pll6Ctl; /*0x28, pll periph ctrl */ *(volatile __u32 *)(&CmuReg->Apb2Div) = clk_misc->Apb2Div; /*0x58, apb2 divide ratio */ #endif /*config axi ratio to 1+1 = 2; */ /*axi can not exceed 300M; */ CmuReg_SysClkDiv_tmp.dwval = CmuReg->SysClkDiv.dwval; CmuReg_SysClkDiv_tmp.bits.AXIClkDiv = 2; CmuReg->SysClkDiv.dwval = CmuReg_SysClkDiv_tmp.dwval; CmuReg_SysClkDiv_tmp.bits.AXIClkDiv = 1; CmuReg->SysClkDiv.dwval = CmuReg_SysClkDiv_tmp.dwval; return 0; } /* ********************************************************************************************************* * mem_clk_get_misc * * Description: get clk_misc * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_get_misc(struct clk_misc_t *clk_misc) { CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); clk_misc->pll1_bias = CmuReg->PllxBias[0]; clk_misc->pll1_tun = CmuReg->Pll1Tun; #ifdef CONFIG_ARCH_SUN8IW6P1 clk_misc->Pll_C1_Bias = CmuReg->PllC1CpuxBias; clk_misc->PllC1Tun = CmuReg->PllC1Tun; clk_misc->PllC1Ctl = CmuReg->PllC1Ctl; clk_misc->PllVideo0Bias = CmuReg->PllVideo0Bias; /*0x228, pll video bias reg */ clk_misc->PllVeBias = CmuReg->PllVeBias; /*0x22c, pll ve bias reg */ clk_misc->PllVideo0Reg0Pattern = CmuReg->PllVideo0Reg0Pattern; /*0x288, pll video pattern reg */ clk_misc->PllVideo0Reg1Pattern = CmuReg->PllVideo0Reg1Pattern; /*0x288, pll video pattern reg */ clk_misc->Pll3Ctl = CmuReg->Pll3Ctl; /*0x10, video */ clk_misc->Pll4Ctl = CmuReg->Pll4Ctl; /*0x18, ve */ clk_misc->PllPeriphBias = CmuReg->PllPeriphBias; /*0x234, pll periph bias */ clk_misc->Pll6Ctl = CmuReg->Pll6Ctl; /*0x28, pll periph ctrl */ clk_misc->Apb2Div = *(volatile __u32 *)(&CmuReg->Apb2Div); /*0x58, apb2 divide ratio */ #endif #ifdef CONFIG_ARCH_SUN8IW5P1 clk_misc->PllVedioBias = CmuReg->PllVedioBias; /*0x228, pll vedio bias reg */ clk_misc->PllVeBias = CmuReg->PllVeBias; /*0x22c, pll ve bias reg */ clk_misc->PllVedioPattern = CmuReg->PllVedioPattern; /*0x288, pll vedio pattern reg */ clk_misc->PllVePattern = CmuReg->PllVePattern; /*0x28c, pll ve pattern reg */ clk_misc->Pll3Ctl = CmuReg->Pll3Ctl; /*0x10, vedio */ clk_misc->Pll4Ctl = CmuReg->Pll4Ctl; /*0x18, ve */ #endif /*busy_waiting(); */ return 0; } #ifdef CONFIG_ARCH_SUN8IW6P1 /* ********************************************************************************************************* * mem_clk_get_cpu_freq * * Description: get current cpu freq * * Arguments : none * * Returns : cpu freq. ********************************************************************************************************* */ __u32 mem_clk_get_cpu_freq(void) { __u32 FactorN = 1; __u32 FactorK = 1; __u32 FactorM = 1; __u32 FactorP = 1; __u32 reg_val = 0; __u32 cpu_freq = 0; CmuReg_SysClkDiv_tmp.dwval = CmuReg->SysClkDiv.dwval; /*get runtime freq: clk src + divider ratio */ /*src selection */ reg_val = CmuReg_SysClkDiv_tmp.bits.CpuClkSrc; if (0 == reg_val) { /*hosc, 24Mhz */ cpu_freq = 24000; /*unit is khz */ } else if (1 == reg_val) { CmuReg_Pll1Ctl_tmp.dwval = CmuReg->Pll1Ctl.dwval; FactorN = CmuReg_Pll1Ctl_tmp.bits.FactorN; FactorM = (CmuReg_Pll1Ctl_tmp.bits.FactorM) + 1; FactorP = (0 == CmuReg_Pll1Ctl_tmp.bits.FactorP) ? 1 : 4; cpu_freq = raw_lib_udiv(24000 * FactorN * FactorK, FactorP * FactorM); } /*printk("cpu_freq = dec(%d). \n", cpu_freq); */ /*busy_waiting(); */ return cpu_freq; } #elif defined(CONFIG_ARCH_SUN8IW10P1) __u32 mem_clk_get_cpu_freq(void) { __u32 FactorN = 1; __u32 FactorK = 1; __u32 FactorM = 1; __u32 FactorP = 1; __u32 reg_val = 0; __u32 cpu_freq = 0; CmuReg_SysClkDiv_tmp.dwval = CmuReg->SysClkDiv.dwval; /*get runtime freq: clk src + divider ratio */ /*src selection */ reg_val = CmuReg_SysClkDiv_tmp.bits.CpuClkSrc; if (0 == reg_val) { /*32khz osc */ cpu_freq = 32; } else if (1 == reg_val) { /*hosc, 26Mhz */ cpu_freq = 26000; /*unit is khz */ } else if (2 == reg_val || 3 == reg_val) { CmuReg_Pll1Ctl_tmp.dwval = CmuReg->Pll1Ctl.dwval; FactorN = CmuReg_Pll1Ctl_tmp.bits.FactorN + 1; FactorK = CmuReg_Pll1Ctl_tmp.bits.FactorK + 1; FactorM = CmuReg_Pll1Ctl_tmp.bits.FactorM + 1; FactorP = 1 << (CmuReg_Pll1Ctl_tmp.bits.FactorP); cpu_freq = raw_lib_udiv(24000 * FactorN * FactorK, FactorP * FactorM); } /*printk("cpu_freq = dec(%d). \n", cpu_freq); */ /*busy_waiting(); */ return cpu_freq; } #elif defined(CONFIG_ARCH_SUN8IW17P1) __u32 mem_clk_get_cpu_freq(void) { return 0; } #else __u32 mem_clk_get_cpu_freq(void) { __u32 FactorN = 1; __u32 FactorK = 1; __u32 FactorM = 1; __u32 FactorP = 1; __u32 reg_val = 0; __u32 cpu_freq = 0; CmuReg_SysClkDiv_tmp.dwval = CmuReg->SysClkDiv.dwval; /*get runtime freq: clk src + divider ratio */ /*src selection */ reg_val = CmuReg_SysClkDiv_tmp.bits.CpuClkSrc; if (0 == reg_val) { /*32khz osc */ cpu_freq = 32; } else if (1 == reg_val) { /*hosc, 24Mhz */ cpu_freq = 24000; /*unit is khz */ } else if (2 == reg_val || 3 == reg_val) { CmuReg_Pll1Ctl_tmp.dwval = CmuReg->Pll1Ctl.dwval; FactorN = CmuReg_Pll1Ctl_tmp.bits.FactorN + 1; FactorK = CmuReg_Pll1Ctl_tmp.bits.FactorK + 1; FactorM = CmuReg_Pll1Ctl_tmp.bits.FactorM + 1; #if defined(CONFIG_ARCH_SUN8IW3P1) || defined(CONFIG_ARCH_SUN8IW5P1) || defined(CONFIG_ARCH_SUN8IW11P1) FactorP = 1 << (CmuReg_Pll1Ctl_tmp.bits.FactorP); #endif cpu_freq = raw_lib_udiv(24000 * FactorN * FactorK, FactorP * FactorM); } /*printk("cpu_freq = dec(%d). \n", cpu_freq); */ /*busy_waiting(); */ return cpu_freq; } #endif #endif #endif #ifdef CONFIG_ARCH_SUN9IW1P1 static AXI0_CFG_REG_t CmuReg_Axi0_Cfg_tmp; static PLL_C0_CFG_REG_t CmuReg_Pll_C0_Cfg_tmp; static AXI1_CFG_REG_t CmuReg_Axi1_Cfg_tmp; static PLL_C1_CFG_REG_t CmuReg_Pll_C1_Cfg_tmp; static CPU_CLK_SRC_REG_t CmuReg_Cpu_Clk_Src_tmp; #define MCTL_COM_BASE 0xf1c62000 #define MC_RMCR (MCTL_COM_BASE + 0x10) #define MCTL_CTL_BASE 0xf1c63000 #define M0_UPD2 (MCTL_CTL_BASE + 0x1A8) #define MCTL_PHY_BASE 0xf1c65000 #define P0_ZQ0CR (MCTL_PHY_BASE + 0x240) /* ********************************************************************************************************* * setting_ahb0_para * *Description: setting ahb0 related para: dram phy update delay para. * the para is related with dram performance, so, after restore the ahb0 freq, * it is recommended to call this function. *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ static __s32 setting_ahb0_para(void) { __u32 reg_val = 0; __u32 zqcr_ch1 = 0; __u32 zqcr_ch0 = 0; #if 0 asm("dmb"); asm("isb"); /*save_pm_secure_mem_status(CLK_RESUME_START | 0xb); */ /*open protect registers */ reg_val = *(volatile __u32 *)(MC_RMCR); reg_val |= (0x1 << 3); *(volatile __u32 *)(MC_RMCR) = reg_val; asm("dmb"); asm("isb"); /*disable ZCAL of channel 0 */ zqcr_ch0 = *(volatile __u32 *)(P0_ZQ0CR); reg_val = (zqcr_ch0 & ~(0x7 << 11)); /*reg_val = (zqcr_ch0 | (0x7<<11)); */ *(volatile __u32 *)(P0_ZQ0CR) = reg_val; asm("dmb"); asm("isb"); /*disable ZCAL of channel 1 */ zqcr_ch1 = *(volatile __u32 *)(P0_ZQ0CR + 0x1000); /*reg_val = (zqcr_ch1 | (0x7<<11)); */ reg_val = (zqcr_ch1 & ~(0x7 << 11)); *(volatile __u32 *)(P0_ZQ0CR + 0x1000) = reg_val; asm("dmb"); asm("isb"); delay_us(50); reg_val = *(volatile __u32 *)(M0_UPD2); /*channel 0 */ reg_val &= ~(0xfff << 16); reg_val |= (0x40 << 16); /*correspond to AHB 60MHz, DRAM 800MHz, 0x10 margin */ *(volatile __u32 *)(M0_UPD2) = reg_val; asm("dmb"); asm("isb"); reg_val = *(volatile __u32 *)(M0_UPD2 + 0x1000); reg_val &= ~(0xfff << 16); reg_val |= (0x40 << 16); /*correspond to AHB 60MHz, DRAM 800MHz, 0x10 margin */ *(volatile __u32 *)(M0_UPD2 + 0x1000) = reg_val; asm("dmb"); asm("isb"); /*write back ZQCR value of channel 0 */ *(volatile __u32 *)(P0_ZQ0CR) = zqcr_ch0; asm("dmb"); asm("isb"); /*write back ZQCR value of channel 1 */ *(volatile __u32 *)(P0_ZQ0CR + 0x1000) = zqcr_ch1; asm("dmb"); asm("isb"); /*save_pm_secure_mem_status(CLK_RESUME_START | 0xe); */ /*close protect registers */ reg_val = *(volatile __u32 *)(MC_RMCR); reg_val &= ~(0x1 << 3); *(volatile __u32 *)(MC_RMCR) = reg_val; asm("dmb"); asm("isb"); delay_us(10); #endif return 0; } /* ********************************************************************************************************* * mem_clk_save * *Description: save ccu for platform mem * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __s32 mem_clk_save(struct clk_state *ccm_reg) { ccm_reg->ccm_reg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); ccm_reg->ccm_mod_reg = (__ccmu_mod_reg_list_t *) IO_ADDRESS(SUNXI_CCM_MOD_PBASE); /*donot need care pll1 & pll5 & pll6, it is dangerous to */ /*write the reg after enable the pllx. */ /*FIXME: which pllx is enabled when restore? */ /*dram need which before exit selfresh? */ /*ccm_reg->ccm_reg_backup.Pll_C0_Bias.dwval = ccm_reg->ccm_reg->Pll_C0_Bias.dwval ; */ ccm_reg->ccm_reg_backup.Pll_C1_Bias.dwval = ccm_reg->ccm_reg->Pll_C1_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_Audio_Bias.dwval = ccm_reg->ccm_reg->Pll_Audio_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_Periph1_Bias.dwval = ccm_reg->ccm_reg->Pll_Periph1_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_Ve_Bias.dwval = ccm_reg->ccm_reg->Pll_Ve_Bias.dwval; /*ccm_reg->ccm_reg_backup.Pll_Ddr_Bias.dwval = ccm_reg->ccm_reg->Pll_Ddr_Bias.dwval ; */ ccm_reg->ccm_reg_backup.Pll_Vedio1_Bias.dwval = ccm_reg->ccm_reg->Pll_Vedio1_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_Vedio2_Bias.dwval = ccm_reg->ccm_reg->Pll_Vedio2_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_Gpu_Bias.dwval = ccm_reg->ccm_reg->Pll_Gpu_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_De_Bias.dwval = ccm_reg->ccm_reg->Pll_De_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_Isp_Bias.dwval = ccm_reg->ccm_reg->Pll_Isp_Bias.dwval; ccm_reg->ccm_reg_backup.Pll_Periph2_Bias.dwval = ccm_reg->ccm_reg->Pll_Periph2_Bias.dwval; /*ccm_reg->ccm_reg_backup.Pll_C0_Tun.dwval = ccm_reg->ccm_reg->Pll_C0_Tun.dwval ; */ ccm_reg->ccm_reg_backup.Pll_C1_Tun.dwval = ccm_reg->ccm_reg->Pll_C1_Tun.dwval; ccm_reg->ccm_reg_backup.Pll_Audio_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_Audio_Pat_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Periph1_Pat_Cfg = ccm_reg->ccm_reg->Pll_Periph1_Pat_Cfg; ccm_reg->ccm_reg_backup.Pll_Ve_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_Ve_Pat_Cfg.dwval; /*ccm_reg->ccm_reg_backup.Pll_Ddr_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_Ddr_Pat_Cfg.dwval ; */ ccm_reg->ccm_reg_backup.Pll_Video1_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_Video1_Pat_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Video2_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_Video2_Pat_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Gpu_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_Gpu_Pat_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_De_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_De_Pat_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Isp_Pat_Cfg.dwval = ccm_reg->ccm_reg->Pll_Isp_Pat_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Periph2_Pat_Cfg = ccm_reg->ccm_reg->Pll_Periph2_Pat_Cfg; /*C0 */ ccm_reg->ccm_reg_backup.Pll_C1_Cfg.dwval = ccm_reg->ccm_reg->Pll_C1_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Audio_Cfg.dwval = ccm_reg->ccm_reg->Pll_Audio_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Periph1_Cfg.dwval = ccm_reg->ccm_reg->Pll_Periph1_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Ve_Cfg.dwval = ccm_reg->ccm_reg->Pll_Ve_Cfg.dwval; /*ccm_reg->ccm_reg_backup.Pll_Ddr_Cfg.dwval = ccm_reg->ccm_reg->Pll_Ddr_Cfg.dwval ; */ ccm_reg->ccm_reg_backup.Pll_Video1_Cfg.dwval = ccm_reg->ccm_reg->Pll_Video1_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Video2_Cfg.dwval = ccm_reg->ccm_reg->Pll_Video2_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Gpu_Cfg.dwval = ccm_reg->ccm_reg->Pll_Gpu_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_De_Cfg.dwval = ccm_reg->ccm_reg->Pll_De_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Isp_Cfg.dwval = ccm_reg->ccm_reg->Pll_Isp_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Periph2_Cfg.dwval = ccm_reg->ccm_reg->Pll_Periph2_Cfg.dwval; ccm_reg->ccm_reg_backup.Cpu_Clk_Src.dwval = ccm_reg->ccm_reg->Cpu_Clk_Src.dwval; ccm_reg->ccm_reg_backup.Axi0_Cfg.dwval = ccm_reg->ccm_reg->Axi0_Cfg.dwval; ccm_reg->ccm_reg_backup.Axi1_Cfg.dwval = ccm_reg->ccm_reg->Axi1_Cfg.dwval; /**/ ccm_reg->ccm_reg_backup.Ahb0_Cfg.dwval = ccm_reg->ccm_reg->Ahb0_Cfg.dwval; ccm_reg->ccm_reg_backup.Ahb1_Cfg.dwval = ccm_reg->ccm_reg->Ahb1_Cfg.dwval; ccm_reg->ccm_reg_backup.Ahb2_Cfg.dwval = ccm_reg->ccm_reg->Ahb2_Cfg.dwval; ccm_reg->ccm_reg_backup.Apb0_Cfg.dwval = ccm_reg->ccm_reg->Apb0_Cfg.dwval; ccm_reg->ccm_reg_backup.Apb1_Cfg.dwval = ccm_reg->ccm_reg->Apb1_Cfg.dwval; ccm_reg->ccm_reg_backup.Ats_Clk.dwval = ccm_reg->ccm_reg->Ats_Clk.dwval; ccm_reg->ccm_reg_backup.Trace_Clk.dwval = ccm_reg->ccm_reg->Trace_Clk.dwval; ccm_reg->ccm_reg_backup.Pll_Lock_Cfg.dwval = ccm_reg->ccm_reg->Pll_Lock_Cfg.dwval; ccm_reg->ccm_reg_backup.Pll_Lock_Cfg_1.dwval = ccm_reg->ccm_reg->Pll_Lock_Cfg_1.dwval; ccm_reg->ccm_reg_backup.Pll_Lock_Status.dwval = ccm_reg->ccm_reg->Pll_Lock_Status.dwval; ccm_reg->ccm_reg_backup.Clk_Outa.dwval = ccm_reg->ccm_reg->Clk_Outa.dwval; ccm_reg->ccm_reg_backup.Clk_Outb.dwval = ccm_reg->ccm_reg->Clk_Outb.dwval; /*backup cci400 + gtbus */ ccm_reg->ccm_reg_backup.Cci400_Cfg.dwval = ccm_reg->ccm_reg->Cci400_Cfg.dwval; ccm_reg->ccm_reg_backup.Gtclk_Cfg.dwval = ccm_reg->ccm_reg->Gtclk_Cfg.dwval; return 0; } /* ********************************************************************************************************* * mem_clk_exit * *Description: restore ccu for platform mem * *Arguments : none * *Return : result, * *Notes : * ********************************************************************************************************* */ __s32 mem_clk_restore(struct clk_state *ccm_reg) { /* restore pll para first. ** then, restore bus; ** reason: pll src need be ready before restore cci, gtbus, ahb... bus src. **/ /*save_pm_secure_mem_status(CLK_RESUME_START | 0x0); */ change_runtime_env(); /*first, sys related clk. */ /*ccm_reg->ccm_reg->Pll_C0_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_C0_Bias.dwval ; */ ccm_reg->ccm_reg->Pll_Audio_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_Audio_Bias.dwval; ccm_reg->ccm_reg->Pll_Periph1_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_Periph1_Bias.dwval; ccm_reg->ccm_reg->Pll_Ve_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_Ve_Bias.dwval; /*ccm_reg->ccm_reg->Pll_Ddr_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_Ddr_Bias.dwval ; */ ccm_reg->ccm_reg->Pll_Gpu_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_Gpu_Bias.dwval; ccm_reg->ccm_reg->Pll_De_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_De_Bias.dwval; ccm_reg->ccm_reg->Pll_Isp_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_Isp_Bias.dwval; ccm_reg->ccm_reg->Pll_Periph2_Bias.dwval = ccm_reg->ccm_reg_backup.Pll_Periph2_Bias.dwval; /*ccm_reg->ccm_reg->Pll_C0_Tun.dwval = ccm_reg->ccm_reg_backup.Pll_C0_Tun.dwval ; */ /*save_pm_secure_mem_status(CLK_RESUME_START | 0x2); */ ccm_reg->ccm_reg->Pll_Audio_Pat_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Audio_Pat_Cfg.dwval; ccm_reg->ccm_reg->Pll_Periph1_Pat_Cfg = ccm_reg->ccm_reg_backup.Pll_Periph1_Pat_Cfg; ccm_reg->ccm_reg->Pll_Ve_Pat_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Ve_Pat_Cfg.dwval; /*ccm_reg->ccm_reg->Pll_Ddr_Pat_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Ddr_Pat_Cfg.dwval ; */ ccm_reg->ccm_reg->Pll_Gpu_Pat_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Gpu_Pat_Cfg.dwval; ccm_reg->ccm_reg->Pll_De_Pat_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_De_Pat_Cfg.dwval; ccm_reg->ccm_reg->Pll_Isp_Pat_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Isp_Pat_Cfg.dwval; ccm_reg->ccm_reg->Pll_Periph2_Pat_Cfg = ccm_reg->ccm_reg_backup.Pll_Periph2_Pat_Cfg; /*save_pm_secure_mem_status(CLK_RESUME_START | 0x4); */ delay_us(10); ccm_reg->ccm_reg->Pll_Audio_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Audio_Cfg.dwval; delay_us(10); ccm_reg->ccm_reg->Pll_Periph1_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Periph1_Cfg.dwval; delay_us(10); ccm_reg->ccm_reg->Pll_Ve_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Ve_Cfg.dwval; delay_us(10); /*ccm_reg->ccm_reg->Pll_Ddr_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Ddr_Cfg.dwval ; */ ccm_reg->ccm_reg->Pll_Gpu_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Gpu_Cfg.dwval; delay_us(10); ccm_reg->ccm_reg->Pll_De_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_De_Cfg.dwval; delay_us(10); ccm_reg->ccm_reg->Pll_Isp_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Isp_Cfg.dwval; delay_us(10); /*busy_waiting(); */ /*config perihp1 freq -> 240M */ ccm_reg->ccm_reg->Pll_Periph2_Cfg.dwval = 0x80041400; /*24*20/2 = 240M; */ delay_us(10); /*save_pm_secure_mem_status(CLK_RESUME_START | 0x5); */ ccm_reg->ccm_reg->Cpu_Clk_Src.dwval = ccm_reg->ccm_reg_backup.Cpu_Clk_Src.dwval; delay_us(10); ccm_reg->ccm_reg->Axi0_Cfg.dwval = ccm_reg->ccm_reg_backup.Axi0_Cfg.dwval; delay_us(10); ccm_reg->ccm_reg->Axi1_Cfg.dwval = ccm_reg->ccm_reg_backup.Axi1_Cfg.dwval; delay_us(200); /*switch gtbus src: gtbus clk = 240M, at this time, ahb0 src is gtbus. */ ccm_reg->ccm_reg->Gtclk_Cfg.dwval = (0x3000000) & (ccm_reg->ccm_reg_backup.Gtclk_Cfg.dwval); delay_us(10); /*save_pm_secure_mem_status(CLK_RESUME_START | 0x6); */ /*config ahb0 divide ratio = 8, ahb0 freq = 240/8 = 30M. */ ccm_reg->ccm_reg->Ahb0_Cfg.dwval = (~0x3000000) & (ccm_reg->ccm_reg_backup.Ahb0_Cfg.dwval); delay_us(10); /*config ahb0 src. ahb0 freq = 960M/8 = 120M */ ccm_reg->ccm_reg->Ahb0_Cfg.dwval = ccm_reg->ccm_reg_backup.Ahb0_Cfg.dwval; delay_us(10); /*save_pm_secure_mem_status(CLK_RESUME_START | 0x7); */ /*config gtbus divide. gtbus clk = 240M /3 = 80M; */ ccm_reg->ccm_reg->Gtclk_Cfg.dwval = ccm_reg->ccm_reg_backup.Gtclk_Cfg.dwval; /*delay 10us */ delay_us(10); /*gtbus clk = 1.2G/3 = 400M */ ccm_reg->ccm_reg->Pll_Periph2_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Periph2_Cfg.dwval; delay_us(200); /*save_pm_secure_mem_status(CLK_RESUME_START | 0x8); */ ccm_reg->ccm_reg->Ahb1_Cfg.dwval = (~0x3000000) & (ccm_reg->ccm_reg_backup.Ahb1_Cfg.dwval); ccm_reg->ccm_reg->Ahb2_Cfg.dwval = (~0x3000000) & (ccm_reg->ccm_reg_backup.Ahb2_Cfg.dwval); ccm_reg->ccm_reg->Apb0_Cfg.dwval = (~0x3000000) & (ccm_reg->ccm_reg_backup.Apb0_Cfg.dwval); delay_us(10); ccm_reg->ccm_reg->Apb1_Cfg.dwval = (~0x3000000) & (ccm_reg->ccm_reg_backup.Apb1_Cfg.dwval); ccm_reg->ccm_reg->Cci400_Cfg.dwval = (~0x3000000) & (ccm_reg->ccm_reg_backup.Cci400_Cfg.dwval); delay_us(10); ccm_reg->ccm_reg->Ats_Clk.dwval = ccm_reg->ccm_reg_backup.Ats_Clk.dwval; ccm_reg->ccm_reg->Trace_Clk.dwval = ccm_reg->ccm_reg_backup.Trace_Clk.dwval; ccm_reg->ccm_reg->Pll_Lock_Cfg.dwval = ccm_reg->ccm_reg_backup.Pll_Lock_Cfg.dwval; ccm_reg->ccm_reg->Pll_Lock_Cfg_1.dwval = ccm_reg->ccm_reg_backup.Pll_Lock_Cfg_1.dwval; ccm_reg->ccm_reg->Pll_Lock_Status.dwval = ccm_reg->ccm_reg_backup.Pll_Lock_Status.dwval; ccm_reg->ccm_reg->Clk_Outa.dwval = ccm_reg->ccm_reg_backup.Clk_Outa.dwval; ccm_reg->ccm_reg->Clk_Outb.dwval = ccm_reg->ccm_reg_backup.Clk_Outb.dwval; /*config src. */ /*save_pm_secure_mem_status(CLK_RESUME_START | 0x8); */ ccm_reg->ccm_reg->Cci400_Cfg.dwval = ccm_reg->ccm_reg_backup.Cci400_Cfg.dwval; delay_us(10); ccm_reg->ccm_reg->Ahb1_Cfg.dwval = ccm_reg->ccm_reg_backup.Ahb1_Cfg.dwval; ccm_reg->ccm_reg->Ahb2_Cfg.dwval = ccm_reg->ccm_reg_backup.Ahb2_Cfg.dwval; ccm_reg->ccm_reg->Apb0_Cfg.dwval = ccm_reg->ccm_reg_backup.Apb0_Cfg.dwval; /*delay 10us */ delay_us(10); ccm_reg->ccm_reg->Apb1_Cfg.dwval = ccm_reg->ccm_reg_backup.Apb1_Cfg.dwval; /*delay_us(10); */ /*save_pm_secure_mem_status(CLK_RESUME_START | 0xa); */ setting_ahb0_para(); /*save_pm_secure_mem_status(CLK_RESUME_START | 0xf); */ return 0; } /* ********************************************************************************************************* * mem_clk_setdiv * * Description: set div ratio * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_setdiv(struct clk_div_t *clk_div) { if (!clk_div) { return -1; } CmuReg = (__ccmu_reg_list_t *) (AW_CCM_BASE); /*restore axi division. */ if (get_cur_cluster_id()) { *(volatile __u32 *)&CmuReg->Axi1_Cfg = clk_div->Axi1_Cfg; } else { *(volatile __u32 *)&CmuReg->Axi0_Cfg = clk_div->Axi0_Cfg; } /*asm volatile ("dsb"); */ /*asm volatile ("isb"); */ return 0; } /* ********************************************************************************************************* * mem_clk_getdiv * * Description: * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_getdiv(struct clk_div_t *clk_div) { if (!clk_div) { return -1; } CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); if (get_cur_cluster_id()) { clk_div->Axi1_Cfg = *(volatile __u32 *)&CmuReg->Axi1_Cfg; } else { clk_div->Axi0_Cfg = *(volatile __u32 *)&CmuReg->Axi0_Cfg; } return 0; } /* ********************************************************************************************************* * mem_clk_set_pll_factor * * Description: set pll factor, target cpu freq is ?M hz * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_set_pll_factor(struct pll_factor_t *pll_factor) { CmuReg = (__ccmu_reg_list_t *) (AW_CCM_BASE); if (get_cur_cluster_id()) { CmuReg_Pll_C1_Cfg_tmp.dwval = CmuReg->Pll_C1_Cfg.dwval; /*set pll factor: notice: when raise freq, N must be the last to set */ CmuReg_Pll_C1_Cfg_tmp.bits.pll_postdiv_m = pll_factor->FactorM; CmuReg_Pll_C1_Cfg_tmp.bits.pll_out_ext_divp = pll_factor->FactorP; CmuReg_Pll_C1_Cfg_tmp.bits.pll_factor_n = pll_factor->FactorN; CmuReg->Pll_C1_Cfg.dwval = CmuReg_Pll_C1_Cfg_tmp.dwval; } else { CmuReg_Pll_C0_Cfg_tmp.dwval = CmuReg->Pll_C0_Cfg.dwval; CmuReg_Pll_C0_Cfg_tmp.bits.pll_postdiv_m = pll_factor->FactorM; CmuReg_Pll_C0_Cfg_tmp.bits.pll_out_ext_divp = pll_factor->FactorP; CmuReg_Pll_C0_Cfg_tmp.bits.pll_factor_n = pll_factor->FactorN; CmuReg->Pll_C0_Cfg.dwval = CmuReg_Pll_C0_Cfg_tmp.dwval; } return 0; } /* ********************************************************************************************************* * mem_clk_get_pll_factor * * Description: get pll factor * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_get_pll_factor(struct pll_factor_t *pll_factor) { CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); if (get_cur_cluster_id()) { CmuReg_Pll_C1_Cfg_tmp.dwval = CmuReg->Pll_C1_Cfg.dwval; pll_factor->FactorN = CmuReg_Pll_C1_Cfg_tmp.bits.pll_factor_n; pll_factor->FactorM = CmuReg_Pll_C1_Cfg_tmp.bits.pll_postdiv_m; pll_factor->FactorP = CmuReg_Pll_C1_Cfg_tmp.bits.pll_out_ext_divp; } else { CmuReg_Pll_C0_Cfg_tmp.dwval = CmuReg->Pll_C0_Cfg.dwval; pll_factor->FactorN = CmuReg_Pll_C0_Cfg_tmp.bits.pll_factor_n; pll_factor->FactorM = CmuReg_Pll_C0_Cfg_tmp.bits.pll_postdiv_m; pll_factor->FactorP = CmuReg_Pll_C0_Cfg_tmp.bits.pll_out_ext_divp; } return 0; } /* ********************************************************************************************************* * mem_clk_set_misc * * Description: set clk_misc * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_set_misc(struct clk_misc_t *clk_misc) { CmuReg = (__ccmu_reg_list_t *) (AW_CCM_BASE); /**/ CmuReg->Pll_C0_Bias.dwval = clk_misc->Pll_C0_Bias; CmuReg->Pll_C0_Tun.dwval = clk_misc->Pll_C0_Tun; CmuReg->Pll_Periph1_Bias.dwval = clk_misc->Pll_Periph1_Bias; CmuReg->Pll_Periph2_Bias.dwval = clk_misc->Pll_Periph2_Bias; /*set vedio, cluster1 pll para */ /*1st bias */ CmuReg->Pll_C1_Bias.dwval = clk_misc->Pll_C1_Bias; /*0x00a4 */ CmuReg->Pll_Vedio1_Bias.dwval = clk_misc->Pll_Vedio1_Bias; /*0x00b8 */ CmuReg->Pll_Vedio2_Bias.dwval = clk_misc->Pll_Vedio2_Bias; /*0x00bc */ /*2nd: tune& pattern */ CmuReg->Pll_C1_Tun.dwval = clk_misc->Pll_C1_Tun; /*0x00e4 */ CmuReg->Pll_Video1_Pat_Cfg.dwval = clk_misc->Pll_Video1_Pat_Cfg; /*0x0118 */ CmuReg->Pll_Video2_Pat_Cfg.dwval = clk_misc->Pll_Video2_Pat_Cfg; /*0x011c */ /*3rd: cfg */ if (get_cur_cluster_id()) { CmuReg->Pll_C0_Cfg.dwval = clk_misc->Pll_C0_Cfg; /*0x0000 */ } else { CmuReg->Pll_C1_Cfg.dwval = clk_misc->Pll_C1_Cfg; /*0x0004 */ } CmuReg->Pll_Video1_Cfg.dwval = clk_misc->Pll_Video1_Cfg; /*0x0018 */ CmuReg->Pll_Video2_Cfg.dwval = clk_misc->Pll_Video2_Cfg; /*0x001c */ /*axi src is cpu clk src. */ /*need set axi division before change pll1 to 408M, */ /*config axi ratio to 1+1 = 2; */ /*axi can not exceed 300M; */ /*need to update axi divide ratio. */ if (get_cur_cluster_id()) { *(volatile __u32 *)&CmuReg->Axi1_Cfg = 0x102; /*atb = 2; axi div = 3; */ } else { *(volatile __u32 *)&CmuReg->Axi0_Cfg = 0x102; /*atb = 2; axi div = 3; */ } /* asm volatile ("dsb");*/ /* asm volatile ("isb");*/ if (get_cur_cluster_id()) { *(volatile __u32 *)&CmuReg->Axi1_Cfg = 0x203; /*atb = 4; axi div = 4; */ } else { *(volatile __u32 *)&CmuReg->Axi0_Cfg = 0x203; /*atb = 4; axi div = 4; */ } /* asm volatile ("dsb");*/ /* asm volatile ("isb");*/ if (get_cur_cluster_id()) { CmuReg_Axi1_Cfg_tmp.dwval = CmuReg->Axi1_Cfg.dwval; CmuReg_Axi1_Cfg_tmp.bits.axi1_clk_div_ratio = 1; CmuReg->Axi1_Cfg.dwval = CmuReg_Axi1_Cfg_tmp.dwval; } else { CmuReg_Axi0_Cfg_tmp.dwval = CmuReg->Axi0_Cfg.dwval; CmuReg_Axi0_Cfg_tmp.bits.axi0_clk_div_ratio = 1; CmuReg->Axi0_Cfg.dwval = CmuReg_Axi0_Cfg_tmp.dwval; } return 0; } /* ********************************************************************************************************* * mem_clk_get_misc * * Description: get clk_misc * * Arguments : none * * Returns : 0; ********************************************************************************************************* */ __s32 mem_clk_get_misc(struct clk_misc_t *clk_misc) { CmuReg = (__ccmu_reg_list_t *) IO_ADDRESS(AW_CCM_BASE); clk_misc->Pll_C0_Bias = CmuReg->Pll_C0_Bias.dwval; clk_misc->Pll_C0_Tun = CmuReg->Pll_C0_Tun.dwval; clk_misc->Pll_Periph1_Bias = CmuReg->Pll_Periph1_Bias.dwval; clk_misc->Pll_Periph2_Bias = CmuReg->Pll_Periph2_Bias.dwval; clk_misc->Pll_C1_Bias = CmuReg->Pll_C1_Bias.dwval; /*0x00a4 */ clk_misc->Pll_Vedio1_Bias = CmuReg->Pll_Vedio1_Bias.dwval; /*0x00b8 */ clk_misc->Pll_Vedio2_Bias = CmuReg->Pll_Vedio2_Bias.dwval; /*0x00bc */ clk_misc->Pll_C1_Tun = CmuReg->Pll_C1_Tun.dwval; /*0x00e4 */ clk_misc->Pll_Video1_Pat_Cfg = CmuReg->Pll_Video1_Pat_Cfg.dwval; /*0x0118 */ clk_misc->Pll_Video2_Pat_Cfg = CmuReg->Pll_Video2_Pat_Cfg.dwval; /*0x011c */ clk_misc->Pll_C0_Cfg = CmuReg->Pll_C0_Cfg.dwval; /*0x0000 */ clk_misc->Pll_C1_Cfg = CmuReg->Pll_C1_Cfg.dwval; /*0x0004 */ clk_misc->Pll_Video1_Cfg = CmuReg->Pll_Video1_Cfg.dwval; /*0x0018 */ clk_misc->Pll_Video2_Cfg = CmuReg->Pll_Video2_Cfg.dwval; /*0x001c */ return 0; } /* ********************************************************************************************************* * mem_clk_get_cpu_freq * * Description: get current cpu freq * * Arguments : none * * Returns : cpu freq. ********************************************************************************************************* */ __u32 mem_clk_get_cpu_freq(void) { __u32 FactorN = 1; __u32 FactorK = 1; __u32 FactorM = 1; __u32 FactorP = 1; __u32 reg_val = 0; __u32 cpu_freq = 0; CmuReg_Cpu_Clk_Src_tmp.dwval = CmuReg->Cpu_Clk_Src.dwval; /*get runtime freq: clk src + divider ratio */ /*src selection */ if (get_cur_cluster_id()) { reg_val = CmuReg_Cpu_Clk_Src_tmp.bits.cpu_c1_clk_src_sel; } else { reg_val = CmuReg_Cpu_Clk_Src_tmp.bits.cpu_c0_clk_src_sel; } if (0 == reg_val) { /*hosc, 24Mhz */ cpu_freq = 24000; /*unit is khz */ } else if (1 == reg_val) { if (get_cur_cluster_id()) { CmuReg_Pll_C1_Cfg_tmp.dwval = CmuReg->Pll_C1_Cfg.dwval; FactorN = CmuReg_Pll_C1_Cfg_tmp.bits.pll_factor_n; FactorM = (CmuReg_Pll_C1_Cfg_tmp.bits.pll_postdiv_m) + 1; FactorP = (0 == CmuReg_Pll_C1_Cfg_tmp. bits.pll_out_ext_divp) ? 1 : 4; } else { CmuReg_Pll_C0_Cfg_tmp.dwval = CmuReg->Pll_C0_Cfg.dwval; FactorN = CmuReg_Pll_C0_Cfg_tmp.bits.pll_factor_n; FactorM = (CmuReg_Pll_C0_Cfg_tmp.bits.pll_postdiv_m) + 1; FactorP = (0 == CmuReg_Pll_C0_Cfg_tmp. bits.pll_out_ext_divp) ? 1 : 4; } cpu_freq = raw_lib_udiv(24000 * FactorN * FactorK, FactorP * FactorM); } /* asm volatile ("dsb");*/ /* asm volatile ("isb"); */ /*printk("cpu_freq = dec(%d). \n", cpu_freq); */ return cpu_freq; } #endif