381 lines
12 KiB
C
381 lines
12 KiB
C
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* AR100 SYSTEM
|
||
|
* AR100 Software System Develop Kits
|
||
|
* clock control unit module
|
||
|
*
|
||
|
* (c) Copyright 2012-2016, Sunny China
|
||
|
* All Rights Reserved
|
||
|
*
|
||
|
* File : sclk.c
|
||
|
* By : Sunny
|
||
|
* Version : v1.0
|
||
|
* Date : 2012-5-7
|
||
|
* Descript: system clock management.
|
||
|
* Update : date auther ver notes
|
||
|
* 2012-5-7 8:43:10 Sunny 1.0 Create this file.
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
#include <delay.h>
|
||
|
#include "ccu_i.h"
|
||
|
#include "errno.h"
|
||
|
#include "hal_prcm.h"
|
||
|
#include "stdio.h"
|
||
|
#include "aw_common.h"
|
||
|
#include "compiler_attributes.h"
|
||
|
|
||
|
|
||
|
static ccu_pll_audio0_reg_t *pll_audio0 = (ccu_pll_audio0_reg_t *)CCU_PLL_AUDIO0_REG;
|
||
|
static ccu_pll_audio1_reg_t *pll_audio1 = (ccu_pll_audio1_reg_t *)CCU_PLL_AUDIO1_REG;
|
||
|
static ccu_pll_audio0_pat0_reg_t *pll_audio0_pat0 = (ccu_pll_audio0_pat0_reg_t *)CCU_PLL_AUDIO0_PAT0_REG;
|
||
|
static ccu_pll_audio1_pat0_reg_t *pll_audio1_pat0 = (ccu_pll_audio1_pat0_reg_t *)CCU_PLL_AUDIO1_PAT0_REG;
|
||
|
|
||
|
static s32 ccu_set_pll_audio0(u32 freq)
|
||
|
{
|
||
|
static u32 old_freq = 0;
|
||
|
s32 loop = 0;
|
||
|
|
||
|
if (freq == old_freq)
|
||
|
return 0;
|
||
|
|
||
|
UNUSED(pll_audio0_pat0);
|
||
|
|
||
|
old_freq = freq;
|
||
|
|
||
|
/* make sure pll new mode is disable */
|
||
|
pll_audio0->lock_en = 0;
|
||
|
pll_audio0->lock_st = 0;
|
||
|
|
||
|
switch (freq) {
|
||
|
default:
|
||
|
printf("not support freq:%d, now set freq:24576000Hz.\n", freq);
|
||
|
case 24576000:
|
||
|
#if 0
|
||
|
/* *pll_audio0_pat0 = 0xc00126e9;*/
|
||
|
/* bit0 - bit16, wave bottom */
|
||
|
pll_audio0_pat0->wave_bot = 0x126e9;
|
||
|
/* bit17 - bit18, frequency */
|
||
|
pll_audio0_pat0->freq = 0;
|
||
|
/* bit19, 0:24M, 1:12M, SDM clk select */
|
||
|
pll_audio0_pat0->clk_sel = 0;
|
||
|
/* bit20 - bit28, wave step */
|
||
|
pll_audio0_pat0->wave_step = 0;
|
||
|
/* bit29 - bit30, Spread frequency mode */
|
||
|
pll_audio0_pat0->freq_mode = 0;
|
||
|
/* bit31, 0-disable, 1-enable, Sigma-Delta Pattern Enable */
|
||
|
pll_audio0_pat0->enable = 1;
|
||
|
|
||
|
/* fix for arch32 or arch64 */
|
||
|
*((unsigned long *)pll_audio0) = 0x890b1701;
|
||
|
#endif
|
||
|
break;
|
||
|
case 22579200:
|
||
|
#if 0
|
||
|
/* *pll_audio1_pat0 = 0xc001288d;*/
|
||
|
/* bit0 - bit16, wave bottom */
|
||
|
pll_audio1_pat0->wave_bot = 0x1288d;
|
||
|
/* bit17 - bit18, frequency */
|
||
|
pll_audio1_pat0->freq = 0;
|
||
|
/* bit19, 0:24M, 1:12M, SDM clk select */
|
||
|
pll_audio1_pat0->clk_sel = 0;
|
||
|
/* bit20 - bit28, wave step */
|
||
|
pll_audio1_pat0->wave_step = 0;
|
||
|
/* bit29 - bit30, Spread frequency mode */
|
||
|
pll_audio1_pat0->freq_mode = 0;
|
||
|
/* bit31, 0-disable, 1-enable, Sigma-Delta Pattern Enable */
|
||
|
pll_audio1_pat0->enable = 1;
|
||
|
|
||
|
*((unsigned long *)pll_audio1) = 0x890b1501;
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (pll_audio0->enable) {
|
||
|
pll_audio0->lock_st = 1;
|
||
|
pll_audio0->lock_en = 1;
|
||
|
while (pll_audio0->lock_st && (--loop > 0)) {
|
||
|
udelay(1);
|
||
|
}
|
||
|
pll_audio0->lock_en = 0;
|
||
|
pll_audio0->lock_st = 0;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static s32 ccu_set_pll_audio1(u32 freq)
|
||
|
{
|
||
|
static u32 old_freq = 0;
|
||
|
s32 loop = 0;
|
||
|
|
||
|
if (freq == old_freq)
|
||
|
return 0;
|
||
|
|
||
|
old_freq = freq;
|
||
|
|
||
|
/* make sure pll new mode is disable */
|
||
|
pll_audio1->lock_en = 0;
|
||
|
pll_audio1->lock_st = 0;
|
||
|
|
||
|
switch (freq) {
|
||
|
default:
|
||
|
printf("not support freq:%d, now set freq:24576000Hz.\n", freq);
|
||
|
case 24576000:
|
||
|
/* *pll_audio1_pat0 = 0xc00126e9;*/
|
||
|
/* bit0 - bit16, wave bottom */
|
||
|
pll_audio1_pat0->wave_bot = 0x126e9;
|
||
|
/* bit17 - bit18, frequency */
|
||
|
pll_audio1_pat0->freq = 0;
|
||
|
/* bit19, 0:24M, 1:12M, SDM clk select */
|
||
|
pll_audio1_pat0->clk_sel = 0;
|
||
|
/* bit20 - bit28, wave step */
|
||
|
pll_audio1_pat0->wave_step = 0;
|
||
|
/* bit29 - bit30, Spread frequency mode */
|
||
|
pll_audio1_pat0->freq_mode = 0;
|
||
|
/* bit31, 0-disable, 1-enable, Sigma-Delta Pattern Enable */
|
||
|
pll_audio1_pat0->enable = 1;
|
||
|
|
||
|
/* fix for arch32 or arch64 */
|
||
|
*((unsigned long *)pll_audio1) = 0x890b1701;
|
||
|
break;
|
||
|
case 22579200:
|
||
|
/* *pll_audio1_pat0 = 0xc001288d;*/
|
||
|
/* bit0 - bit16, wave bottom */
|
||
|
pll_audio1_pat0->wave_bot = 0x1288d;
|
||
|
/* bit17 - bit18, frequency */
|
||
|
pll_audio1_pat0->freq = 0;
|
||
|
/* bit19, 0:24M, 1:12M, SDM clk select */
|
||
|
pll_audio1_pat0->clk_sel = 0;
|
||
|
/* bit20 - bit28, wave step */
|
||
|
pll_audio1_pat0->wave_step = 0;
|
||
|
/* bit29 - bit30, Spread frequency mode */
|
||
|
pll_audio1_pat0->freq_mode = 0;
|
||
|
/* bit31, 0-disable, 1-enable, Sigma-Delta Pattern Enable */
|
||
|
pll_audio1_pat0->enable = 1;
|
||
|
|
||
|
*((unsigned long *)pll_audio1) = 0x890b1501;
|
||
|
break;
|
||
|
case 90316800:
|
||
|
/* *pll_audio1_pat0 = 0xc001288d;*/
|
||
|
/* bit0 - bit16, wave bottom */
|
||
|
pll_audio1_pat0->wave_bot = 0x1288d;
|
||
|
/* bit17 - bit18, frequency */
|
||
|
pll_audio1_pat0->freq = 0;
|
||
|
/* bit19, 0:24M, 1:12M, SDM clk select */
|
||
|
pll_audio1_pat0->clk_sel = 0;
|
||
|
/* bit20 - bit28, wave step */
|
||
|
pll_audio1_pat0->wave_step = 0;
|
||
|
/* bit29 - bit30, Spread frequency mode */
|
||
|
pll_audio1_pat0->freq_mode = 0;
|
||
|
/* bit31, 0-disable, 1-enable, Sigma-Delta Pattern Enable */
|
||
|
pll_audio1_pat0->enable = 1;
|
||
|
|
||
|
*((unsigned long *)pll_audio1) = 0x89021501;
|
||
|
break;
|
||
|
case 98304000:
|
||
|
/* *pll_audio1_pat0 = 0xc00126e9;*/
|
||
|
/* bit0 - bit16, wave bottom */
|
||
|
pll_audio1_pat0->wave_bot = 0x126e9;
|
||
|
/* bit17 - bit18, frequency */
|
||
|
pll_audio1_pat0->freq = 0;
|
||
|
/* bit19, 0:24M, 1:12M, SDM clk select */
|
||
|
pll_audio1_pat0->clk_sel = 0;
|
||
|
/* bit20 - bit28, wave step */
|
||
|
pll_audio1_pat0->wave_step = 0;
|
||
|
/* bit29 - bit30, Spread frequency mode */
|
||
|
pll_audio1_pat0->freq_mode = 0;
|
||
|
/* bit31, 0-disable, 1-enable, Sigma-Delta Pattern Enable */
|
||
|
pll_audio1_pat0->enable = 1;
|
||
|
|
||
|
*((unsigned long *)pll_audio1) = 0x89021701;
|
||
|
break;
|
||
|
}
|
||
|
if (pll_audio1->enable) {
|
||
|
pll_audio1->lock_st = 1;
|
||
|
pll_audio1->lock_en = 1;
|
||
|
while (pll_audio1->lock_st && (--loop > 0)) {
|
||
|
udelay(1);
|
||
|
}
|
||
|
pll_audio1->lock_en = 0;
|
||
|
pll_audio1->lock_st = 0;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* SET SOURCE FREQUENCY
|
||
|
*
|
||
|
* Description: set the frequency of a specific source clock.
|
||
|
*
|
||
|
* Arguments : sclk : the source clock ID which we want to set frequency.
|
||
|
* freq : the frequency which we want to set.
|
||
|
*
|
||
|
* Returns : OK if set source frequency succeeded, others if failed.
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
s32 ccu_set_sclk_freq(u32 sclk, __maybe_unused u32 freq)
|
||
|
{
|
||
|
switch (sclk) {
|
||
|
case CCU_SYS_CLK_AUDIO0:
|
||
|
return ccu_set_pll_audio0(freq);
|
||
|
case CCU_SYS_CLK_AUDIO1:
|
||
|
return ccu_set_pll_audio1(freq);
|
||
|
default:
|
||
|
pr_warning("invaid clock id (%d) when set freq(%d)\n", sclk);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
/* un-reached */
|
||
|
}
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* GET SOURCE FREQUENCY
|
||
|
*
|
||
|
* Description: get the frequency of a specific source clock.
|
||
|
*
|
||
|
* Arguments : sclk : the source clock ID which we want to get frequency.
|
||
|
*
|
||
|
* Returns : frequency of the specific source clock.
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
u32 ccu_get_sclk_freq(u32 sclk)
|
||
|
{
|
||
|
switch (sclk) {
|
||
|
case CCU_SYS_CLK_LOSC: {
|
||
|
return losc_freq;
|
||
|
}
|
||
|
case CCU_SYS_CLK_HOSC: {
|
||
|
return CCU_HOSC_FREQ;
|
||
|
}
|
||
|
case CCU_SYS_CLK_CPUX: {
|
||
|
/* maybe should delete */
|
||
|
ccu_pll_c0_cpux_reg0000_t pll_c0 = *(ccu_pll_c0_cpux_reg_addr);
|
||
|
return (CCU_HOSC_FREQ * (pll_c0.factor_n + 1)) /
|
||
|
((pll_c0.factor_m + 1) * (1 << pll_c0.factor_p));
|
||
|
}
|
||
|
case CCU_SYS_CLK_CPUS: {
|
||
|
switch (ccu_reg_addr->cpus_clk_cfg.src_sel) {
|
||
|
case 0: {
|
||
|
/* cpus clock source is losc */
|
||
|
return CCU_HOSC_FREQ;
|
||
|
}
|
||
|
case 1: {
|
||
|
/* cpus clock source is hosc */
|
||
|
return losc_freq;
|
||
|
}
|
||
|
case 2: {
|
||
|
/* cpus clock source is internal-osc */
|
||
|
return iosc_freq;
|
||
|
}
|
||
|
case 3: {
|
||
|
/* cpus clock source is pll_peri0(2x) */
|
||
|
return ccu_get_sclk_freq(CCU_SYS_CLK_PERI_2X) /
|
||
|
(1 << ccu_reg_addr->cpus_clk_cfg.factor_n) /
|
||
|
(ccu_reg_addr->cpus_clk_cfg.factor_m + 1);
|
||
|
}
|
||
|
case 4: {
|
||
|
return ccu_get_sclk_freq(CCU_SYS_CLK_AUDIO0_DIV2) /
|
||
|
(1 << ccu_reg_addr->cpus_clk_cfg.factor_n) /
|
||
|
(ccu_reg_addr->cpus_clk_cfg.factor_m + 1);
|
||
|
}
|
||
|
default: {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
case CCU_SYS_CLK_AHBS: {
|
||
|
return ccu_get_sclk_freq(CCU_SYS_CLK_CPUS);
|
||
|
}
|
||
|
case CCU_SYS_CLK_APBS1: {
|
||
|
return ccu_get_sclk_freq(CCU_SYS_CLK_AHBS) /
|
||
|
ccu_get_mclk_div(CCU_MOD_CLK_APBS1);
|
||
|
}
|
||
|
case CCU_SYS_CLK_APBS2: {
|
||
|
switch (ccu_reg_addr->apbs2_cfg.src_sel) {
|
||
|
case 0: {
|
||
|
/* cpus clock source is losc */
|
||
|
return CCU_HOSC_FREQ;
|
||
|
}
|
||
|
case 1: {
|
||
|
/* cpus clock source is hosc */
|
||
|
return losc_freq;
|
||
|
}
|
||
|
case 2: {
|
||
|
/* cpus clock source is internal-osc */
|
||
|
return iosc_freq;
|
||
|
}
|
||
|
case 3: {
|
||
|
/* cpus clock source is pll6 */
|
||
|
return ccu_get_sclk_freq(CCU_SYS_CLK_PLL3) /
|
||
|
(ccu_reg_addr->apbs2_cfg.factor_m + 1) /
|
||
|
(1 << ccu_reg_addr->apbs2_cfg.factor_n);
|
||
|
}
|
||
|
default: {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
case CCU_SYS_CLK_PERI_1X: {
|
||
|
/* output=24M*N*K/2 */
|
||
|
ccu_pll_periph_reg0010_t pll_periph0 =
|
||
|
*(ccu_pll_periph0_reg_addr);
|
||
|
|
||
|
return ((long long)CCU_HOSC_FREQ * (pll_periph0.factor_n + 1) /
|
||
|
(pll_periph0.factor_m + 1) /
|
||
|
(pll_periph0.factor_p0 + 1) / 2);
|
||
|
}
|
||
|
case CCU_SYS_CLK_PERI_2X: {
|
||
|
ccu_pll_periph_reg0010_t pll_periph0 =
|
||
|
*(ccu_pll_periph0_reg_addr);
|
||
|
return ((long long)CCU_HOSC_FREQ * (pll_periph0.factor_n + 1) /
|
||
|
(pll_periph0.factor_m + 1) /
|
||
|
(pll_periph0.factor_p0 + 1));
|
||
|
}
|
||
|
case CCU_SYS_CLK_AUDIO0_DIV2: {
|
||
|
ccu_pll_audio0_reg0020_t pll_audio0 =
|
||
|
*(ccu_pll_audio0_reg_addr);
|
||
|
return ((long long)CCU_HOSC_FREQ * (pll_audio0.factor_n + 1) /
|
||
|
(pll_audio0.factor_m + 1) / (pll_audio0.factor_p0 + 1));
|
||
|
}
|
||
|
}
|
||
|
pr_warning("invalid clock id for get source freq\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
s32 ccu_set_sclk_onoff(u32 sclk, s32 onoff)
|
||
|
{
|
||
|
switch (sclk) {
|
||
|
case CCU_SYS_CLK_C0:
|
||
|
{
|
||
|
ccu_pll_c0_cpux_reg_addr->enable = onoff;
|
||
|
return OK;
|
||
|
}
|
||
|
case CCU_SYS_CLK_DDR0:
|
||
|
{
|
||
|
ccu_pll_ddr0_reg_addr->enable = onoff;
|
||
|
return OK;
|
||
|
}
|
||
|
case CCU_SYS_CLK_PERI0:
|
||
|
{
|
||
|
ccu_pll_periph0_reg_addr->enable = onoff;
|
||
|
return OK;
|
||
|
}
|
||
|
case CCU_SYS_CLK_AUDIO0:
|
||
|
{
|
||
|
pll_audio0->enable = onoff;
|
||
|
return OK;
|
||
|
}
|
||
|
case CCU_SYS_CLK_AUDIO1:
|
||
|
{
|
||
|
pll_audio1->enable = onoff;
|
||
|
return OK;
|
||
|
}
|
||
|
default:
|
||
|
pr_warning("invalid clock id for get source freq\n");
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|