rk30: ddr.c support for rk3066b
authorcym <cym@rock-chips.com>
Mon, 3 Sep 2012 09:22:35 +0000 (17:22 +0800)
committercym <cym@rock-chips.com>
Mon, 3 Sep 2012 09:22:35 +0000 (17:22 +0800)
arch/arm/mach-rk30/common.c
arch/arm/mach-rk30/ddr.c
arch/arm/mach-rk30/ddr_freq.c

index 9e47f426d4842b76d0d4b06a69e94d8a6f3e972c..48ccd49c4ff559778a3917773407a61a0eb1b23e 100755 (executable)
@@ -133,8 +133,8 @@ void __init rk30_map_io(void)
        rk29_sram_init();
        board_clock_init();
        rk30_l2_cache_init();
-#if !defined(CONFIG_ARCH_RK3066B)
        ddr_init(DDR_TYPE, DDR_FREQ);
+#if !defined(CONFIG_ARCH_RK3066B)
        clk_disable_unused();
 #endif
        rk30_iomux_init();
index db644378fc36cf5a24e6b70093fe8989522707de..4a4d8f1cd6f5260a49d660301c5d675ef2b0de9a 100755 (executable)
@@ -38,6 +38,7 @@ typedef uint32_t uint32;
 #define SysSrv_DdrTiming        (RK30_CPU_AXI_BUS_BASE+0x0c)
 #define SysSrv_DdrMode          (RK30_CPU_AXI_BUS_BASE+0x10)
 #define SysSrv_ReadLatency      (RK30_CPU_AXI_BUS_BASE+0x14)
+#define ROM_CHIP_ID_ADDR    (RK30_ROM_BASE+0x27f0)
 
 #define ddr_print(x...) printk( "DDR DEBUG: " x )
 
@@ -228,6 +229,14 @@ typedef volatile struct tagPMU_FILE
 #define NO(n)      ((0xF<<16) | ((n)-1))
 #define NF(n)      ((0x1FFF<<16) | ((n)-1))
 #define NB(n)      ((0xFFF<<16) | ((n)-1))
+
+//RK3066B
+#define PLL_RESET_RK3066B  (((0x1<<1)<<16) | (0x1<<1))
+#define PLL_DE_RESET_RK3066B  (((0x1<<1)<<16) | (0x0<<1))
+#define NR_RK3066B(n)      ((0x3F<<(8+16)) | (((n)-1)<<8))
+#define NO_RK3066B(n)      ((0x3F<<16) | ((n)-1))
+#define NF_RK3066B(n)      ((0xFFFF<<16) | ((n)-1))
+
  //CRU Registers
 typedef volatile struct tagCRU_STRUCT
 {
@@ -288,6 +297,33 @@ typedef volatile struct tagREG_FILE
 
 #define pGRF_Reg ((pREG_FILE)REG_FILE_BASE_ADDR)
 
+//REG FILE registers
+typedef volatile struct tagREG_FILE_RK3066B
+{
+    GPIO_LH_T GRF_GPIO_DIR[4];
+    GPIO_LH_T GRF_GPIO_DO[4];
+    GPIO_LH_T GRF_GPIO_EN[4];
+    GPIO_IOMUX_T GRF_GPIO_IOMUX[4];
+    uint32 GRF_SOC_CON[3];
+    uint32 GRF_SOC_STATUS0;
+    uint32 GRF_DMAC0_CON[3];
+    uint32 GRF_DMAC1_CON[4];
+    uint32 reserved0[(0xec-0xcc)/4];
+    uint32 GRF_DDRC_CON0;
+    uint32 GRF_DDRC_STAT;
+    uint32 GRF_IO_CON[5];
+    uint32 reserved1;
+    uint32 GRF_UOC0_CON[4];
+    uint32 GRF_UOC1_CON[4];
+    uint32 GRF_UOC2_CON[2];
+    uint32 reserved2;
+    uint32 GRF_UOC3_CON[2];
+    uint32 GRF_HSIC_STAT;
+    uint32 GRF_OS_REG[8];
+} REG_FILE_RK3066B, *pREG_FILE_RK3066B;
+
+#define pGRF_Reg_RK3066B ((pREG_FILE_RK3066B)REG_FILE_BASE_ADDR)
+
 //SCTL
 #define INIT_STATE                     (0)
 #define CFG_STATE                      (1)
@@ -981,7 +1017,9 @@ uint32_t __sramdata ddr3_tRC_tFAW[22]={
 
     ((53<<16)|50)  //DDR3_DEFAULT
 };
+
 __sramdata uint32_t mem_type;    // 0:LPDDR, 1:DDR, 2:DDR2, 3:DDR3, 4:LPDDR2
+__sramdata bool chip_rk3066b_flag=false;    
 static __sramdata uint32_t ddr_speed_bin;    // used for ddr3 only
 static __sramdata uint32_t ddr_capability_per_die;  // one chip cs capability
 static __sramdata uint32_t ddr_freq;
@@ -1023,9 +1061,19 @@ uint32 ddr_get_row(void)
 
     i = *(volatile uint32*)SysSrv_DdrConf;
     row = ddr_cfg_2_rbc[i].row;
-    if(pGRF_Reg->GRF_SOC_CON[2] &  (1<<1))
+    if(chip_rk3066b_flag == true)
+    {
+        if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] &  (1<<1))
+        {
+            row += 1;
+        }
+    }
+    else
     {
-        row += 1;
+        if(pGRF_Reg->GRF_SOC_CON[2] &  (1<<1))
+        {
+            row += 1;
+        }
     }
     return row;
 }
