From: cym Date: Mon, 3 Sep 2012 09:22:35 +0000 (+0800) Subject: rk30: ddr.c support for rk3066b X-Git-Tag: firefly_0821_release~8751^2~4 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e92d4bc777b99f8d757eb8c5e15541e842fd66f3;p=firefly-linux-kernel-4.4.55.git rk30: ddr.c support for rk3066b --- diff --git a/arch/arm/mach-rk30/common.c b/arch/arm/mach-rk30/common.c index 9e47f426d484..48ccd49c4ff5 100755 --- a/arch/arm/mach-rk30/common.c +++ b/arch/arm/mach-rk30/common.c @@ -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(); diff --git a/arch/arm/mach-rk30/ddr.c b/arch/arm/mach-rk30/ddr.c index db644378fc36..4a4d8f1cd6f5 100755 --- a/arch/arm/mach-rk30/ddr.c +++ b/arch/arm/mach-rk30/ddr.c @@ -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; diff --git a/arch/arm/mach-rk30/ddr_freq.c b/arch/arm/mach-rk30/ddr_freq.c index 5a3eef8f02b1..bf87a3db0f9d 100644 --- a/arch/arm/mach-rk30/ddr_freq.c +++ b/arch/arm/mach-rk30/ddr_freq.c @@ -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");