rk2928:sdk: codec pll for sclk_lcdc only, aclk_vio_pre need yxj fixed, move other...
authorchenxing <chenxing@rock-chips.com>
Mon, 20 Aug 2012 06:22:55 +0000 (14:22 +0800)
committerchenxing <chenxing@rock-chips.com>
Mon, 20 Aug 2012 06:22:55 +0000 (14:22 +0800)
arch/arm/mach-rk2928/clock_data.c

index a1c3440bdbd456129e284176c97780b7d3e4b5d8..1a734cdb94a44be504f024f7d9b27864d234ab40 100644 (file)
@@ -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)
 {