/** ***************************************************************************** * @file cmem7_ddr.c * * @brief CMEM7 DDR source file * * * @version V1.0 * @date 3. September 2013 * * @note * ***************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT, * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2013 Capital-micro

***************************************************************************** */ #include "cmem7_ddr.h" #define MAX(a, b) ((a >= b) ? (a) : (b)) #define CAL_DDR3_CL(cl) ((cl>11)?(((cl-12)<Chip_type<_16Mbx16)?(chip_info->Chip_type):(chip_info->Chip_type-_16Mbx16); capacity=(chip_info->Chip_type<_16Mbx16)?(CHIP_MIN_CAPACITY*(1<Chip_num+1)):(CHIP_MIN_CAPACITY*(1<Bus_width+1)/(BUS_WIDTH_16+1)); return capacity; } uint32_t Calc_DDR_RFC(const MEM_CHIP_INFO *chip_info) { uint32_t capacity=0; uint32_t tRFC=0; assert_param(chip_info); capacity=Get_DDR_Capacity(chip_info); if (chip_info->mem_type==MEM_DDR2) { switch(capacity){ case CHIP_CAPACITY_32MB:tRFC=75;break; case CHIP_CAPACITY_64MB:tRFC=105;break; case CHIP_CAPACITY_128MB:tRFC=128;break; case CHIP_CAPACITY_256MB:tRFC=195;break; case CHIP_CAPACITY_512MB:tRFC=328;break; } } else{ switch(capacity){ case CHIP_CAPACITY_64MB:tRFC=90;break; case CHIP_CAPACITY_128MB:tRFC=110;break; case CHIP_CAPACITY_256MB:tRFC=160;break; case CHIP_CAPACITY_512MB:tRFC=300;break; case CHIP_CAPACITY_1024MB:tRFC=350;break; } } return tRFC; } static void DDR_Cmd(const uint32_t cmd ,const uint32_t param) { DDRC->CMD =((cmd)|(param)); } static void DDR_Latency(const uint32_t cycle ) { DDR_Cmd(SW_CMD_NOP,cycle); } static void DDR2_conf(const MEM_CHIP_INFO *chip_info ,const void *ddr) { uint32_t period=0; const DDR2MEM *ptr = (const DDR2MEM *)ddr; uint32_t tRFC=0; assert_param(ddr); tRFC=Calc_DDR_RFC(chip_info); period = (1000 / (SYSTEM_CLOCK_FREQ / 1000000)); CFG_CTRL->DONE_b.CMD = 0x1; DDRC->MODE_b.LANE = 1; DDRC->MODE_b.B16 = 1; DDRC->REF_b.TIME =( DDR_TREF/period); DDRC->RP_b.RPA = 1; DDRC->RFC_b.DI = (tRFC/period); DDRC->PHUNG_b.MODE = 1; DDRC->RD_SEL_b.PHY_SEL = 5; DDRC->DQSEN0_b.DL = 2; DDRC->DQSEN1_b.DL = 2; DDRC->DQSEN2_b.DL = 2; DDRC->DQSEN3_b.DL = 2; DDRC->INTCTL_b.DONE = 1; DDRC->INTCTL_b.ERR = 0; DDRC->RDQ_b.L3 = DDRC->RDQ_b.L2 = DDRC->RDQ_b.L1 = DDRC->RDQ_b.L0 = 0x32; DDRC->ITMDLY_b.I0 = DDRC->ITMDLY_b.IS0 = DDRC->ITMDLY_b.I1 = DDRC->ITMDLY_b.IS1 = DDRC->ITMDLY_b.I2 = DDRC->ITMDLY_b.IS2 = DDRC->ITMDLY_b.I3 = DDRC->ITMDLY_b.IS3 = 3; DDR_Latency((POWER_UP_NOP/period)); DDR_Cmd(SW_CMD_NOPCKE,(PRE_ALL_NOP/period)); DDR_Cmd(SW_CMD_PREA,NULL); DDR_Latency(ptr->tRP);/*tRP*/ DDR_Cmd(SW_CMD_EMR2,NULL); DDR_Latency(DDR2_TMRD); DDR_Cmd(SW_CMD_EMR3,NULL); DDR_Latency(DDR2_TMRD); DDR_Cmd(SW_CMD_DLL_EN,NULL); DDR_Latency(DDR2_TMRD); DDR_Cmd(SW_CMD_DLL_RST,NULL); DDR_Latency(DDR2_TMRD); DDR_Cmd(SW_CMD_PREA,NULL); DDR_Latency(ptr->tRP); DDR_Cmd(SW_CMD_REF,NULL); DDR_Latency((tRFC/period));/*tRFC*/ DDR_Cmd(SW_CMD_REF,NULL); DDR_Latency((tRFC/period)); DDR_Cmd(SW_CMD_MR,(((ptr->tWR-1)<tCL<MODE_b.LANE = 0x1; DDRC->QUE_b.DEPTH=1; DDRC->REF_b.TIME = (DDR_TREF / period);////// //2Gb periodic refresh interval 7.8us 7.8us/5ns DDRC->REF_b.TRIG = 1; DDRC->REF_b.THRD = 8; DDRC->ZQCSR_b.EN = 1; DDRC->ZQCSI = 128 * 1000000 / period; DDRC->RP_b.RPA = 1; DDRC->RFC_b.DI = (tRFC / period); if (ptr->tCK == 2500) { // 200MHz DDRC->RD_SEL_b.PHY_SEL = 5; } else if (ptr->tCK == 3000) { // 333MHz DDRC->RD_SEL_b.PHY_SEL = 6; } DDRC->PHUNG_b.MODE = 1; DDRC->DQSEN0_b.DL = 2; DDRC->DQSEN1_b.DL = 2; DDRC->DQSEN2_b.DL = 2; DDRC->DQSEN3_b.DL = 2; // config MR# DDR_Latency((POWER_UP_NOP/period));//200us nop DDR_Cmd(SW_CMD_RSTH,NULL);// RESET H DDR_Latency((RSTH_NOP/period));// 500us nop DDR_Cmd(SW_CMD_NOPCKE,((tRFC+10)/period));// cke high 170/tck tck txpr max(5nck, trfc(min) + 10ns) 2Gb refresh time 160ns DDR_Cmd(SW_CMD_EMR2,((ptr->tWCL-5)<tWR-1)<tCL)))); // MR0 // A1 , A0 2'b0 fixed 8 // A2 CL 0 // A3 nibble sequential 0 Interleave 1 // A6,A5,A4 CL 101 CL =9 // A7 normal mode 0 // A8 DLL reset 1 // A11,A10,A9 wr=(twr/ck)=(15/3)=5 =001 // A12 DLL control for precharge PD fast exit 1 // MR0 =0xb50 DDR_Latency(MAX(DDR3_TMOD_CK,(DDR3_TMOD/period)));// tmod max (12nck,15ns) DDR_Cmd(SW_CMD_ZQCL,NULL);// ZQCL starting ZQ calibration DDR_Latency(MAX(DDR3_TZQINIT_CK,(DDR3_TZQINIT/period))); // tdllk 512nck (should be 500nck) DDR_Latency(DDR3_TDLLK_CK); // tZQinit max(512nck,640ns) } BOOL DDR_Init(const MEM_CHIP_INFO *chip_info, const void *ddr) { uint32_t tCL, tWR, tWCL, tWTR, tCK,mode; assert_param(chip_info); assert_param(ddr); if((chip_info->Bus_widthChip_numChip_type< CHIP_TYPE_MAX)) { if(chip_info->mem_type==MEM_DDR2) { mode=DDR2_MODE[chip_info->Bus_width][chip_info->Chip_num][chip_info->Chip_type]; } else { mode=DDR3_MODE[chip_info->Bus_width][chip_info->Chip_num][chip_info->Chip_type]; } if(mode==0xff) { return FALSE; } } else { return FALSE; } PDPROT->LOCK_b.EN = 0; do { CFG_CTRL->PDLLSTR_b.C2R1D = 0; // rst dll_c2r1 udelay(10); CFG_CTRL->PDLLSTR_b.C2R1D = 1; // releset rst udelay(10); } while ((PDLOCK->GCLK & 0x40) != 0x40); PDPROT->LOCK_b.EN = 1; DDRC->MODE_b.MODE = mode; if (chip_info->mem_type==MEM_DDR2) { const DDR2MEM *ptr = (const DDR2MEM *)ddr; DDRC->RL_b.VAL = ptr->tCL; DDRC->RCD_b.DI = ptr->tRCD; DDRC->RP_b.DI = ptr->tRP; DDRC->RC_b.DI = ptr->tRC; DDRC->RAS_b.DI = ptr->tRAS; tWR = ptr->tWR; tWTR = ptr->tWTR; DDRC->RRD_b.DI = ptr->tRRD; DDRC->RTP_b.DI = ptr->tRTP; DDRC->FAW_b.DI = ptr->tFAW; DDR2_conf(chip_info,ptr); } else { const DDR3MEM *ptr = (const DDR3MEM *)ddr; DDRC->RL_b.VAL = ptr->tCL; tWCL = ptr->tWCL; DDRC->RCD_b.DI = ptr->tRCD; DDRC->RAS_b.DI = ptr->tRAS; DDRC->RP_b.DI = ptr->tRP; DDRC->RC_b.DI = ptr->tRC; DDRC->RRD_b.DI = ptr->tRRD; DDRC->FAW_b.DI = ptr->tFAW; tWR = ptr->tWR; tCK = ptr->tCK; DDRC->RTP_b.DI = ptr->tRTP; DDRC->ZQCL_b.DI = ptr->tZQoper; DDRC->ZQCS_b.DI = ptr->tZQCS; DDR3_conf(chip_info,ptr); } tCL = DDRC->RL_b.VAL; DDRC->WTR_b.DI = (DDRC->MODE_b.MODE & 0x20) ? (tWCL + tWTR + (DDRC->BURST_b.LEN ? 2 : 4)) : ((tCK * 4) > 7500) ? 18 : (tCK * 4 + 7500 - 1) / 7500; //4 DDRC->CCD_b.DI = (DDRC->MODE_b.MODE & 0x20) ? (DDRC->BURST_b.LEN ? 2 : 4) : 4; DDRC->RTW_b.DI = (DDRC->MODE_b.MODE & 0x20) ? (DDRC->BURST_b.LEN ? 4 : 6) : (tCL + DDRC->CCD_b.DI - tWCL + (DDRC->BURST_b.LEN ? 0 : 2)); DDRC->WTP_b.DI = (DDRC->MODE_b.MODE & 0x20) ? (tCL + tWR + (DDRC->BURST_b.LEN ? 1 : 3)) : (tWCL + tWR + (DDRC->BURST_b.LEN ? 2 : 4)); DDRC->WL_b.VAL = (DDRC->MODE_b.MODE & 0x20) ? (MAX(tCL, 3) - 3) : (tWCL - 2); DDRC->ODTH_b.DL = (DDRC->MODE_b.MODE & 0x20) ? (MAX(tCL, 4) - 4) : 0; if (tCK == 2500) { // 200MHz DDRC->ODTL_b.DL = (DDRC->MODE_b.MODE & 0x20) ? (DDRC->BURST_b.LEN ? (tCL - 1) : (tCL + 1)) : (DDRC->BURST_b.LEN ? 4 : 6); } else if (tCK == 3000) { // 333MHz DDRC->ODTL_b.DL = 0x1f; } // DEBUG INFO HERE DDRC->CTRL_b.STR = 1; while (0 == DDRC->STA_b.EMPTY); while(0 == DDRC->INTRAW_b.DONE); DDRC->CTRL_b.STR = DDRC->CTRL_b.TO = 0; return TRUE; }