From ebb93cff36c953ba0eebe4b9c6a8d71e54b2be4d Mon Sep 17 00:00:00 2001 From: chenxing Date: Mon, 20 Aug 2012 14:22:55 +0800 Subject: [PATCH] rk2928:sdk: codec pll for sclk_lcdc only, aclk_vio_pre need yxj fixed, move other clks to general pll --- arch/arm/mach-rk2928/clock_data.c | 194 ++++++++++++++++++------------ 1 file changed, 119 insertions(+), 75 deletions(-) diff --git a/arch/arm/mach-rk2928/clock_data.c b/arch/arm/mach-rk2928/clock_data.c index a1c3440bdbd4..1a734cdb94a4 100644 --- a/arch/arm/mach-rk2928/clock_data.c +++ b/arch/arm/mach-rk2928/clock_data.c @@ -291,17 +291,18 @@ static unsigned long pll_clk_recalc(u8 pll_id, unsigned long parent_rate) if (PLLS_IN_NORM(pll_id)) { u32 pll_con0 = cru_readl(PLL_CONS(pll_id, 0)); u32 pll_con1 = cru_readl(PLL_CONS(pll_id, 1)); + u32 pll_con2 = cru_readl(PLL_CONS(pll_id, 2)); //integer mode rate64 = (u64)parent_rate * PLL_GET_FBDIV(pll_con0); do_div(rate64, PLL_GET_REFDIV(pll_con1)); if (FRAC_MODE == dsmp) { //fractional mode - frac_rate64 = (u64)parent_rate * PLL_GET_FRAC(pll_con1); + frac_rate64 = (u64)parent_rate * PLL_GET_FRAC(pll_con2); do_div(frac_rate64, PLL_GET_REFDIV(pll_con1)); rate64 += frac_rate64 >> 24; - CLKDATA_DBG("%s id=%d frac_rate=%llu(0x%08x/2^24) by pass mode\n", - __func__, pll_id, frac_rate64, PLL_GET_FRAC(pll_con1)); + CLKDATA_DBG("%s id=%d frac_rate=%llu(%08x/2^24) by pass mode\n", + __func__, pll_id, frac_rate64 >> 24, PLL_GET_FRAC(pll_con2)); } do_div(rate64, PLL_GET_POSTDIV1(pll_con0)); do_div(rate64, PLL_GET_POSTDIV2(pll_con1)); @@ -322,7 +323,8 @@ static unsigned long plls_clk_recalc(struct clk *clk) /************************clk set rate*********************************/ static int clksel_set_rate_freediv(struct clk *clk, unsigned long rate) { - u32 div; + u32 div = 0; + for (div = 0; div < clk->div_max; div++) { u32 new_rate = clk->parent->rate / (div + 1); if (new_rate <= rate) { @@ -700,30 +702,55 @@ static int pll_clk_get_set(unsigned long fin_hz,unsigned long fout_hz, { // FIXME set postdiv1/2 always 1 u32 gcd; - + u64 fin_64, frac_64; + u32 f_frac; if(!fin_hz || !fout_hz || fout_hz == fin_hz) return -1; - fin_hz /= MHZ; - fout_hz /= MHZ; - gcd = clk_gcd(fin_hz, fout_hz); - *refdiv = fin_hz / gcd; - *fbdiv = fout_hz / gcd; - *postdiv1 = 1; - *postdiv2 = 1; - - *frac = 0; + if (fin_hz / MHZ * MHZ == fin_hz && fout_hz /MHZ * MHZ == fout_hz) { + fin_hz /= MHZ; + fout_hz /= MHZ; + gcd = clk_gcd(fin_hz, fout_hz); + *refdiv = fin_hz / gcd; + *fbdiv = fout_hz / gcd; + *postdiv1 = 1; + *postdiv2 = 1; - CLKDATA_DBG("fin=%lu,fout=%lu,gcd=%u,refdiv=%u,fbdiv=%u,postdiv1=%u,postdiv2=%u,frac=%u\n", - fin_hz, fout_hz, gcd, *refdiv, *fbdiv, *postdiv1, *postdiv2, *frac); + *frac = 0; + CLKDATA_DBG("fin=%lu,fout=%lu,gcd=%u,refdiv=%u,fbdiv=%u,postdiv1=%u,postdiv2=%u,frac=%u\n", + fin_hz, fout_hz, gcd, *refdiv, *fbdiv, *postdiv1, *postdiv2, *frac); + } else { + CLKDATA_DBG("******frac div running, fin_hz=%lu, fout_hz=%lu, fin_mhz=%lu, fout_mhz=%lu\n", + fin_hz, fout_hz, fin_hz / MHZ * MHZ, fout_hz / MHZ * MHZ); + gcd = clk_gcd(fin_hz / MHZ, fout_hz / MHZ); + *refdiv = fin_hz / MHZ / gcd; + *fbdiv = fout_hz / MHZ / gcd; + *postdiv1 = 1; + *postdiv2 = 1; + + *frac = 0; + + f_frac = (fout_hz % MHZ); + fin_64 = fin_hz; + do_div(fin_64, (u64)*refdiv); + frac_64 = (u64)f_frac << 24; + do_div(frac_64, fin_64); + *frac = (u32) frac_64; + CLKDATA_DBG("frac_64=%llx, frac=%u\n", frac_64, *frac); + } return 0; } static int pll_set_con(u8 id, u32 refdiv, u32 fbdiv, u32 postdiv1, u32 postdiv2, u32 frac) { struct pll_clk_set temp_clk_set; - temp_clk_set.pllcon0 = PLL_SET_FBDIV(fbdiv) | PLL_SET_POSTDIV1(postdiv1) ; + temp_clk_set.pllcon0 = PLL_SET_FBDIV(fbdiv) | PLL_SET_POSTDIV1(postdiv1); temp_clk_set.pllcon1 = PLL_SET_REFDIV(refdiv) | PLL_SET_POSTDIV2(postdiv2); + if (frac != 0) { + temp_clk_set.pllcon1 |= PLL_SET_DSMPD(0); + } else { + temp_clk_set.pllcon1 |= PLL_SET_DSMPD(1); + } temp_clk_set.pllcon2 = PLL_SET_FRAC(frac); temp_clk_set.rst_dly = 1500; CLKDATA_DBG("setting....\n"); @@ -836,6 +863,7 @@ static int cpll_clk_set_rate(struct clk *clk, unsigned long rate) CLKDATA_DBG("%s get fin=%lu, fout=%lu, rate=%lu, refdiv=%u, fbdiv=%u, postdiv1=%u, postdiv2=%u", __func__, fin_hz, fout_hz, rate, refdiv, fbdiv, postdiv1, postdiv2); pll_set_con(pll_data->id, refdiv, fbdiv, postdiv1, postdiv2, frac); + } CLKDATA_DBG("setting OK\n"); @@ -1132,7 +1160,8 @@ static struct clk aclk_vepu = { .gate_idx = CLK_GATE_ACLK_VEPU_SRC, .recalc = clksel_recalc_div, .clksel_con = CRU_CLKSELS_CON(32), - .set_rate = clkset_rate_freediv_autosel_parents, + //.set_rate = clkset_rate_freediv_autosel_parents, + .set_rate = clksel_set_rate_freediv, CRU_DIV_SET(0x1f, 0, 32), CRU_SRC_SET(0x1, 7), CRU_PARENTS_SET(clk_aclk_vepu_parents), @@ -1143,7 +1172,8 @@ static struct clk aclk_vdpu = { .mode = gate_mode, .gate_idx = CLK_GATE_ACLK_VDPU_SRC, .recalc = clksel_recalc_div, - .set_rate = clkset_rate_freediv_autosel_parents, + //.set_rate = clkset_rate_freediv_autosel_parents, + .set_rate = clksel_set_rate_freediv, .clksel_con = CRU_CLKSELS_CON(32), CRU_DIV_SET(0x1f, 8, 32), CRU_SRC_SET(0x1, 15), @@ -1169,7 +1199,7 @@ static struct clk hclk_vdpu = { static struct clk *clk_aclk_vio_pre_parents[] = SELECT_FROM_2PLLS_CG; static struct clk aclk_vio_pre = { .name = "aclk_vio_pre", - .parent = &clk_cpu_div, + .parent = &general_pll_clk, .mode = gate_mode, .gate_idx = CLK_GATE_ACLK_VIO_SRC, .recalc = clksel_recalc_div, @@ -1374,6 +1404,17 @@ static struct clk clk_emmc_drv = { #endif /****************lcdc*******************/ // DO NOT USE ARM_PLL +static int sclk_lcdc_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = 0; + struct clk *parent; + + CLKDATA_DBG("enter %s clk=%s, rate=%lu\n", __func__, clk->name, rate); + parent = clk->parent; + ret = clk_set_rate_nolock(parent, rate); + set_cru_bits_w_msk(0, clk->div_mask, clk->div_shift, clk->clksel_con); + return ret; +} static struct clk *dclk_lcdc_parents[] = {&codec_pll_clk, &general_pll_clk}; static struct clk dclk_lcdc = { .name = "dclk_lcdc", @@ -1381,7 +1422,8 @@ static struct clk dclk_lcdc = { .mode = gate_mode, .gate_idx = CLK_GATE_DCLK_LCDC0_SRC, .recalc = clksel_recalc_div, - .set_rate = clkset_rate_freediv_autosel_parents, + //.set_rate = clkset_rate_freediv_autosel_parents, + .set_rate = clksel_set_rate_freediv, .clksel_con = CRU_CLKSELS_CON(27), CRU_DIV_SET(0xff, 8, 256), CRU_SRC_SET(0x3, 0), @@ -1394,7 +1436,8 @@ static struct clk sclk_lcdc = { .mode = gate_mode, .gate_idx = CLK_GATE_SCLK_LCDC_SRC, .recalc = clksel_recalc_div, - .set_rate = clkset_rate_freediv_autosel_parents, + //.set_rate = clkset_rate_freediv_autosel_parents, + .set_rate = sclk_lcdc_set_rate, .clksel_con = CRU_CLKSELS_CON(28), CRU_DIV_SET(0xff, 8, 256), CRU_SRC_SET(0x1, 0), @@ -1438,7 +1481,8 @@ static struct clk clk_cif_out_div = { .mode = gate_mode, .gate_idx = CLK_GATE_CIF_OUT_SRC, .recalc = clksel_recalc_div, - .set_rate = clkset_rate_freediv_autosel_parents, + //.set_rate = clkset_rate_freediv_autosel_parents, + .set_rate = clksel_set_rate_freediv, .clksel_con = CRU_CLKSELS_CON(29), CRU_SRC_SET(0x1, 0), CRU_DIV_SET(0x1f, 1, 32), @@ -1625,7 +1669,8 @@ static struct clk clk_gpu_pre = { .mode = gate_mode, .gate_idx = CLK_GATE_GPU_PRE, .recalc = clksel_recalc_div, - .set_rate = clkset_rate_freediv_autosel_parents, + //.set_rate = clkset_rate_freediv_autosel_parents, + .set_rate = clksel_set_rate_freediv, .round_rate = clk_freediv_round_autosel_parents_rate, .clksel_con = CRU_CLKSELS_CON(34), CRU_SRC_SET(0x1, 8), @@ -1824,8 +1869,7 @@ GATE_CLK(aclk_dma2, aclk_periph_pre, ACLK_DMAC2); GATE_CLK(aclk_peri_niu, aclk_periph_pre, ACLK_PERI_NIU); GATE_CLK(aclk_cpu_peri, aclk_periph_pre, ACLK_CPU_PERI); GATE_CLK(aclk_peri_axi_matrix, aclk_periph_pre, ACLK_PERI_AXI_MATRIX); -//FIXME -//GATE_CLK(aclk_gps, aclk_periph_pre, ACLK_GPS); +GATE_CLK(aclk_gps, aclk_periph_pre, ACLK_GPS); /*************************hclk_periph***********************/ GATE_CLK(hclk_peri_axi_matrix, hclk_periph_pre, HCLK_PERI_AXI_MATRIX); @@ -2094,8 +2138,7 @@ static struct clk_lookup clks[] = { CLK_GATE_NODEV(aclk_peri_niu), CLK_GATE_NODEV(aclk_cpu_peri), CLK_GATE_NODEV(aclk_peri_axi_matrix), - //FIXME - //CLK_GATE_NODEV(aclk_gps), + CLK_GATE_NODEV(aclk_gps), CLK_GATE_NODEV(hclk_peri_axi_matrix), CLK_GATE_NODEV(hclk_peri_ahb_arbi), @@ -2359,11 +2402,11 @@ struct clk_dump_ops dump_ops={ static void periph_clk_set_init(void) { unsigned long aclk_p, hclk_p, pclk_p; - unsigned long ppll_rate=general_pll_clk.rate; + unsigned long gpll_rate=general_pll_clk.rate; //aclk 148.5 /* general pll */ - switch (ppll_rate) { + switch (gpll_rate) { case 148500* KHZ: aclk_p = 148500*KHZ; hclk_p = aclk_p>>1; @@ -2375,13 +2418,13 @@ static void periph_clk_set_init(void) pclk_p = aclk_p>>2; case 297 * MHZ: - aclk_p = ppll_rate>>1; - hclk_p = aclk_p>>0; + aclk_p = gpll_rate>>0; + hclk_p = aclk_p>>1; pclk_p = aclk_p>>1; break; case 300 * MHZ: - aclk_p = ppll_rate>>1; + aclk_p = gpll_rate>>1; hclk_p = aclk_p>>0; pclk_p = aclk_p>>1; break; @@ -2391,10 +2434,10 @@ static void periph_clk_set_init(void) pclk_p = 75 * MHZ; break; } - clk_set_parent_nolock(&aclk_periph_pre, &general_pll_clk); - clk_set_rate_nolock(&aclk_periph_pre, aclk_p); - clk_set_rate_nolock(&hclk_periph_pre, hclk_p); - clk_set_rate_nolock(&pclk_periph_pre, pclk_p); + clk_set_parent_nolock(&peri_aclk, &general_pll_clk); + clk_set_rate_nolock(&peri_aclk, aclk_p); + clk_set_rate_nolock(&peri_hclk, hclk_p); + clk_set_rate_nolock(&peri_pclk, pclk_p); } @@ -2408,37 +2451,32 @@ void rk2928_clock_common_i2s_init(void) unsigned long i2s_rate; //struct clk *max_clk,*min_clk; //20 times - if(rk2928_clock_flags&CLK_FLG_MAX_I2S_49152KHZ) - { - i2s_rate=49152000; - }else if(rk2928_clock_flags&CLK_FLG_MAX_I2S_24576KHZ) - { - i2s_rate=24576000; - } - else if(rk2928_clock_flags&CLK_FLG_MAX_I2S_22579_2KHZ) - { - i2s_rate=22579000; - } - else if(rk2928_clock_flags&CLK_FLG_MAX_I2S_12288KHZ) - { - i2s_rate=12288000; - } - else - { - i2s_rate=49152000; + if(rk2928_clock_flags & CLK_FLG_MAX_I2S_49152KHZ) { + i2s_rate = 49152000; + + } else if(rk2928_clock_flags & CLK_FLG_MAX_I2S_24576KHZ) { + i2s_rate = 24576000; + + } else if(rk2928_clock_flags & CLK_FLG_MAX_I2S_22579_2KHZ) { + i2s_rate = 22579000; + + } else if(rk2928_clock_flags & CLK_FLG_MAX_I2S_12288KHZ) { + i2s_rate = 12288000; + + } else { + i2s_rate = 49152000; } - if(((i2s_rate*20)<=general_pll_clk.rate)||!(general_pll_clk.rate%i2s_rate)) - { + 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)) - { + + } 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) + + } 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); @@ -2447,9 +2485,8 @@ void rk2928_clock_common_i2s_init(void) } static void __init rk2928_clock_common_init(unsigned long gpll_rate,unsigned long cpll_rate) { - CLKDATA_DBG("ENTER %s\n", __func__); - clk_set_rate_nolock(&clk_core_pre, 600 * MHZ);//816? + clk_set_rate_nolock(&clk_core_pre, 816 * MHZ);//816 //general clk_set_rate_nolock(&general_pll_clk, gpll_rate); //code pll @@ -2478,7 +2515,6 @@ static void __init rk2928_clock_common_init(unsigned long gpll_rate,unsigned lon clk_set_parent_nolock(&clk_mac_pll_div, &ddr_pll_clk); else CRU_PRINTK_ERR("mac can't get 50mhz\n"); -#endif //hsadc //auto pll sel //clk_set_parent_nolock(&clk_hsadc_pll_div, &general_pll_clk); @@ -2488,27 +2524,35 @@ static void __init rk2928_clock_common_init(unsigned long gpll_rate,unsigned lon //lcdc0 lcd auto sel pll //clk_set_parent_nolock(&dclk_lcdc0_div, &general_pll_clk); +#endif //cif clk_set_parent_nolock(&clk_cif_out_div, &general_pll_clk); + // FIXME yxj this plase cause display unusual + //clk_set_parent_nolock(&aclk_vio_pre, &general_pll_clk); + //axi lcdc auto sel //clk_set_parent_nolock(&aclk_lcdc0, &general_pll_clk); //clk_set_parent_nolock(&aclk_lcdc1, &general_pll_clk); // FIXME -#if 0 - clk_set_rate_nolock(&aclk_lcdc0_ipp_parent, 300*MHZ); - clk_set_rate_nolock(&aclk_lcdc1_rga_parent, 300*MHZ); -#endif + + clk_set_rate_nolock(&aclk_vio_pre, 300*MHZ); //axi vepu auto sel - //clk_set_parent_nolock(&aclk_vepu, &general_pll_clk); - //clk_set_parent_nolock(&aclk_vdpu, &general_pll_clk); + clk_set_parent_nolock(&aclk_vepu, &general_pll_clk); + clk_set_parent_nolock(&aclk_vdpu, &general_pll_clk); clk_set_rate_nolock(&aclk_vepu, 300*MHZ); clk_set_rate_nolock(&aclk_vdpu, 300*MHZ); //gpu auto sel - //clk_set_parent_nolock(&clk_gpu, &general_pll_clk); - // + clk_set_parent_nolock(&clk_gpu_pre, &general_pll_clk); + + clk_set_parent_nolock(&clk_cpu_div, &general_pll_clk); + + clk_set_parent_nolock(&clk_sdmmc0, &general_pll_clk); + clk_set_parent_nolock(&clk_sdio, &general_pll_clk); + clk_set_parent_nolock(&clk_emmc, &general_pll_clk); + clk_set_parent_nolock(&dclk_lcdc, &general_pll_clk); } void __init _rk2928_clock_data_init(unsigned long gpll,unsigned long cpll,int flags) { -- 2.34.1