gpll support 300mhz for vmac,arm can selelt between apll\gpll

This commit is contained in:
xxx
2012-06-13 14:23:54 -07:00
parent 47ee5bc625
commit a0d9664aa3
2 changed files with 221 additions and 62 deletions

View File

@@ -712,7 +712,7 @@ static int pll_clk_mode(struct clk *clk, int on)
u8 pll_id=clk->pll->id;
u32 nr=PLL_NR(cru_readl(PLL_CONS(pll_id,0)));
u32 dly= (nr*500)/24+1;
CRU_PRINTK_DBG("pll_mode %s(%d)",clk->name,on);
if (on) {
cru_writel(PLL_PWR_ON|PLL_PWR_DN_W_MSK,PLL_CONS(pll_id,3));
rk30_clock_udelay(dly);
@@ -894,28 +894,46 @@ static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate)
temp_clk_div->clksel0,temp_clk_div->clksel1);
local_irq_save(flags);
//new div max first
if(gpll_arm_aclk_div>=old_aclk_div)
{
if((old_aclk_div==3||gpll_arm_aclk_div==3)&&(gpll_arm_aclk_div!=old_aclk_div))
{
cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON);
cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1));
cru_writel((temp_clk_div->clksel0|CORE_CLK_DIV(temp_div)|CORE_CLK_DIV_W_MSK),
CRU_CLKSELS_CON(0));
cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON);
}
else
{
cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1));
cru_writel((temp_clk_div->clksel0)|CORE_CLK_DIV(temp_div)|CORE_CLK_DIV_W_MSK,
CRU_CLKSELS_CON(0));
}
}
// open gpu gpll path
cru_writel(CLK_GATE_W_MSK(CLK_GATE_CPU_GPLL_PATH)|CLK_UN_GATE(CLK_GATE_CPU_GPLL_PATH),CLK_GATE_CLKID_CONS(CLK_GATE_CPU_GPLL_PATH));
cru_writel(CORE_SEL_GPLL|CORE_SEL_PLL_W_MSK, CRU_CLKSELS_CON(0));
loops_per_jiffy = arm_gpll_lpj;
smp_wmb();
if((old_aclk_div==3||gpll_arm_aclk_div==3)&&(gpll_arm_aclk_div!=old_aclk_div))
{
cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON);
cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1));
cru_writel((temp_clk_div->clksel0|CORE_CLK_DIV(temp_div)|CORE_CLK_DIV_W_MSK),
CRU_CLKSELS_CON(0));
cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON);
}
else
//new div max late
if(gpll_arm_aclk_div<old_aclk_div)
{
cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1));
cru_writel((temp_clk_div->clksel0)|CORE_CLK_DIV(temp_div)|CORE_CLK_DIV_W_MSK,
CRU_CLKSELS_CON(0));
if((old_aclk_div==3||gpll_arm_aclk_div==3)&&(gpll_arm_aclk_div!=old_aclk_div))
{
cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON);
cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1));
cru_writel((temp_clk_div->clksel0|CORE_CLK_DIV(temp_div)|CORE_CLK_DIV_W_MSK),
CRU_CLKSELS_CON(0));
cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON);
}
else
{
cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1));
cru_writel((temp_clk_div->clksel0)|CORE_CLK_DIV(temp_div)|CORE_CLK_DIV_W_MSK,
CRU_CLKSELS_CON(0));
}
}
/*if core src don't select gpll ,apll neet to enter slow mode */
@@ -940,23 +958,42 @@ static int arm_pll_clk_set_rate(struct clk *clk, unsigned long rate)
//return form slow
//cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON);
//a/h/p clk sel
if((gpll_arm_aclk_div==3||new_aclk_div==3)&&(new_aclk_div!=gpll_arm_aclk_div))
{
cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON);
cru_writel((ps->clksel1), CRU_CLKSELS_CON(1));
cru_writel((ps->clksel0)|CORE_CLK_DIV(1)|CORE_CLK_DIV_W_MSK, CRU_CLKSELS_CON(0));
cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON);
}
else
{
cru_writel((ps->clksel1), CRU_CLKSELS_CON(1));
cru_writel((ps->clksel0)|CORE_CLK_DIV(1)|CORE_CLK_DIV_W_MSK, CRU_CLKSELS_CON(0));
if(new_aclk_div>=gpll_arm_aclk_div)
{
if((gpll_arm_aclk_div==3||new_aclk_div==3)&&(new_aclk_div!=gpll_arm_aclk_div))
{
cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON);
cru_writel((ps->clksel1), CRU_CLKSELS_CON(1));
cru_writel((ps->clksel0)|CORE_CLK_DIV(1)|CORE_CLK_DIV_W_MSK, CRU_CLKSELS_CON(0));
cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON);
}
else
{
cru_writel((ps->clksel1), CRU_CLKSELS_CON(1));
cru_writel((ps->clksel0)|CORE_CLK_DIV(1)|CORE_CLK_DIV_W_MSK, CRU_CLKSELS_CON(0));
}
}
//reparent to apll
cru_writel(CORE_SEL_PLL_W_MSK|CORE_SEL_APLL, CRU_CLKSELS_CON(0));
loops_per_jiffy = ps->lpj;
smp_wmb();
if(new_aclk_div<gpll_arm_aclk_div)
{
if((gpll_arm_aclk_div==3||new_aclk_div==3)&&(new_aclk_div!=gpll_arm_aclk_div))
{
cru_writel(PLL_MODE_SLOW(APLL_ID), CRU_MODE_CON);
cru_writel((ps->clksel1), CRU_CLKSELS_CON(1));
cru_writel((ps->clksel0)|CORE_CLK_DIV(1)|CORE_CLK_DIV_W_MSK, CRU_CLKSELS_CON(0));
cru_writel(PLL_MODE_NORM(APLL_ID), CRU_MODE_CON);
}
else
{
cru_writel((ps->clksel1), CRU_CLKSELS_CON(1));
cru_writel((ps->clksel0)|CORE_CLK_DIV(1)|CORE_CLK_DIV_W_MSK, CRU_CLKSELS_CON(0));
}
}
//CRU_PRINTK_DBG("apll set loops_per_jiffy =%lu,rate(%lu)\n",loops_per_jiffy,ps->rate);
local_irq_restore(flags);
@@ -1014,6 +1051,7 @@ static struct _pll_data apll_data=SET_PLL_DATA(APLL_ID,(void *)apll_clks);
static struct clk arm_pll_clk ={
.name = "arm_pll",
.parent = &xin24m,
.mode = pll_clk_mode,
.recalc = plls_clk_recalc,
.set_rate = arm_pll_clk_set_rate,
.round_rate = arm_pll_clk_round_rate,
@@ -1041,14 +1079,16 @@ static const struct pll_clk_set cpll_clks[] = {
_PLL_SET_CLKS(504000, 1, 21, 1),
_PLL_SET_CLKS(552000, 1, 23, 1),
_PLL_SET_CLKS(600000, 1, 25, 1),
_PLL_SET_CLKS(742500, 8, 495, 2),
_PLL_SET_CLKS(798000, 4, 133, 1),
_PLL_SET_CLKS(1188000,2, 99, 1),
_PLL_SET_CLKS( 0, 4, 133, 1),
};
static struct _pll_data cpll_data=SET_PLL_DATA(CPLL_ID,(void *)cpll_clks);
static struct clk codec_pll_clk = {
.name = "codec_pll",
.parent = &xin24m,
//.mode = pll_clk_mode,
.mode = pll_clk_mode,
.recalc = plls_clk_recalc,
.set_rate = cpll_clk_set_rate,
.pll= &cpll_data,
@@ -1057,7 +1097,8 @@ static struct clk codec_pll_clk = {
static const struct pll_clk_set gpll_clks[] = {
_PLL_SET_CLKS(148500, 4, 99, 4),
_PLL_SET_CLKS(297000, 2, 99, 4),
_PLL_SET_CLKS(1188000, 1, 99, 2),
_PLL_SET_CLKS(300000, 1, 25, 2),
_PLL_SET_CLKS(1188000, 2, 99, 1),
_PLL_SET_CLKS(0, 0, 0, 0),
};
static struct _pll_data gpll_data=SET_PLL_DATA(GPLL_ID,(void *)gpll_clks);
@@ -1089,7 +1130,7 @@ static int arm_core_clk_set_rate(struct clk *c, unsigned long rate)
{
int ret;
//set arm pll div 1
set_cru_bits_w_msk(0,c->div_mask,c->div_shift,c->clksel_con);
//set_cru_bits_w_msk(0,c->div_mask,c->div_shift,c->clksel_con);
ret = clk_set_rate_nolock(c->parent, rate);
if (ret) {
@@ -1110,14 +1151,93 @@ static long core_clk_round_rate(struct clk *clk, unsigned long rate)
return clk_round_rate_nolock(clk->parent,rate)/div;
}
/*
static int core_clksel_set_parent(struct clk *clk, struct clk *new_prt)
{
u32 temp_div;
struct clk *old_prt;
if(clk->parent==new_prt)
return 0;
if (unlikely(!clk->parents))
return -EINVAL;
CRU_PRINTK_DBG("%s,reparent %s\n",clk->name,new_prt->name);
//arm
old_prt=clk->parent;
if(clk->parents[0]==new_prt)
{
new_prt->set_rate(new_prt,300*MHZ);
set_cru_bits_w_msk(0,clk->div_mask,clk->div_shift,clk->clksel_con);
}
else if(clk->parents[1]==new_prt)
{
if(new_prt->rate>old_prt->rate)
{
temp_div=clk_get_freediv(old_prt->rate,new_prt->rate,clk->div_max);
set_cru_bits_w_msk(temp_div-1,clk->div_mask,clk->div_shift,clk->clksel_con);
}
set_cru_bits_w_msk(1,clk->src_mask,clk->src_shift,clk->clksel_con);
new_prt->set_rate(new_prt,300*MHZ);
}
else
return -1;
return 0;
}
static int core_gpll_clk_set_rate(struct clk *c, unsigned long rate)
{
unsigned long flags;
u32 pll_id=APLL_ID;
u32 temp_div;
u32 old_aclk_div=0,new_aclk_div;
struct arm_clks_div_set *temp_clk_div;
unsigned long arm_gpll_rate, arm_gpll_lpj;
temp_div=clk_get_freediv(rate,c->parent->rate,c->div_max);
arm_gpll_rate=c->parent->rate/temp_div;
temp_clk_div=arm_clks_get_div(arm_gpll_rate/MHZ);
if(!temp_clk_div)
temp_clk_div=&arm_clk_div_tlb[4];
old_aclk_div=GET_CORE_ACLK_VAL(cru_readl(CRU_CLKSELS_CON(1))&CORE_ACLK_MSK);
new_aclk_div=GET_CORE_ACLK_VAL(temp_clk_div->clksel1&CORE_ACLK_MSK);
if(c->rate>=rate)
{
arm_gpll_lpj = lpj_gpll / temp_div;
set_cru_bits_w_msk(temp_div-1,c->div_mask,c->div_shift,c->clksel_con);
}
cru_writel((temp_clk_div->clksel1), CRU_CLKSELS_CON(1));
cru_writel((temp_clk_div->clksel0)|CORE_CLK_DIV(temp_div)|CORE_CLK_DIV_W_MSK,
CRU_CLKSELS_CON(0));
if((c->rate<rate))
{
arm_gpll_lpj = lpj_gpll / temp_div;
set_cru_bits_w_msk(temp_div-1,c->div_mask,c->div_shift,c->clksel_con);
}
return 0;
}
static unsigned long arm_core_gpll_clk_get_rate(struct clk *c)
{
return c->parent->rate;
}
static struct clk clk_cpu_gpll_path = {
.name = "core_gpll_path",
.name = "cpu_gpll_path",
.parent = &general_pll_clk,
.recalc = arm_core_gpll_clk_get_rate,
.set_rate = core_gpll_clk_set_rate,
CRU_DIV_SET(0x1f,0,32),
CRU_GATE_MODE_SET(gate_mode,CLK_GATE_CPU_GPLL_PATH),
};
*/
//static struct clk *clk_cpu_parents[2] = {&arm_pll_clk,&clk_cpu_gpll_path};
static struct clk *clk_cpu_parents[2] = {&arm_pll_clk,&clk_cpu_gpll_path};
static struct clk clk_cpu = {
.name = "cpu",
@@ -1125,10 +1245,11 @@ static struct clk clk_cpu = {
.set_rate = arm_core_clk_set_rate,
.recalc = arm_core_clk_get_rate,
.round_rate = core_clk_round_rate,
.set_parent = core_clksel_set_parent,
.clksel_con = CRU_CLKSELS_CON(0),
//CRU_DIV_SET(0x1f,0,32),
//CRU_SRC_SET(1,8),
//CRU_PARENTS_SET(clk_cpu_parents),
CRU_DIV_SET(0x1f,0,32),
CRU_SRC_SET(1,8),
CRU_PARENTS_SET(clk_cpu_parents),
};
static unsigned long aclk_cpu_recalc(struct clk *clk)
{
@@ -2561,6 +2682,7 @@ static struct clk_lookup clks[] = {
CLK(NULL, "ddr", &clk_ddr),
//CLK(NULL, "core_gpll_path", &clk_cpu_gpll_path),
CLK(NULL, "cpu", &clk_cpu),
CLK(NULL, "arm_gpll", &clk_cpu_gpll_path),
CLK("smp_twd", NULL, &core_periph),
CLK(NULL, "aclk_cpu", &aclk_cpu),
CLK(NULL, "hclk_cpu", &hclk_cpu),
@@ -3095,35 +3217,48 @@ static void periph_clk_set_init(void)
void rk30_clock_common_i2s_init(void)
{
struct clk *max_clk,*min_clk;
if(general_pll_clk.rate>=codec_pll_clk.rate)
{
max_clk=&general_pll_clk;
min_clk=&codec_pll_clk;
}else
{
max_clk=&codec_pll_clk;
min_clk=&general_pll_clk;
}
unsigned long i2s_rate;
//20 times
if(rk30_clock_flags&CLK_FLG_MAX_I2S_49152KHZ)
{
clk_set_parent_nolock(&clk_i2s_pll, max_clk);
i2s_rate=49152000;
}else if(rk30_clock_flags&CLK_FLG_MAX_I2S_24576KHZ)
{
clk_set_parent_nolock(&clk_i2s_pll, max_clk);
i2s_rate=24576000;
}
else if(rk30_clock_flags&CLK_FLG_MAX_I2S_22579_2KHZ)
{
clk_set_parent_nolock(&clk_i2s_pll, max_clk);
i2s_rate=22579000;
}
else if(rk30_clock_flags&CLK_FLG_MAX_I2S_12288KHZ)
{
clk_set_parent_nolock(&clk_i2s_pll, &general_pll_clk);
CRU_PRINTK_DBG("i2s max rate is 12288KHZ\n");
i2s_rate=12288000;
}
else
{
i2s_rate=49152000;
}
if(((i2s_rate*20)<=general_pll_clk.rate)||!(general_pll_clk.rate%i2s_rate))
{
clk_set_parent_nolock(&clk_i2s_pll, &general_pll_clk);
}
else if(((i2s_rate*20)<=codec_pll_clk.rate)||!(codec_pll_clk.rate%i2s_rate))
{
clk_set_parent_nolock(&clk_i2s_pll, &codec_pll_clk);
}
else
{
if(general_pll_clk.rate>codec_pll_clk.rate)
clk_set_parent_nolock(&clk_i2s_pll, &general_pll_clk);
else
clk_set_parent_nolock(&clk_i2s_pll, &codec_pll_clk);
}
}
static void __init rk30_clock_common_init(unsigned long gpll_rate,unsigned long cpll_rate)
@@ -3151,10 +3286,14 @@ static void __init rk30_clock_common_init(unsigned long gpll_rate,unsigned long
#else
clk_set_parent_nolock(&clk_uart_pll, &general_pll_clk);
#endif
//mac
clk_set_parent_nolock(&clk_mac_pll_div, &ddr_pll_clk);
if(!(gpll_rate%(50*MHZ)))
clk_set_parent_nolock(&clk_mac_pll_div, &general_pll_clk);
else if(!(ddr_pll_clk.rate%(50*MHZ)))
clk_set_parent_nolock(&clk_mac_pll_div, &ddr_pll_clk);
else
CRU_PRINTK_ERR("mac can't get 50mhz\n");
//hsadc
//auto pll sel
//clk_set_parent_nolock(&clk_hsadc_pll_div, &general_pll_clk);

View File

@@ -97,8 +97,8 @@ extern struct sys_timer rk30_timer;
enum _periph_pll {
periph_pll_1485mhz = 148500000,
periph_pll_297mhz = 297000000,
periph_pll_300mhz = 300000000,
periph_pll_1188mhz = 1188000000, /* for box*/
periph_pll_default = periph_pll_297mhz,
};
enum _codec_pll {
codec_pll_360mhz = 360000000, /* for HDMI */
@@ -107,9 +107,11 @@ enum _codec_pll {
codec_pll_504mhz = 504000000,
codec_pll_552mhz = 552000000, /* for HDMI */
codec_pll_600mhz = 600000000,
codec_pll_742_5khz = 742500000,
codec_pll_798mhz = 798000000,
codec_pll_default = codec_pll_798mhz,
codec_pll_1188mhz = 1188000000,
};
//has extern 27mhz
#define CLK_FLG_EXT_27MHZ (1<<0)
//max i2s rate
@@ -118,7 +120,25 @@ enum _codec_pll {
#define CLK_FLG_MAX_I2S_24576KHZ (1<<3)
#define CLK_FLG_MAX_I2S_49152KHZ (1<<4)
#define max_i2s_12288khz (CLK_FLG_MAX_I2S_12288KHZ/*|CLK_FLG_EXT_27MHZ*/)
#ifdef CONFIG_RK29_VMAC
#define RK30_CLOCKS_DEFAULT_FLAGS (CLK_FLG_MAX_I2S_12288KHZ/*|CLK_FLG_EXT_27MHZ*/)
#define periph_pll_default periph_pll_300mhz
#define codec_pll_default codec_pll_1188mhz
#else
#define RK30_CLOCKS_DEFAULT_FLAGS (CLK_FLG_MAX_I2S_12288KHZ/*|CLK_FLG_EXT_27MHZ*/)
#define codec_pll_default codec_pll_798mhz
#define periph_pll_default periph_pll_297mhz
#endif
#endif