From 3f322d5aabd0826b8c87a168ee266691e58b2b14 Mon Sep 17 00:00:00 2001 From: hecanyang Date: Tue, 29 May 2012 14:18:18 +0800 Subject: [PATCH] fix data training bug, add ODT disable frequency macro, and reduce change frequency period --- arch/arm/mach-rk30/ddr.c | 488 +++++++++++++++++++++------------------ arch/arm/mach-rk30/pm.c | 29 ++- 2 files changed, 291 insertions(+), 226 deletions(-) diff --git a/arch/arm/mach-rk30/ddr.c b/arch/arm/mach-rk30/ddr.c index 3404abcece4e..a7d82bdf1201 100755 --- a/arch/arm/mach-rk30/ddr.c +++ b/arch/arm/mach-rk30/ddr.c @@ -23,6 +23,10 @@ #include typedef uint32_t uint32; + +#define DDR3_DDR2_DLL_DISABLE_FREQ (125) +#define DDR3_DDR2_ODT_DISABLE_FREQ (333) + #define PMU_BASE_ADDR RK30_PMU_BASE #define SDRAMC_BASE_ADDR RK30_DDR_PCTL_BASE #define DDR_PUBL_BASE RK30_DDR_PUBL_BASE @@ -112,8 +116,8 @@ typedef uint32_t uint32; #define DDR3_BC4 (2) #define DDR3_CL(n) (((((n)-4)&0x7)<<4)|((((n)-4)&0x8)>>1)) #define DDR3_WR(n) (((n)&0x7)<<9) -#define DDR3_MR0_DLL_RESET (1<<8) -#define DDR3_MR0_DLL_NOR (0<<8) +#define DDR3_DLL_RESET (1<<8) +#define DDR3_DLL_DISABLE (0<<8) //mr1 for ddr3 #define DDR3_MR1_AL(n) (((n)&0x7)<<3) @@ -139,6 +143,8 @@ typedef uint32_t uint32; #define DDR2_BL8 (3) #define DDR2_CL(n) (((n)&0x7)<<4) #define DDR2_WR(n) ((((n)-1)&0x7)<<9) +#define DDR2_DLL_RESET (1<<8) +#define DDR2_DLL_DISABLE (0<<8) //EMR; //Extended Mode Register #define DDR2_STR_FULL (0) @@ -542,6 +548,7 @@ typedef volatile struct DDR_REG_Tag #define DRAMINIT (1<<6) #define QSTRN (1<<7) #define EYETRN (1<<8) +#define ICPC (1<<16) #define DLLBYP (1<<17) #define CTLDINIT (1<<18) #define CLRSR (1<<28) @@ -879,7 +886,7 @@ uint32_t __sramdata ddr3_tRC_tFAW[22]={ ((53<<16)|50) //DDR3_DEFAULT }; -static __sramdata uint32_t mem_type; // 0:DDR2, 1:DDR3, 2:LPDDR +__sramdata uint32_t mem_type; // 0:LPDDR, 1:DDR, 2:DDR2, 3:DDR3, 4:LPDDR2 static __sramdata uint32_t ddr_type; // used for ddr3 only static __sramdata uint32_t capability; // one chip cs capability @@ -892,13 +899,13 @@ static __sramdata uint32_t ddr_freq; /**************************************************************************** Internal sram us delay function -Cpu highest frequency is 1.2 GHz -1 cycle = 1/1.2 ns -1 us = 1000 ns = 1000 * 1.2 cycles = 1200 cycles +Cpu highest frequency is 1.6 GHz +1 cycle = 1/1.6 ns +1 us = 1000 ns = 1000 * 1.6 cycles = 1600 cycles *****************************************************************************/ static __sramdata uint32_t loops_per_us; -#define LPJ_100MHZ 499728UL +#define LPJ_100MHZ 999456UL /*static*/ void __sramlocalfunc delayus(uint32_t us) { @@ -909,7 +916,7 @@ static __sramdata uint32_t loops_per_us; barrier(); } -static __sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words) +__sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words) { uint32 i; @@ -919,7 +926,7 @@ static __sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words) } } -static uint32 get_row(void) +uint32 get_row(void) { uint32 i; uint32 row; @@ -933,7 +940,7 @@ static uint32 get_row(void) return row; } -static uint32 get_bank(void) +uint32 get_bank(void) { uint32 i; @@ -941,7 +948,7 @@ static uint32 get_bank(void) return ddr_cfg_2_rbc[i].bank; } -static uint32 get_col(void) +uint32 get_col(void) { uint32 i; @@ -949,7 +956,7 @@ static uint32 get_col(void) return ddr_cfg_2_rbc[i].col; } -static uint32_t get_datatraing_addr(void) +uint32_t get_datatraing_addr(void) { uint32_t value=0; uint32_t addr; @@ -987,51 +994,23 @@ static uint32_t get_datatraing_addr(void) return value; } -static __sramfunc void idle_port(void) -{ - pPMU_Reg->PMU_MISC_CON1 = (pPMU_Reg->PMU_MISC_CON1 & (~(0x1F<<1))) - | idle_req_cpu_cfg - | idle_req_peri_cfg - | idle_req_gpu_cfg - | idle_req_video_cfg - | idle_req_vio_cfg; - while(((pPMU_Reg->PMU_PWRDN_ST) & (idle_peri - | idle_gpu - | idle_cpu - | idle_video - | idle_vio)) != (idle_peri - | idle_gpu - | idle_cpu - | idle_video - | idle_vio)); -} - - -static __sramfunc void deIdle_port(void) -{ - pPMU_Reg->PMU_MISC_CON1 &= ~(idle_req_peri_cfg - | idle_req_gpu_cfg - | idle_req_cpu_cfg - | idle_req_video_cfg - | idle_req_vio_cfg); -} - -static __sramlocalfunc void reset_dll(void) +__sramlocalfunc void reset_dll(void) { pPHY_Reg->ACDLLCR &= ~0x40000000; pPHY_Reg->DATX8[0].DXDLLCR &= ~0x40000000; pPHY_Reg->DATX8[1].DXDLLCR &= ~0x40000000; pPHY_Reg->DATX8[2].DXDLLCR &= ~0x40000000; pPHY_Reg->DATX8[3].DXDLLCR &= ~0x40000000; - delayus(10); + delayus(1); pPHY_Reg->ACDLLCR |= 0x40000000; pPHY_Reg->DATX8[0].DXDLLCR |= 0x40000000; pPHY_Reg->DATX8[1].DXDLLCR |= 0x40000000; pPHY_Reg->DATX8[2].DXDLLCR |= 0x40000000; pPHY_Reg->DATX8[3].DXDLLCR |= 0x40000000; - delayus(10); + delayus(1); } -static __sramfunc void move_to_Lowpower_state(void) + +__sramfunc void move_to_Lowpower_state(void) { volatile uint32 value; @@ -1061,7 +1040,7 @@ static __sramfunc void move_to_Lowpower_state(void) } } -static __sramfunc void move_to_Access_state(void) +__sramfunc void move_to_Access_state(void) { volatile uint32 value; @@ -1093,7 +1072,7 @@ static __sramfunc void move_to_Access_state(void) } } -static __sramfunc void move_to_Config_state(void) +__sramfunc void move_to_Config_state(void) { volatile uint32 value; @@ -1122,7 +1101,7 @@ static __sramfunc void move_to_Config_state(void) } //arg°üÀ¨bank_addrºÍcmd_addr -static void __sramlocalfunc send_command(uint32 rank, uint32 cmd, uint32 arg) +void __sramlocalfunc send_command(uint32 rank, uint32 cmd, uint32 arg) { uint32 i; pDDR_Reg->MCMD = (start_cmd | (rank<<20) | arg | cmd); @@ -1133,21 +1112,38 @@ static void __sramlocalfunc send_command(uint32 rank, uint32 cmd, uint32 arg) //¶ÔtypeÀàÐ͵ÄDDRµÄ¼¸¸öcs½øÐÐDTT //0 DTT³É¹¦ //!0 DTTʧ°Ü -static uint32_t __sramlocalfunc data_training(void) +uint32_t __sramlocalfunc data_training(void) { - uint32 i,value; + uint32 i,value,cs; + // disable auto refresh value = pDDR_Reg->TREFI; pDDR_Reg->TREFI = 0; - - pPHY_Reg->PIR = INIT | CLRSR; - delayus(1); - pPHY_Reg->PIR = INIT | QSTRN | LOCKBYP | ZCALBYP | CLRSR; + // clear DTDONE status + pPHY_Reg->PIR |= CLRSR; + cs = ((pPHY_Reg->PGCR>>18) & 0xF); + // trigger DTT + pPHY_Reg->PIR |= INIT | QSTRN | LOCKBYP | ZCALBYP | CLRSR | ICPC; for (i = 0; i < 10; i ++) {;} - while((pPHY_Reg->PGSR & (IDONE | DTDONE)) != (IDONE | DTDONE)); - - pDDR_Reg->TREFI = value>>3; - delayus(20); + // wait echo byte DTDONE + while((pPHY_Reg->DATX8[0].DXGSR[0] & cs) != cs); + while((pPHY_Reg->DATX8[1].DXGSR[0] & cs) != cs); + while((pPHY_Reg->DATX8[2].DXGSR[0] & cs) != cs); + while((pPHY_Reg->DATX8[3].DXGSR[0] & cs) != cs); //²âµ½1¸öCSµÄDTT×ʱ¼äÊÇ10.7us¡£×î¶à²¹2´ÎˢР+ // send some auto refresh to complement the lost while DTT + if(cs > 1) + { + send_command(cs, REF_cmd, 0); + send_command(cs, REF_cmd, 0); + send_command(cs, REF_cmd, 0); + send_command(cs, REF_cmd, 0); + } + else + { + send_command(cs, REF_cmd, 0); + send_command(cs, REF_cmd, 0); + } + // resume auto refresh pDDR_Reg->TREFI = value; if(pPHY_Reg->PGSR & DTERR) @@ -1160,7 +1156,7 @@ static uint32_t __sramlocalfunc data_training(void) } } -static void __sramlocalfunc phy_dll_bypass_set(uint32 freq) +void __sramlocalfunc phy_dll_bypass_set(uint32 freq) { if(freq<=150) { @@ -1170,6 +1166,7 @@ static void __sramlocalfunc phy_dll_bypass_set(uint32 freq) pPHY_Reg->DATX8[1].DXDLLCR |= 0x80000000; pPHY_Reg->DATX8[2].DXDLLCR |= 0x80000000; pPHY_Reg->DATX8[3].DXDLLCR |= 0x80000000; + pPHY_Reg->PIR |= DLLBYP; } else if(freq<=250) { @@ -1179,6 +1176,7 @@ static void __sramlocalfunc phy_dll_bypass_set(uint32 freq) pPHY_Reg->DATX8[1].DXDLLCR |= 0x80000000; pPHY_Reg->DATX8[2].DXDLLCR |= 0x80000000; pPHY_Reg->DATX8[3].DXDLLCR |= 0x80000000; + pPHY_Reg->PIR |= DLLBYP; } else { @@ -1188,6 +1186,7 @@ static void __sramlocalfunc phy_dll_bypass_set(uint32 freq) pPHY_Reg->DATX8[1].DXDLLCR &= ~0x80000000; pPHY_Reg->DATX8[2].DXDLLCR &= ~0x80000000; pPHY_Reg->DATX8[3].DXDLLCR &= ~0x80000000; + pPHY_Reg->PIR &= ~DLLBYP; } } @@ -1202,7 +1201,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 ******************************************/ -static uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set) +uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set) { uint32_t ret = 0; int delay = 1000; @@ -1255,8 +1254,8 @@ static uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set) while (delay > 0) { delayus(1); - //if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4)) - // break; + if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4)) + break; delay--; } @@ -1270,82 +1269,7 @@ out: return ret; } -static __sramfunc void ddr_adjust_config(uint32_t dram_type) -{ - uint32 value; - unsigned long save_sp; - u32 i; - volatile u32 n; - volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET; - - //get data training address before idle port - value = get_datatraing_addr(); - - /** 1. Make sure there is no host access */ - flush_cache_all(); - outer_flush_all(); - flush_tlb_all(); - DDR_SAVE_SP(save_sp); - - for(i=0;i<16;i++) - { - n=temp[1024*i]; - barrier(); - } - n= pDDR_Reg->SCFG.d32; - n= pPHY_Reg->RIDR; - n= pCRU_Reg->CRU_PLL_CON[0][0]; - n= pPMU_Reg->PMU_WAKEUP_CFG[0]; - n= *(volatile uint32_t *)SysSrv_DdrConf; - dsb(); - - //enter config state - idle_port(); - move_to_Config_state(); - - //extend capability for debug - if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1)) - { - pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en; - } - - //set data training address - pPHY_Reg->DTAR = value; - - //set auto power down idle - pDDR_Reg->MCFG=(pDDR_Reg->MCFG&0xffff00ff)|(0x40<<8); - - //adjust DRV and ODT - if(dram_type == DDR3) - { - pPHY_Reg->ZQ0CR[1] = 0x1B; //DS=40ohm,ODT=120ohm - pPHY_Reg->ZQ0CR[0] |= (1<<30); //trigger - } - else if (dram_type == DDR2) - { - pPHY_Reg->ZQ0CR[1] = 0x4B; //DS=40ohm,ODT=75ohm - pPHY_Reg->ZQ0CR[0] |= (1<<30); //trigger - } - else - { - pPHY_Reg->ZQ0CR[1] = 0x1B; //DS=40ohm,ODT=120ohm - pPHY_Reg->ZQ0CR[0] |= (1<<30); //trigger - } - delayus(10); - while(!(pPHY_Reg->ZQ0SR[0] & (0x1u<<31))); - if(pPHY_Reg->ZQ0SR[0] & (0x1u<<30)) - { - ddr_print("ZQCR error!\n"); - } - - //enter access state - move_to_Access_state(); - deIdle_port(); - - DDR_RESTORE_SP(save_sp); -} - -static uint32_t ddr_get_parameter(uint32_t nMHz) +uint32_t ddr_get_parameter(uint32_t nMHz) { uint32_t tmp; uint32_t ret = 0; @@ -1411,7 +1335,14 @@ static uint32_t ddr_get_parameter(uint32_t nMHz) cwl = ddr3_cl_cwl[ddr_type][tmp] & 0x0ff; if(cl == 0) ret = -4; - p_ddr_timing->phy_timing.mr[1] = DDR3_DS_40 | DDR3_Rtt_Nom_120; + if(nMHz <= DDR3_DDR2_ODT_DISABLE_FREQ) + { + p_ddr_timing->phy_timing.mr[1] = DDR3_DS_40 | DDR3_Rtt_Nom_DIS; + } + else + { + p_ddr_timing->phy_timing.mr[1] = DDR3_DS_40 | DDR3_Rtt_Nom_120; + } p_ddr_timing->phy_timing.mr[2] = DDR3_MR2_CWL(cwl) /* | DDR3_Rtt_WR_60 */; p_ddr_timing->phy_timing.mr[3] = 0; /************************************************** @@ -1708,8 +1639,8 @@ static uint32_t ddr_get_parameter(uint32_t nMHz) #define LPDDR2_tFAW_GREAT_200MHz (50) //ns #define LPDDR2_tFAW_LITTLE_200MHz (60) //ns #define LPDDR2_tDLLK (2) //tCK - #define LPDDR2_tDQSCK_MAX (5) //ns - #define LPDDR2_tDQSCK_MIN (2) //ns + #define LPDDR2_tDQSCK_MAX (3) //tCK + #define LPDDR2_tDQSCK_MIN (0) //tCK #define LPDDR2_tDQSS (1) //tCK al = 0; @@ -1830,12 +1761,12 @@ static uint32_t ddr_get_parameter(uint32_t nMHz) p_ddr_timing->phy_timing.dtpr0.b.tRC = (((LPDDR2_tRP_4_BANK+LPDDR2_tRAS)*nMHz+999)/1000)&0xF; } - p_ddr_timing->pctl_timing.trtw = (cl+((LPDDR2_tDQSCK_MIN*nMHz+(nMHz>>1)+999)/1000)-cwl);//LPDDR2_tRTW; + p_ddr_timing->pctl_timing.trtw = (cl+LPDDR2_tDQSCK_MAX+(bl/2)+1-cwl);//LPDDR2_tRTW; p_ddr_timing->phy_timing.dtpr1.b.tRTW = 0; /* * RdToWr=RL+tDQSCK-WL */ - p_ddr_timing->noc_timing.b.RdToWr = ((cl+((LPDDR2_tDQSCK_MIN*nMHz+(nMHz>>1)+999)/1000)-cwl)&0x1F); + p_ddr_timing->noc_timing.b.RdToWr = ((cl+LPDDR2_tDQSCK_MAX+1-cwl)&0x1F); p_ddr_timing->pctl_timing.tal = al; p_ddr_timing->pctl_timing.tcl = cl; p_ddr_timing->pctl_timing.tcwl = cwl; @@ -1960,13 +1891,11 @@ static uint32_t ddr_get_parameter(uint32_t nMHz) /* * tDQSCKmax,5.5ns */ - tmp = ((LPDDR2_tDQSCK_MAX*nMHz+(nMHz>>1)+999)/1000); - p_ddr_timing->phy_timing.dtpr1.b.tDQSCKmax = 3; + p_ddr_timing->phy_timing.dtpr1.b.tDQSCKmax = LPDDR2_tDQSCK_MAX; /* * tDQSCKmin,2.5ns */ - tmp = ((LPDDR2_tDQSCK_MAX*nMHz+(nMHz>>1))/1000); - p_ddr_timing->phy_timing.dtpr1.b.tDQSCK = 2; + p_ddr_timing->phy_timing.dtpr1.b.tDQSCK = LPDDR2_tDQSCK_MIN; /* * tRTODT, 0:ODT may be turned on immediately after read post-amble * 1:ODT may not be turned on until one clock after the read post-amble @@ -2041,7 +1970,14 @@ static uint32_t ddr_get_parameter(uint32_t nMHz) cl = 7; } cwl = cl -1; - p_ddr_timing->phy_timing.mr[1] = DDR2_STR_REDUCE | DDR2_Rtt_Nom_75; + if(nMHz <= DDR3_DDR2_ODT_DISABLE_FREQ) + { + p_ddr_timing->phy_timing.mr[1] = DDR2_STR_REDUCE | DDR2_Rtt_Nom_DIS; + } + else + { + p_ddr_timing->phy_timing.mr[1] = DDR2_STR_REDUCE | DDR2_Rtt_Nom_75; + } p_ddr_timing->phy_timing.mr[2] = 0; p_ddr_timing->phy_timing.mr[3] = 0; /************************************************** @@ -2552,7 +2488,7 @@ out: return ret; } -static uint32_t __sramlocalfunc ddr_update_timing(void) +uint32_t __sramlocalfunc ddr_update_timing(void) { uint32_t i; DDR_TIMING_T *p_ddr_timing=&ddr_timing; @@ -2579,7 +2515,7 @@ static uint32_t __sramlocalfunc ddr_update_timing(void) } i = ((pPHY_Reg->DTPR[1] >> 27) & 0x7) - ((pPHY_Reg->DTPR[1] >> 24) & 0x7); pPHY_Reg->DSGCR = (pPHY_Reg->DSGCR & (~(0x3F<<5))) | (i<<5) | (i<<8); //tDQSCKmax-tDQSCK - pDDR_Reg->DFITRDDATAEN = pDDR_Reg->TCL; + pDDR_Reg->DFITRDDATAEN = pDDR_Reg->TCL-1; pDDR_Reg->DFITPHYWRLAT = pDDR_Reg->TCWL; } else if(mem_type == DDR2) @@ -2593,76 +2529,180 @@ static uint32_t __sramlocalfunc ddr_update_timing(void) return 0; } -static uint32_t __sramlocalfunc ddr_update_mr(void) +uint32_t __sramlocalfunc ddr_update_mr(void) { DDR_TIMING_T *p_ddr_timing=&ddr_timing; + uint32_t cs; + cs = ((pPHY_Reg->PGCR>>18) & 0xF); copy((uint32_t *)&(pPHY_Reg->MR[0]), (uint32_t*)&(p_ddr_timing->phy_timing.mr[0]), 4); - if(mem_type == DDR3) + if((mem_type == DDR3) || (mem_type == DDR2)) { - send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr(((uint8_t)(p_ddr_timing->phy_timing.mr[0]))|(0X1<<8))); - delayus(100); - send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0]))); - send_command(3, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1]))); - send_command(3, MRS_cmd, bank_addr(0x2) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); + if(ddr_freq>DDR3_DDR2_DLL_DISABLE_FREQ) + { + if(pPHY_Reg->MR[1] & DDR3_DLL_DISABLE) // off -> on + { + send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1]))); //DLL enable + send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr(((uint8_t)(p_ddr_timing->phy_timing.mr[0]))| DDR3_DLL_RESET)); //DLL reset + delayus(2); //at least 200 DDR cycle + send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0]))); + } + else // on -> on + { + send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1]))); + send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0]))); + } + } + else + { + pPHY_Reg->MR[1] = (((uint8_t)(p_ddr_timing->phy_timing.mr[1])) | DDR3_DLL_DISABLE); + send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr(((uint8_t)(p_ddr_timing->phy_timing.mr[1])) | DDR3_DLL_DISABLE)); //DLL disable + send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0]))); + } + send_command(cs, MRS_cmd, bank_addr(0x2) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); } else if(mem_type == LPDDR2) { - send_command(3, MRS_cmd, lpddr2_ma(0x1) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[1]))); - send_command(3, MRS_cmd, lpddr2_ma(0x2) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); - send_command(3, MRS_cmd, lpddr2_ma(0x3) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[3]))); + send_command(cs, MRS_cmd, lpddr2_ma(0x1) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[1]))); + send_command(cs, MRS_cmd, lpddr2_ma(0x2) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); + send_command(cs, MRS_cmd, lpddr2_ma(0x3) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[3]))); } - else if(mem_type == DDR2) + else //mDDR { - send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0]))); - send_command(3, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1]))); + send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0]))); + send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); //mr[2] is mDDR MR1 } - else //if(mem_type == LPDDR) + return 0; +} + +void __sramlocalfunc ddr_update_odt(void) +{ + uint32_t cs,tmp; + + //adjust DRV and ODT + if((mem_type == DDR3) || (mem_type == DDR2)) + { + if(ddr_freq <= DDR3_DDR2_ODT_DISABLE_FREQ) + { + pPHY_Reg->DATX8[0].DXGCR &= ~(0x3<<9); //dynamic RTT disable + pPHY_Reg->DATX8[1].DXGCR &= ~(0x3<<9); + pPHY_Reg->DATX8[2].DXGCR &= ~(0x3<<9); + pPHY_Reg->DATX8[3].DXGCR &= ~(0x3<<9); + } + else + { + pPHY_Reg->DATX8[0].DXGCR |= (0x3<<9); //dynamic RTT enable + pPHY_Reg->DATX8[1].DXGCR |= (0x3<<9); + pPHY_Reg->DATX8[2].DXGCR |= (0x3<<9); + pPHY_Reg->DATX8[3].DXGCR |= (0x3<<9); + } + } + else + { + pPHY_Reg->DATX8[0].DXGCR &= ~(0x3<<9); //dynamic RTT disable + pPHY_Reg->DATX8[1].DXGCR &= ~(0x3<<9); + pPHY_Reg->DATX8[2].DXGCR &= ~(0x3<<9); + pPHY_Reg->DATX8[3].DXGCR &= ~(0x3<<9); + } + tmp = (0x1<<28) | (0x2<<15) | (0x2<<10) | (0xb<<5) | 0xb; //DS=34ohm,ODT=171ohm + cs = ((pPHY_Reg->PGCR>>18) & 0xF); + if(cs > 1) + { + pPHY_Reg->ZQ1CR[0] = tmp; + } + pPHY_Reg->ZQ0CR[0] = tmp; +} + +__sramfunc void ddr_adjust_config(uint32_t dram_type) +{ + uint32 value; + unsigned long save_sp; + u32 i; + volatile u32 n; + volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET; + + //get data training address before idle port + value = get_datatraing_addr(); + + /** 1. Make sure there is no host access */ + flush_cache_all(); + outer_flush_all(); + flush_tlb_all(); + DDR_SAVE_SP(save_sp); + + for(i=0;i<16;i++) { - send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0]))); - send_command(3, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); //mr[2] is mDDR MR1 + n=temp[1024*i]; + barrier(); } + n= pDDR_Reg->SCFG.d32; + n= pPHY_Reg->RIDR; + n= pCRU_Reg->CRU_PLL_CON[0][0]; + n= pPMU_Reg->PMU_WAKEUP_CFG[0]; + n= *(volatile uint32_t *)SysSrv_DdrConf; + dsb(); - return 0; + //enter config state + move_to_Config_state(); + + //extend capability for debug + if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1)) + { + pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en; + } + + //set data training address + pPHY_Reg->DTAR = value; + + //set auto power down idle + pDDR_Reg->MCFG=(pDDR_Reg->MCFG&0xffff00ff)|(0x40<<8); + + ddr_update_odt(); + + //enter access state + move_to_Access_state(); + + DDR_RESTORE_SP(save_sp); } -static void __sramlocalfunc ddr_selfrefresh_enter(void) +void __sramlocalfunc ddr_selfrefresh_enter(uint32 nMHz) { - idle_port(); + uint32 cs; + + move_to_Config_state(); + pDDR_Reg->TZQCSI = 0; + if((nMHz<=DDR3_DDR2_DLL_DISABLE_FREQ) && ((mem_type == DDR3) || (mem_type == DDR2))) // DLL disable + { + cs = ((pPHY_Reg->PGCR>>18) & 0xF); + pPHY_Reg->MR[1] = (((uint8_t)(ddr_timing.phy_timing.mr[1])) | DDR3_DLL_DISABLE); + send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr(((uint8_t)(ddr_timing.phy_timing.mr[1])) | DDR3_DLL_DISABLE)); + } move_to_Lowpower_state(); - //pPHY_Reg->ACDLLCR &= ~0x40000000; - //pPHY_Reg->DATX8[0].DXDLLCR &= ~0x40000000; - //pPHY_Reg->DATX8[1].DXDLLCR &= ~0x40000000; - //pPHY_Reg->DATX8[2].DXDLLCR &= ~0x40000000; - //pPHY_Reg->DATX8[3].DXDLLCR &= ~0x40000000; //reset DLL - //delayus(1); - //pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16)|(0x1<<2); //close DDR PHY clock - //phy_dll_bypass_set(0); //dll bypass + phy_dll_bypass_set(0); //dll bypass + pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (1<<2); //disable DDR PHY clock + delayus(1); } -static void __sramlocalfunc ddr_selfrefresh_exit(void) +void __sramlocalfunc ddr_selfrefresh_exit(void) { uint32 n; - //pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16)|(0x0<<2); //open DDR PHY clock - //delayus(1000); - //pPHY_Reg->ACDLLCR |= 0x40000000; - //pPHY_Reg->DATX8[0].DXDLLCR |= 0x40000000; - //pPHY_Reg->DATX8[1].DXDLLCR |= 0x40000000; - //pPHY_Reg->DATX8[2].DXDLLCR |= 0x40000000; - //pPHY_Reg->DATX8[3].DXDLLCR |= 0x40000000; //de-reset DLL - //delayus(10); - //pPHY_Reg->PIR = INIT | ITMSRST | LOCKBYP | ZCALBYP | CLRSR; //reset ITM - + + pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (0<<2); //enable DDR PHY clock + dsb(); + phy_dll_bypass_set(ddr_freq); + reset_dll(); + //delayus(10); //wait DLL lock + move_to_Config_state(); ddr_update_timing(); ddr_update_mr(); + ddr_update_odt(); n = data_training(); move_to_Access_state(); - deIdle_port(); if(n!=0) { - ddr_print("DTT failed!\n"); + sram_printascii("DTT failed!\n"); } } @@ -2674,6 +2714,18 @@ uint32_t __sramfunc ddr_change_freq(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; + + // 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) + /((((regvalue>>8)&0x3f)+1) // NR = CLKR+1 + *((regvalue&0xF)+1)); // OD = 2^CLKOD + else + freq = 24; + + loops_per_us = LPJ_100MHZ*freq / 1000000; ret=ddr_set_pll(nMHz,0); ddr_get_parameter(ret); @@ -2698,25 +2750,12 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz) dsb(); /** 2. ddr enter self-refresh mode or precharge power-down mode */ - ddr_selfrefresh_enter(); - - phy_dll_bypass_set(0); //dll bypass - dsb(); - pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (1<<2); //disable DDR PHY clock - delayus(1); + ddr_selfrefresh_enter(ret); /** 3. change frequence */ ddr_set_pll(ret,1); ddr_freq = ret; - pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (0<<2); //enable DDR PHY clock - dsb(); - delayus(1000); //wait pll lock - phy_dll_bypass_set(ret); - dsb(); - - reset_dll(); - dsb(); /** 5. Issues a Mode Exit command */ ddr_selfrefresh_exit(); dsb(); @@ -2751,35 +2790,39 @@ void __sramfunc ddr_suspend(void) n= *(volatile uint32_t *)SysSrv_DdrConf; dsb(); - //idle_port(); - move_to_Lowpower_state(); + ddr_selfrefresh_enter(0); - phy_dll_bypass_set(0); //dll bypass - pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (1<<2); //disable DDR PHY clock + pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x0<<(1*4)); //PLL slow-mode dsb(); - delayus(1); - pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x0<<(1*4)); //PLL slow-mode + delayus(1); + pCRU_Reg->CRU_PLL_CON[1][3] = ((0x1<<1)<<16) | (0x1<<1); //PLL power-down dsb(); delayus(1); - pPHY_Reg->DSGCR = pPHY_Reg->DSGCR&(~((0x1<<28)|(0x1<<29))); + pPHY_Reg->DSGCR = pPHY_Reg->DSGCR&(~((0x1<<28)|(0x1<<29))); //CKOE } EXPORT_SYMBOL(ddr_suspend); void __sramfunc ddr_resume(void) { - pPHY_Reg->DSGCR = pPHY_Reg->DSGCR|((0x1<<28)|(0x1<<29)); + int delay=1000; + pPHY_Reg->DSGCR = pPHY_Reg->DSGCR|((0x1<<28)|(0x1<<29)); //CKOE dsb(); - pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x1<<(1*4)); //PLL normal + pCRU_Reg->CRU_PLL_CON[1][3] = ((0x1<<1)<<16) | (0x0<<1); //PLL no power-down dsb(); - pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (0<<2); //enable DDR PHY clock + while (delay > 0) + { + delayus(1); + if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4)) + break; + delay--; + } + + pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x1<<(1*4)); //PLL normal dsb(); - delayus(10); //wait pll lock - phy_dll_bypass_set(ddr_freq); - reset_dll(); - move_to_Access_state(); - //deIdle_port(); + + ddr_selfrefresh_exit(); } EXPORT_SYMBOL(ddr_resume); @@ -2818,10 +2861,10 @@ EXPORT_SYMBOL(ddr_get_cap); int ddr_init(uint32_t dram_type, uint32_t freq) { volatile uint32_t value = 0; - uint32_t cs; + uint32_t cs,die=1; uint32_t gsr,dqstr; - ddr_print("version 1.00 20120505 \n"); + ddr_print("version 1.00 20120529 \n"); mem_type = pPHY_Reg->DCR.b.DDRMD; ddr_type = dram_type; @@ -2829,6 +2872,7 @@ int ddr_init(uint32_t dram_type, uint32_t freq) switch(mem_type) { case DDR3: + die = 2; //there is two die DDR3 at least ddr_print("DDR3 Device\n"); break; case LPDDR2: @@ -2859,7 +2903,7 @@ int ddr_init(uint32_t dram_type, uint32_t freq) break; } //get capability per chip, not total size, used for calculate tRFC - capability = ddr_get_cap()/cs; + capability = ddr_get_cap()/(cs*die); ddr_print("%d CS, ROW=%d, Bank=%d, COL=%d, Total Capability=%dMB\n", cs, \ get_row(), \ diff --git a/arch/arm/mach-rk30/pm.c b/arch/arm/mach-rk30/pm.c index 5e081fddcce3..6ff619ed0560 100755 --- a/arch/arm/mach-rk30/pm.c +++ b/arch/arm/mach-rk30/pm.c @@ -82,25 +82,46 @@ static int inline calc_crc32(u32 addr, size_t len) return crc32_le(~0, (const unsigned char *)addr, len); } +extern __sramdata uint32_t mem_type; static void __sramfunc ddr_testmode(void) { int32_t g_crc1, g_crc2; uint32_t nMHz; uint32_t n = 0; + uint32_t min,max; extern char _stext[], _etext[]; + if (ddr_debug == 1) { + switch(mem_type) + { + case 0: //LPDDR + case 1: //DDR + max = 210; + min = 100; + break; + case 2: //DDR2 + case 4: //LPDDR2 + max=410; + min=100; + break; + case 3: //DDR3 + default: + max=500; + min=100; + break; + } for (;;) { sram_printascii("\n change freq:"); g_crc1 = calc_crc32((u32)_stext, (size_t)(_etext-_stext)); do { - nMHz = 300 + random32(); - nMHz %= 500; - }while(nMHz < 300); - nMHz = ddr_change_freq(nMHz); + nMHz = min + random32(); + nMHz %= max; + }while(nMHz < min); sram_printhex(nMHz); sram_printch(' '); + nMHz = ddr_change_freq(nMHz); sram_printhex(n++); sram_printch(' '); g_crc2 = calc_crc32((u32)_stext, (size_t)(_etext-_stext)); -- 2.34.1