1352 lines
42 KiB
C
1352 lines
42 KiB
C
/*
|
|
* 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
|