@@ -1360,18 +1408,101 @@ uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set)
         ddr_delayus(1);
         pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET;
         dsb();
-        while (delay > 0) 
+        while (delay > 0)
         {
            ddr_delayus(1);
-               if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
-                       break;
-               delay--;
-       }
-        
+            if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
+            break;
+            delay--;
+        }
         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();
+    }
+out:
+    return ret;
+}
+
+
+/*****************************************
+RK3066B
+NR   NO     NF                      Fout                       freq Step     finally use
+1    14     46 - 91          78MHz  -   157MHz          1.7MHz        78MHz<= 150MHz
+1    8      46 - 91          137MHz  -  275MHz          3MHz          150MHz<= 200MHz
+1    6      46 - 91          183MHz   - 366MHz          4MHz          200MHz<= 300MHz
+1    4      46 - 91          275MHz   - 550MHz          6MHz          300MHz<= 550MHz
+1    2      46 - 91          550MHz   - 1100MHz         12MHz         550MHz<= 1100MHz
+1    1      46 - 91          1100MHz  - 2200MHz         24MHz         1100MHz<= 2200MHz
+******************************************/
+uint32_t __sramlocalfunc ddr_set_pll_rk3600b(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)
+    {
+        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;
+        ret = (24*clkf)/(clkr*clkod);
+    }
+    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_RK3066B;
+        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_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();
     }
@@ -2798,9 +2929,19 @@ __sramfunc void ddr_adjust_config(uint32_t dram_type)
     ddr_move_to_Config_state();
 
     //extend capability for debug
-    if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1))
+    if(chip_rk3066b_flag == true)
+    {
+        if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] & (0x1<<1))
+        {
+            pGRF_Reg_RK3066B->GRF_SOC_CON[2] = rank_to_row15_en;
+        }
+    }
+    else
     {
-        pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en;
+        if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1))
+        {
+            pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en;
+        }
     }
 
     //set data training address
@@ -2985,15 +3126,18 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
 
      // 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]&0x1fff)+1)    // NF = 2*(CLKF+1)
+         freq = 24 *((pCRU_Reg->CRU_PLL_CON[0][1]&0xffff)+1)    // NF = 2*(CLKF+1)
                 /((((regvalue>>8)&0x3f)+1)           // NR = CLKR+1
-                *((regvalue&0xF)+1));             // OD = 2^CLKOD
+                *((regvalue&0x3F)+1));             // OD = 2^CLKOD
      else
         freq = 24;
         
     loops_per_us = LPJ_100MHZ*freq / 1000000;
-    
-    ret=ddr_set_pll(nMHz,0);
+
+    if(chip_rk3066b_flag == true)
+        ret=ddr_set_pll_rk3600b(nMHz,0);
+    else
+        ret=ddr_set_pll(nMHz,0);
     ddr_get_parameter(ret);
 
     /** 1. Make sure there is no host access */
@@ -3014,7 +3158,14 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     n= pCRU_Reg->CRU_PLL_CON[0][0];
     n= pPMU_Reg->PMU_WAKEUP_CFG[0];
     n= *(volatile uint32_t *)SysSrv_DdrConf;
-    n= pGRF_Reg->GRF_SOC_STATUS0;
+    if(chip_rk3066b_flag == true)
+    {
+        n= pGRF_Reg_RK3066B->GRF_SOC_STATUS0;
+    }
+    else
+    {
+        n= pGRF_Reg->GRF_SOC_STATUS0;
+    }
     dsb();
 
     /** 2. ddr enter self-refresh mode or precharge power-down mode */
@@ -3022,7 +3173,10 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     ddr_selfrefresh_enter(ret);
 
     /** 3. change frequence  */
-    ddr_set_pll(ret,1);
+    if(chip_rk3066b_flag == true)
+        ddr_set_pll_rk3600b(ret,1);
+    else
+        ddr_set_pll(ret,1);
     ddr_freq = ret;
     
     /** 5. Issues a Mode Exit command   */
@@ -3092,9 +3246,17 @@ void __sramfunc ddr_resume(void)
     while (delay > 0) 
     {
            ddr_delayus(1);
-               if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
-                       break;
-               delay--;
+        if(chip_rk3066b_flag == true)
+        {
+            if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5))
+                break;
+        }
+        else
+        {
+            if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
+                break;
+        }
+        delay--;
        }
     
     pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) +  16))  | (0x1<<(1*4));   //PLL normal
