#include <mach/sram.h>
#include <mach/ddr.h>
-
+#include <mach/cpu.h>
#include <plat/efuse.h>
typedef uint32_t uint32;
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
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;
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)
{
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
{
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
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;
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
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)
}
#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);
#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 */
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
{
}
-
+/*****************************************
+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);
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;
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:
(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++)
{