From: cym Date: Tue, 7 May 2013 01:42:31 +0000 (+0800) Subject: rk3188 plus:add DDR support for rk3188 plus X-Git-Tag: firefly_0821_release~7152 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=05b38ce618a409edd09b023ecd4817834d29b6c6;p=firefly-linux-kernel-4.4.55.git rk3188 plus:add DDR support for rk3188 plus --- diff --git a/arch/arm/mach-rk30/ddr.c b/arch/arm/mach-rk30/ddr.c index 2dba5a41aadd..bd346f7a0c54 100755 --- a/arch/arm/mach-rk30/ddr.c +++ b/arch/arm/mach-rk30/ddr.c @@ -21,7 +21,7 @@ #include #include - +#include #include typedef uint32_t uint32; @@ -1452,10 +1452,34 @@ static __sramdata uint32_t clkr; static __sramdata uint32_t clkf; static __sramdata uint32_t clkod; -static __sramdata uint32_t dpllvaluel=0; -static __sramdata uint32_t gpllvaluel=0; +static __sramdata uint32_t dpllvaluel=0,gpllvaluel=0; static __sramdata uint32_t ddr_select_gpll_div=0; // 0-Disable, 1-1:1, 2-2:1, 4-4:1 -static __sramdata bool ddr_select_gpll=false; + +static __sramdata bool ddr_soc_is_rk3188_plus=false; + +typedef enum PLL_ID_Tag +{ + APLL=0, + DPLL, + CPLL, + GPLL, + PLL_MAX +}PLL_ID; + +uint32_t __sramlocalfunc ddr_get_pll_freq(PLL_ID pll_id) //APLL-1;CPLL-2;DPLL-3;GPLL-4 +{ + uint32_t ret = 0; + + // freq = (Fin/NR)*NF/OD + if(((pCRU_Reg->CRU_MODE_CON>>(pll_id*4))&3) == 1) // DPLL Normal mode + ret= 24 *((pCRU_Reg->CRU_PLL_CON[pll_id][1]&0xffff)+1) // NF = 2*(CLKF+1) + /((((pCRU_Reg->CRU_PLL_CON[pll_id][0]>>8)&0x3f)+1) // NR = CLKR+1 + *((pCRU_Reg->CRU_PLL_CON[pll_id][0]&0x3F)+1)); // OD = 2^CLKOD + else + ret = 24; + + return ret; +} /***************************************** NR NO NF Fout freq Step finally use @@ -1465,7 +1489,7 @@ NR NO NF Fout freq Step finally us 1 2 12.5 - 62.5 150MHz - 750MHz 12MHz 300MHz <= 600MHz 1 1 12.5 - 62.5 300MHz - 1500MHz 24MHz 600MHz <= 1200MHz ******************************************/ -uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set) +uint32_t __sramlocalfunc ddr_set_pll_3066(uint32_t nMHz, uint32_t set) { uint32_t ret = 0; int delay = 1000; @@ -1558,21 +1582,8 @@ uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set) if(!set) { - // freq = (Fin/NR)*NF/OD - if(((pCRU_Reg->CRU_MODE_CON>>4)&3) == 1) // DPLL Normal mode - dpllvaluel= 24 *((pCRU_Reg->CRU_PLL_CON[1][1]&0xffff)+1) // NF = 2*(CLKF+1) - /((((pCRU_Reg->CRU_PLL_CON[1][0]>>8)&0x3f)+1) // NR = CLKR+1 - *((pCRU_Reg->CRU_PLL_CON[1][0]&0x3F)+1)); // OD = 2^CLKOD - else - dpllvaluel = 24; - - // freq = (Fin/NR)*NF/OD - if(((pCRU_Reg->CRU_MODE_CON>>12)&3) == 1) // GPLL Normal mode - gpllvaluel= 24 *((pCRU_Reg->CRU_PLL_CON[3][1]&0xffff)+1) // NF = 2*(CLKF+1) - /((((pCRU_Reg->CRU_PLL_CON[3][0]>>8)&0x3f)+1) // NR = CLKR+1 - *((pCRU_Reg->CRU_PLL_CON[3][0]&0x3F)+1)); // OD = 2^CLKOD - else - gpllvaluel = 24; + dpllvaluel = ddr_get_pll_freq(DPLL); + gpllvaluel = ddr_get_pll_freq(GPLL); if(ddr_select_gpll_div > 0) { @@ -1624,14 +1635,16 @@ uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set) pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000; pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) | (0x1<<8) //clk_ddr_src = G PLL - | 2; //clk_ddr_src:clk_ddrphy = 4:1 + | 2; //clk_ddr_src:clk_ddrphy = 4:1 + dsb(); } if(ddr_select_gpll_div == 2) { pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000; pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) | (0x1<<8) //clk_ddr_src = G PLL - | 1; //clk_ddr_src:clk_ddrphy = 2:1 + | 1; //clk_ddr_src:clk_ddrphy = 2:1 + dsb(); } else { @@ -1639,15 +1652,15 @@ uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set) pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) | (0x1<<8) //clk_ddr_src = G PLL | 0; //clk_ddr_src:clk_ddrphy = 1:1 + dsb(); } - dsb(); } - else if(nMHz==dpllvaluel) + else if((nMHz==dpllvaluel) && (set == 1)) { // ddr_pll_clk: clk_ddr=1:1 pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) | (0x0<<8) //clk_ddr_src = DDR PLL - | 0; //clk_ddr_src:clk_ddrphy = 1:1 + | 0; //clk_ddr_src:clk_ddrphy = 1:1 dsb(); } else @@ -1670,19 +1683,167 @@ uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set) break; delay--; } + + if(set == 1) + pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) + | (0x0<<8) //clk_ddr_src = DDR PLL + | 0; //clk_ddr_src:clk_ddrphy = 1:1 + pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x1<<(pll_id*4)); //PLL normal + dsb(); + } + } + dsb(); +out: + return ret; +} + +/***************************************** +NR NO NF Fout freq Step finally use +1 8 12.5 - 62.5 37.5MHz - 187.5MHz 3MHz 50MHz <= 150MHz +1 6 12.5 - 62.5 50MHz - 250MHz 4MHz 150MHz <= 200MHz +1 4 12.5 - 62.5 75MHz - 375MHz 6MHz 200MHz <= 300MHz +1 2 12.5 - 62.5 150MHz - 750MHz 12MHz 300MHz <= 600MHz +1 1 12.5 - 62.5 300MHz - 1500MHz 24MHz 600MHz <= 1200MHz +******************************************/ +uint32_t __sramlocalfunc ddr_set_pll_rk3188_plus(uint32_t nMHz, uint32_t set) +{ + uint32_t ret = 0; + int delay = 1000; + uint32_t pll_id=1; //DPLL + + if(nMHz == 24) + { + ret = 24; + goto out; + } + + if(!set) + { + dpllvaluel = ddr_get_pll_freq(DPLL); + gpllvaluel = ddr_get_pll_freq(GPLL); + + if(ddr_select_gpll_div > 0) + { + if(ddr_select_gpll_div == 4) + ret = gpllvaluel/4; + else if(ddr_select_gpll_div == 2) + ret = gpllvaluel/2; + else + ret=gpllvaluel; + } + else + { + if(nMHz <= 150) + { + clkod = 8; + } + else if(nMHz <= 200) + { + clkod = 6; + } + else if(nMHz <= 300) + { + clkod = 4; + } + else if(nMHz <= 600) + { + clkod = 2; + } + else + { + clkod = 1; + } + clkr = 1; + clkf=(nMHz*clkr*clkod)/24; + ret = (24*clkf)/(clkr*clkod); + } + + } + else + { + if(ddr_select_gpll_div > 0) + { + if(ddr_select_gpll_div == 4) + { + pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000; + pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) + | (0x1<<8) //clk_ddr_src = G PLL + | 2; //clk_ddr_src:clk_ddrphy = 4:1 + dsb(); + } + if(ddr_select_gpll_div == 2) + { + pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000; + pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) + | (0x1<<8) //clk_ddr_src = G PLL + | 1; //clk_ddr_src:clk_ddrphy = 2:1 + dsb(); + } + else + { + pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000; + pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) + | (0x1<<8) //clk_ddr_src = G PLL + | 0; //clk_ddr_src:clk_ddrphy = 1:1 + dsb(); + } + } + else if((nMHz==dpllvaluel) && (set == 1)) + { + // ddr_pll_clk: clk_ddr=1:1 pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) + | (0x0<<8) //clk_ddr_src = DDR PLL + | 0; //clk_ddr_src:clk_ddrphy = 1:1 + dsb(); + } + else + { + pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x0<<(pll_id*4)); //PLL slow-mode + dsb(); + + pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_RESET; + ddr_delayus(1); + pCRU_Reg->CRU_PLL_CON[pll_id][0] = NR(clkr) | NO(clkod); + pCRU_Reg->CRU_PLL_CON[pll_id][1] = NF(clkf); + pCRU_Reg->CRU_PLL_CON[pll_id][2] = NB(clkf>>1); + ddr_delayus(1); + pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET; + dsb(); + while (delay > 0) + { + ddr_delayus(1); + if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5)) + break; + delay--; + } + + if(set == 1) + pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16) | (0x0<<8) //clk_ddr_src = DDR PLL | 0; //clk_ddr_src:clk_ddrphy = 1:1 pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x1<<(pll_id*4)); //PLL normal - dsb(); + dsb(); } } + dsb(); out: return ret; } +uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set) +{ +#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) + if(ddr_soc_is_rk3188_plus == true) + return ddr_set_pll_rk3188_plus(nMHz,set); + else + return ddr_set_pll_rk3066b(nMHz,set); +#else + return ddr_set_pll_3066(nMHz,set); +#endif +} + uint32_t ddr_get_parameter(uint32_t nMHz) { uint32_t tmp; @@ -3391,16 +3552,16 @@ void __sramlocalfunc ddr_set_pll_exit_3168(uint32 freq_slew,uint32_t dqstr_value ddr_data_training(); ddr_move_to_Access_state(); } -#endif +#endif -static bool ddr_dpll_status = true; +static __sramdata bool ddr_rk3188_dpll_is_good=true; #if defined(CONFIG_ARCH_RK3188) -void ddr_get_dpll_status(void) //DPLL fial rerurn 0;DPLL good return 1; -{ +bool ddr_get_dpll_status(void) //DPLL bad rerurn false;DPLL good return true; +{ if (rk_pll_flag() & 0x2) - ddr_dpll_status = false; - else - ddr_dpll_status = true; + return false; + else + return true; } #endif @@ -3412,7 +3573,6 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz) unsigned long flags; volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET; unsigned long save_sp; - uint32_t regvalue = pCRU_Reg->CRU_PLL_CON[0][0]; uint32_t freq; #if defined(CONFIG_ARCH_RK3066B) @@ -3424,21 +3584,11 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz) } #endif - // freq = (Fin/NR)*NF/OD - if((pCRU_Reg->CRU_MODE_CON&3) == 1) // CPLL Normal mode - freq = 24 *((pCRU_Reg->CRU_PLL_CON[0][1]&0xffff)+1) // NF = 2*(CLKF+1) - /((((regvalue>>8)&0x3f)+1) // NR = CLKR+1 - *((regvalue&0x3F)+1)); // OD = 2^CLKOD - else - freq = 24; - + freq = ddr_get_pll_freq(APLL); //APLL + loops_per_us = LPJ_100MHZ*freq / 1000000; -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - ret=ddr_set_pll_rk3066b(nMHz,0); -#else ret=ddr_set_pll(nMHz,0); -#endif ddr_get_parameter(ret); @@ -3483,11 +3633,7 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz) #endif /** 3. change frequence */ -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - ddr_set_pll_rk3066b(ret,1); -#else ddr_set_pll(ret,1); -#endif ddr_freq = ret; /** 5. Issues a Mode Exit command */ @@ -3507,86 +3653,33 @@ uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz) uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz) { uint32_t gpll_freq,gpll_div; - int delay = 1000; - uint32_t pll_id=1; //DPLL - if(((pCRU_Reg->CRU_MODE_CON>>12)&3) == 1) // GPLL Normal mode - gpllvaluel= 24 *((pCRU_Reg->CRU_PLL_CON[3][1]&0xffff)+1) // NF = 2*(CLKF+1) - /((((pCRU_Reg->CRU_PLL_CON[3][0]>>8)&0x3f)+1) // NR = CLKR+1 - *((pCRU_Reg->CRU_PLL_CON[3][0]&0x3F)+1)); // OD = 2^CLKOD - else - gpllvaluel = 24; + gpllvaluel = ddr_get_pll_freq(GPLL); if((200 < gpllvaluel) ||( gpllvaluel <1600)) //GPLL:200MHz~1600MHz { - if( gpllvaluel > 800) + if( gpllvaluel > 800) //800-1600MHz /4:200MHz-400MHz { gpll_freq = gpllvaluel/4; gpll_div = 4; } - else if( gpllvaluel > 400) + else if( gpllvaluel > 400) //400-800MHz /2:200MHz-400MHz { - gpll_freq = gpllvaluel/2; + gpll_freq = gpllvaluel/2; gpll_div = 2; } - else + else //200-400MHz /1:200MHz-400MHz { - gpll_freq = gpllvaluel; + gpll_freq = gpllvaluel; gpll_div = 1; } - - ddr_select_gpll_div=gpll_div; + + ddr_select_gpll_div=gpll_div; //select GPLL ddr_change_freq_sram(gpll_freq); ddr_select_gpll_div=0; - //set DPLL,when ddr_clock select GPLL - if(nMHz <= 150) - { - clkod = 14; - } - else if(nMHz <= 200) - { - clkod = 8; - } - else if(nMHz <= 300) - { - clkod = 6; - } - else if(nMHz <= 550) - { - clkod = 4; - } - else if(nMHz <= 1100) - { - clkod = 2; - } - else - { - clkod = 1; - } - clkr = 1; - clkf=(nMHz*clkr*clkod)/24; - - pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x0<<(pll_id*4)); //PLL slow-mode - dsb(); - - pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_RESET_RK3066B; - ddr_delayus(1); - pCRU_Reg->CRU_PLL_CON[pll_id][0] = NR_RK3066B(clkr) | NO_RK3066B(clkod); - pCRU_Reg->CRU_PLL_CON[pll_id][1] = NF_RK3066B(clkf); - // pCRU_Reg->CRU_PLL_CON[pll_id][2] = NB(clkf>>1); - ddr_delayus(1); - pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET_RK3066B; - dsb(); - while (delay > 0) - { - ddr_delayus(1); - if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5)) - break; - delay--; - } - pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x1<<(pll_id*4)); //PLL normal - //set DPLL end + ddr_set_pll(nMHz,0); //count DPLL + ddr_set_pll(nMHz,2); //lock DPLL only,but not select DPLL } else { @@ -3597,33 +3690,56 @@ uint32_t ddr_change_freq_gpll_dpll(uint32_t nMHz) } - +/***************************************** +if rk3188 DPLL is bad,use GPLL + GPLL DDR_CLCOK +1000MHz-2000MHz 4:250MHz-500MHz +800MHz-1000MHz 4:200MHz-250MHz 2:400MHz-500MHz +500MHz-800MHz 2:250MHz-400MHz +200MHz-500MHz 1:200MHz-500MHz +******************************************/ uint32_t ddr_change_freq(uint32_t nMHz) { - - if(ddr_dpll_status == false) + + if(ddr_rk3188_dpll_is_good == false) //if rk3188 DPLL is bad,use GPLL { - uint32_t gpll_div_4,gpll_div_2,gpll_div_1; - if(((pCRU_Reg->CRU_MODE_CON>>12)&3) == 1) // GPLL Normal mode - gpllvaluel= 24 *((pCRU_Reg->CRU_PLL_CON[3][1]&0xffff)+1) // NF = 2*(CLKF+1) - /((((pCRU_Reg->CRU_PLL_CON[3][0]>>8)&0x3f)+1) // NR = CLKR+1 - *((pCRU_Reg->CRU_PLL_CON[3][0]&0x3F)+1)); // OD = 2^CLKOD - else - gpllvaluel = 24; - - if(nMHz > 300) - ddr_select_gpll_div=2; - else - ddr_select_gpll_div=4; - - return ddr_change_freq_sram(gpllvaluel/ddr_select_gpll_div); - } + gpllvaluel = ddr_get_pll_freq(GPLL); + + if( (gpllvaluel < 200) ||(gpllvaluel > 2000)) + { + ddr_print("DPLL is bad and GPLL freq = %dMHz,Not suitable for ddr_clock\n",gpllvaluel); + return 0; + } + if(gpllvaluel > 1000) //GPLL:1000MHz-2000MHz + { + ddr_select_gpll_div=4; //DDR_CLCOK:250MHz-500MHz + } + else if(gpllvaluel > 800) //GPLL:800MHz-1000MHz + { + if(nMHz > 300) + ddr_select_gpll_div=2; //DDR_CLCOK:400MHz-500MHz + else + ddr_select_gpll_div=4; //DDR_CLCOK:200MHz-250MHz + } + else if(gpllvaluel > 500) //GPLL:500MHz-800MHz + { + ddr_select_gpll_div=2; //DDR_CLCOK:250MHz-400MHz + } + else //GPLL:200MHz-500MHz + { + ddr_select_gpll_div=1; //DDR_CLCOK:200MHz-500MHz + } + return ddr_change_freq_sram(gpllvaluel/ddr_select_gpll_div); + } + else + { #if defined(ENABLE_DDR_CLCOK_GPLL_PATH) && defined(CONFIG_ARCH_RK3188) - return ddr_change_freq_gpll_dpll(nMHz); + return ddr_change_freq_gpll_dpll(nMHz); #else - return ddr_change_freq_sram(nMHz); + return ddr_change_freq_sram(nMHz); #endif + } } EXPORT_SYMBOL(ddr_change_freq); @@ -3805,10 +3921,8 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq) uint32_t die=1; uint32_t gsr,dqstr; - ddr_print("version 1.00 20130427 \n"); -#if defined(CONFIG_ARCH_RK3188) - ddr_get_dpll_status(); -#endif + ddr_print("version 1.00 20130507 \n"); + mem_type = pPHY_Reg->DCR.b.DDRMD; ddr_speed_bin = dram_speed_bin; @@ -3818,6 +3932,11 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq) ddr_freq = clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000; ddr_sr_idle = 0; + +#if defined(CONFIG_ARCH_RK3188) + ddr_soc_is_rk3188_plus = soc_is_rk3188plus(); + ddr_rk3188_dpll_is_good = ddr_get_dpll_status(); +#endif switch(mem_type) { case DDR3: @@ -3848,14 +3967,15 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq) (ddr_get_cap()>>20)); ddr_adjust_config(mem_type); - if(ddr_dpll_status == true) { - if(freq != 0) - value=ddr_change_freq(freq); - else - value=ddr_change_freq(clk_get_rate(clk_get(NULL, "ddr"))/1000000); - } - clk_set_rate(clk_get(NULL, "ddr_pll"), 0); - ddr_print("init success!!! freq=%luMHz\n", clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000); + if(ddr_rk3188_dpll_is_good == true) + { + if(freq != 0) + value=ddr_change_freq(freq); + else + value=ddr_change_freq(clk_get_rate(clk_get(NULL, "ddr"))/1000000); + } + clk_set_rate(clk_get(NULL, "ddr"), 0); + ddr_print("init success!!! freq=%luMHz\n", clk_get_rate(clk_get(NULL, "ddr"))/1000000); for(value=0;value<4;value++) {