@@ -3127,9 +3289,19 @@ uint32 ddr_get_cap(void)
             break;
     }
     row = ddr_cfg_2_rbc[i].row;
-    if(pGRF_Reg->GRF_SOC_CON[2] &  (1<<1))
+    if(*(volatile uint32_t *)(ROM_CHIP_ID_ADDR+0x0c)  == 0x56313030)
     {
-        row += 1;
+        if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] &  (1<<1))
+        {
+            row += 1;
+        }
+    }
+    else
+    {
+        if(pGRF_Reg->GRF_SOC_CON[2] &  (1<<1))
+        {
+            row += 1;
+        }
     }
 
     return (1 << (row+(ddr_cfg_2_rbc[i].col)+(ddr_cfg_2_rbc[i].bank)+2))*cs;
@@ -3225,7 +3397,15 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq)
     uint32_t cs,die=1;
     uint32_t gsr,dqstr;
 
-    ddr_print("version 1.00 20120822 \n");
+    ddr_print("version 1.00 20120903 \n");
+
+    if(*(volatile uint32_t *)(ROM_CHIP_ID_ADDR+0x0c)  == 0x56313030)
+    {
+        chip_rk3066b_flag=true;
+        ddr_print("RK3066B \n");
+    }
+    else
+        chip_rk3066b_flag=false;
 
     mem_type = pPHY_Reg->DCR.b.DDRMD;
     ddr_speed_bin = dram_speed_bin;
index 5a3eef8f02b1a3b0802fa0ae451e76a02ed8d8d2..bf87a3db0f9dd0278d10059afd2c039d84bfd04d 100644 (file)
@@ -88,21 +88,22 @@ out:
 
 uint32_t ddr_set_rate(uint32_t nMHz)
 {
-       _ddr_change_freq(nMHz);
-       return 0;
+    nMHz = _ddr_change_freq(nMHz);
+    return nMHz;
 }
 
-
 #ifdef CONFIG_HAS_EARLYSUSPEND
+static uint32_t ddr_resume_freq=DDR_FREQ;
+static uint32_t ddr_suspend_freq=120;
 static void ddr_early_suspend(struct early_suspend *h)
 {
     uint32_t value;
 
     //Enable auto self refresh  0x01*32 DDR clk cycle
     ddr_set_auto_self_refresh(true);
-
-    value = _ddr_change_freq(120);
-
+    
+    ddr_resume_freq=clk_get_rate(ddr.ddr_pll)/1000000;
+    value = ddr_set_rate(ddr_suspend_freq);
     ddr_print("init success!!! freq=%dMHz\n", value);
 
     return;
@@ -115,8 +116,7 @@ static void ddr_late_resume(struct early_suspend *h)
     //Disable auto self refresh
     ddr_set_auto_self_refresh(false);
 
-    value = _ddr_change_freq(DDR_FREQ);
-
+    value = ddr_set_rate(ddr_resume_freq);
     ddr_print("init success!!! freq=%dMHz\n", value);
 
     return;
@@ -173,13 +173,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                 p=strsep(&cookie_pot,"M");
                 value = simple_strtol(p,NULL,10);
                 printk("change!!! freq=%dMHz\n", value);
-                cpu1_online=cpu_online(1);
-                if(cpu1_online)
-                    cpu_down(1);
-                value=ddr_change_freq(value);
-                if(cpu1_online)
-                    cpu_up(1);
+                value=ddr_set_rate(value);
                 printk("success!!! freq=%dMHz\n", value);
+                msleep(32);
                 printk("\n");
             }
             else
@@ -216,16 +212,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                     }while(value < value1);
 
                     printk("change!!! freq=%dMHz\n", value);
-
-                    cpu1_online=cpu_online(1);
-                    if(cpu1_online)
-                        cpu_down(1);
-                    msleep(32);
-                    value=ddr_change_freq(value);
-                    if(cpu1_online)
-                        cpu_up(1);
+                    value=ddr_set_rate(value);
                     printk("success!!! freq=%dMHz\n", value);
-
+                    msleep(32);
                     count++;
                 }
 
@@ -269,14 +258,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                     }
 
                     printk("change!!! freq=%dMHz\n", value);
-                    cpu1_online=cpu_online(1);
-                    if(cpu1_online)
-                        cpu_down(1);
-                    msleep(32);
-                    value=ddr_change_freq(value);
-                    if(cpu1_online)
-                        cpu_up(1);
+                    value=ddr_set_rate(value);
                     printk("success!!! freq=%dMHz\n", value);
+                    msleep(32);
                     count++;
                 }
 
@@ -287,7 +271,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
                 printk("-->'b&&B' auto change ddr freq test (specific),Example: echo 'a:200M-400M-1000T' > ddr_test\n");
             }
             break;
-
+            
+        case 'h':
+        case 'H':
         default:
             printk("Help for ddr_ts .\n-->The Cmd list: \n");
             printk("-->'a&&A' auto change ddr freq test (random),Example: echo 'a:200M-400M-100T' > ddr_test\n");