⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bcm1480_draminit.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
    fMemClk = ((plldiv * BCM1480_REFCLK * 1000 / 2 / 2) * 4 / clk_ratio);    refrate = fMemClk / 32 / ref_freq;    /* Don't let the refresh rate go beyond the field width */    if (refrate > 255) refrate = 255;    /*     * Calculate CAS Latency in half cycles.  The low bit indicates     * half a cycle, so 2 (0010) = 1 cycle and 3 (0011) = 1.5 cycles     */    res = tdata->spd_caslatency;    if (res & JEDEC_CASLAT_40) caslatency = (4 << 1);		/* 4.0 */    else if (res & JEDEC_CASLAT_35) caslatency = (3 << 1) + 1;	/* 3.5 */    else if (res & JEDEC_CASLAT_30) caslatency = (3 << 1);	/* 3.0 */    else if (res & JEDEC_CASLAT_25) caslatency = (2 << 1) + 1;	/* 2.5 */    else if (res & JEDEC_CASLAT_20) caslatency = (2 << 1);	/* 2.0 */    else if (res & JEDEC_CASLAT_15) caslatency = (1 << 1) + 1;	/* 1.5 */    else caslatency = (1 << 1);					/* 1.0 */    if ((spd_tCK_10 != 0) && (spd_tCK_10 <= tMemClk)) {	caslatency -= (1 << 1);				/* subtract 1.0 */	}    else if ((spd_tCK_20 != 0) && (spd_tCK_20 <= tMemClk)) {	caslatency -= 1;				/* subtract 0.5 */	}    /*     * Store the CAS latency in the chip select info     */        tdata->flags &= ~CS_CASLAT_MASK;    tdata->flags |= (((caslatency << CS_CASLAT_SHIFT)) & CS_CASLAT_MASK);#ifdef _MCSTANDALONE_    dram_cas_latency = caslatency;	    dram_tMemClk = tMemClk;#endif    /*     * Now, on to the timing parameters.     */    w2rIdle = 1;	/* Needs to be set on all parts.  XXX this is a 1250 bug, what to do on 1480? */    r2rIdle = 0;    /* ======================================================================== */    /*     * New "Window" calculations     */    n01_open = -BCM1480_WINDOW_OPEN_OFFSET;    n02_open = -BCM1480_WINDOW_OPEN_OFFSET;    n12_open = tMemClk/2 - BCM1480_WINDOW_OPEN_OFFSET;    n01_close = tMemClk - BCM1480_CLOSE_01_OFFSET;    n02_close = 3*tMemClk/2 - BCM1480_CLOSE_02_OFFSET;    n12_close = 7*tMemClk/4 - BCM1480_CLOSE_12_OFFSET;    minDqsMargin = BCM1480_MIN_DQS_MARGIN;    dllScaleNum = DLL_SCALE_NUMERATOR;    dllScaleDenom = DLL_SCALE_DENOMINATOR;    dllOffset = DLL_OFFSET;	    /*      * get initial values for tCL and dqsArrival     */    tCL = (caslatency >> 1);    dqsArrival = mc->roundtrip;    if (caslatency & 1) {	dqsArrival += tMemClk/2;	}    /*     * need to adjust for settings of skew values.     * can either add to dqsArrival or subtract from     * all the windows.     */    addrAdjust = ((int)tMemClk * dllScaleNum - dllOffset) / (8 * dllScaleDenom);    dqiAdjust  = ((int)tMemClk * dllScaleNum - dllOffset) / (8 * dllScaleDenom);    dqsArrival += addrAdjust + dqiAdjust;    dqoAdjust  = (tMemClk * dllScaleNum - dllOffset) / (8 * dllScaleDenom);    n12_close += dqoAdjust;#ifdef _MCSTANDALONE_NOISY_    printf("DRAM: addrAdjust=%d dqiAdjust=%d dqsArrival=%d\n",	   addrAdjust,dqiAdjust,dqsArrival);    printf("DRAM: n02_close=%d n12_close=%d minDqsMargin=%d\n",	   n02_close,n12_close,minDqsMargin);    printf("DRAM: tMemClk=%d dllScaleNum=%d dllScaleDenom=%d dllOffset=%d\n",	   tMemClk,dllScaleNum,dllScaleDenom,dllOffset);#endif    while ((n02_close - dqsArrival < minDqsMargin) &&	   (n12_close - dqsArrival < minDqsMargin)) {	/* very late DQS arrival; shift latency by one tick */#ifdef _MCSTANDALONE_NOISY_	printf("DRAM: Very late DQS arrival, shift latency one tick\n");#endif	++tCL;	dqsArrival -= tMemClk;	}    if ((dqsArrival - n01_open  >= minDqsMargin) &&	(n01_close - dqsArrival >= minDqsMargin)) {	/* use n,0,1 */	tCrDh = 0;	tFIFO = 1;#ifdef _MCSTANDALONE_NOISY_	printf("DRAM: DQS arrival in n,0,1 window\n");#endif	}     else if ((dqsArrival - n02_open  >= minDqsMargin) &&	     (n02_close - dqsArrival >= minDqsMargin)) {	/* use n,0,2 */	tCrDh = 0;	tFIFO = 2;#ifdef _MCSTANDALONE_NOISY_	printf("DRAM: DQS arrival in n,0,2 window\n");#endif	}     else if ((dqsArrival - n12_open  >= minDqsMargin) &&	     (n12_close - dqsArrival >= minDqsMargin)) {	/* use n,1,2 */	tCrDh = 1;	tFIFO = 2;#ifdef _MCSTANDALONE_NOISY_	printf("DRAM: DQS arrival in n,1,2 window\n");#endif	}     else {	/* 	 * minDqsMargin is probably set too high 	 * try using n,0,2	 */	tCrDh = 0;	tFIFO = 2;#ifdef _MCSTANDALONE_NOISY_	printf("DRAM: Default: DQS arrival in n,0,2 window\n");#endif	}    /*  r2wIdle = ((tMemClk - dqsArrival) < BCM1480_MIN_R2W_TIME);*/    r2wIdle = 2;		/* XXX force 1 for now until 1480 measurements are done */#ifdef _VERILOG_    tFIFO = 0;#endif    /*      * Above stuff just calculated tCrDh, tCL, and tFIFO     *///    tFIFO = 0;	tCrDh = 1; tCL = 2; /* XXX */    /* ======================================================================== */    /* Recompute tMemClk as a fixed-point 6.2 value */    tMemClk = (4000 *  clk_ratio) / (BCM1480_REFCLK * plldiv);    /*     * With the actual tMemClk in hand, calculate tRAS, tRP, tRRD, and tRCD      */    tRAS = ( ((unsigned int)(tdata->spd_tRAS))*4 + tMemClk-1) / tMemClk;    tRP =  ( ((unsigned int)(tdata->spd_tRP))    + tMemClk-1) / tMemClk;    tRRD = ( ((unsigned int)(tdata->spd_tRRD))   + tMemClk-1) / tMemClk;    tRCD = ( ((unsigned int)(tdata->spd_tRCD))   + tMemClk-1) / tMemClk;       /* tWR is the write recovery time, a constant of 15ns for DDR DIMMs. */    tWR  = ( ((unsigned int) 15)*4               + tMemClk-1) / tMemClk;    /*      * Check for registered DIMMs, or if we are "forcing" registered     * DIMMs, as might be the case of regular unregistered DIMMs     * behind an external register.     */    switch (mc->dramtype) {	case FCRAM:	    /* For FCRAMs, tCwD is always caslatency - 1  */	    tCwD = (caslatency >> 1) - 1; 	    tRCD = 1;		/* always 1 for FCRAM */	    tRP = 1;		/* always 1 for FCRAM */	    break;	default:	    /* Otherwise calculate based on registered attribute */	    if ((tdata->spd_attributes & JEDEC_ATTRIB_REG) ||		(mc->flags & MCFLG_FORCEREG)) {  	/* registered DIMM */		tCwD = 2; 		tCL++;		}	    else {			/* standard unbuffered DIMM */		tCwD = 1;		}	    break;	}    /*     * tWTR should be 1 tick unless we're actually using     * CAS Latency 1.5 (unlikely) or memory runs faster than     * 166MHz (tCK = 6.0ns or less)     *      * CAS Latency is stored in "halves", so 3 means "1.5"      */    tWTR = 1;    if ((caslatency == 3) || (spd_tCK_25 <= 60)) tWTR = 2;    /*     * Okay, using this info, figure out tRCw,tRCr.     */    tRCw = tRCD + tCwD + BURSTLEN/2 + tWR + tRP;    tRCr = tRCD + (caslatency>>1) + BURSTLEN/2 + tRP;    /*     * Calculate tRFC if the SPD did not specify it.  Use the DIMM's     * actual rated speed, spd_tCK_25.  Remember that spd_tCK_25 is in     * tenths of nanoseconds, and tMemClk is in fixed-6.2 format,     * but the SPD value itself is in nanoseconds (no tenths).     *     * Use the value from the first expression below that matches:     *     *    100Mhz or less  [10.0ns or more]  -- tRFC = 80ns     *    133Mhz or less  [7.5ns or more]   -- tRFC = 75ns     *    166Mhz or less  [6.0ns or more]   -- tRFC = 72ns     *    All others:                       -- tRFC = 70ns     *     * Special case for gigabit parts: always use 120ns [see JEDEC spec]     *      * Note: the calculation may cause tRFC to overflow the 4-bit field     * that we have allocated for it.  If that happens, reduce memory     * speed and try again.  Hopefully we won't go into a loop.     */    if (tdata->spd_tRFC == 0) {	unsigned int calcRFC;	/* in nanoseconds */	if (tdata->rows >= 14) {	/* Gigabit parts have >= 14 rows */	    calcRFC = 120;	    } 	else {	    if (spd_tCK_25 >= 100)     calcRFC = 80;	/* 100MHz */	    else if (spd_tCK_25 >= 75) calcRFC = 75;	/* 133MHz */	    else if (spd_tCK_25 >= 60) calcRFC = 72;	/* 166MHz */	    else calcRFC = 70;				/* Others */	    }	tRFC = (calcRFC*4 + tMemClk-1) / tMemClk;	/* 	 * if tRFC is greater than 48,	 * then we need to slow the memory down.	 */	if (tRFC > 48) {#ifdef _MCSTANDALONE_NOISY_	    printf("DRAM: tRFC too big, reducing memory speed\n");#endif	    clk_ratio++;	    goto new_ratio;			/* yikes! */	    }	}    else {	tRFC = ( ((unsigned int) tdata->spd_tRFC)*4 + tMemClk-1) / tMemClk;	}#if _BCM1480_S0_WORKAROUNDS_    /*     *  XXX Override some values for ddr2 (Micron MT47H32M8-37E 256Mb)     *			       * 	tRFC=19@250 15@200 14@175 12@150 10@125 (75ns)     *  tCL=3 caslat=3     *	tCwD=caslat-1 (2) (write latency) @200     *	tWR=4@250 3@200 3@175 3@150 2@125 (15nc)      *	tRP=4@250 3@200 3@175 3@150 2@125 (15ns)     *	tRRD=2@250 2@200 2@175 2@150 2@125 (7.5ns)     *	tRCD=4@250 3@200 3@175 3@150 2@125 (15ns)     *     * 	tRCw=16@250 13@200 13@175 11@150 9@125      * 	tRCr=14@250 11@200 11@175 9@150  7@125 (55ns)     *         * 	tFIFO=1; tCrDh=0 ; r2wIdle=1;     * 	w2rIdle=1; r2rIdle=1;     *     * XXX Set it for 150 MClk @ cas latency 3     */    if(mc->dramtype == JEDEC_DDR2) {	tRFC=12; tCL=3; tCwD=2; tWR=3; tRP=3; tRRD=2; tRCD=3;	tRCw=11; tRCr=9;	tFIFO=1; tCrDh=0; r2wIdle=1;	w2rIdle=1; r2rIdle=1;	mc->tWR = tWR; /* DDR2 part requires tWR. See bcm1480_jedec_ddr2_initcmds */	}#endif    /*     * Finally, put it all together in the timing register.     */    timing1 = V_BCM1480_MC_tRCD(tRCD) |	V_BCM1480_MC_tCL(tCL) |	(tCrDh ? M_BCM1480_MC_tCrDh : 0) |	V_BCM1480_MC_tWR(tWR) |	V_BCM1480_MC_tCwD(tCwD) |	V_BCM1480_MC_tRP(tRP) |	V_BCM1480_MC_tRRD(tRRD) |	V_BCM1480_MC_tRCw(tRCw) |	V_BCM1480_MC_tRCr(tRCr) |	V_BCM1480_MC_tRFC(tRFC) |	V_BCM1480_MC_tFIFO(tFIFO) |	V_BCM1480_MC_tR2W(r2wIdle) |	V_BCM1480_MC_tW2R(w2rIdle) |	(r2rIdle ? M_BCM1480_MC_tR2R : 0);    base = PHYS_TO_K1(A_BCM1480_MC_BASE(mcidx));    WRITECSR(base+R_BCM1480_MC_TIMING1,timing1);    /*     * Set the clk_ratio and refresh rate in memory clock config register.     */    mclkcfg = V_BCM1480_MC_CLK_RATIO(clk_ratio) |	V_BCM1480_MC_REF_RATE(refrate);    WRITECSR(base+R_BCM1480_MC_MCLK_CFG,mclkcfg);    /*     * Memory DLL config and memory drive config registers.     */    WRITECSR(base+R_BCM1480_MC_DLL_CFG,mc->dllcfg);    WRITECSR(base+R_BCM1480_MC_DRIVE_CFG,mc->drvcfg);    /*     * In the case of 64-bit channels, do the same things on the     * "ganged" channel so that they'll have the same timing.     */    if (mc->chantype == MC_64BIT_CHAN) {	base = PHYS_TO_K1(A_BCM1480_MC_BASE(mcidx+2));	WRITECSR(base+R_BCM1480_MC_TIMING1,timing1);	WRITECSR(base+R_BCM1480_MC_MCLK_CFG,mclkcfg);	WRITECSR(base+R_BCM1480_MC_DLL_CFG,mc->dllcfg);	WRITECSR(base+R_BCM1480_MC_DRIVE_CFG,mc->drvcfg);	}}/*  *********************************************************************    *  BCM1480_MANUAL_TIMING(mcidx,mc)    *      *  Program the timing registers, for the case of user-specified    *  timing parameters (don't calculate values based on datasheet    *  values, just stuff the info into the MC registers)    *      *  Input parameters:     *  	   mcidx - memory controller index    *  	   mc - memory controller data    *  	       *  Return value:    *  	   nothing    ********************************************************************* */static void bcm1480_manual_timing(int mcidx,mcdata_t *mc){    unsigned int plldiv;    unsigned int clk_ratio;    unsigned int refrate;    unsigned int ref_freq;    unsigned int tCpuClk;    unsigned int tMemClk;    uint64_t timing1, mclkcfg;    sbport_t base;    /*     * We need our cpu clock for all sorts of things.     */#if defined(_FUNCSIM_)    plldiv = 16;		/* 800MHz CPU for functional simulation */#else    plldiv = G_BCM1480_SYS_PLL_DIV(READCSR(PHYS_TO_K1(A_SCD_SYSTEM_CFG)));#endif    if (plldiv == 0) {	/* XXX: should be common macro, also defaulted by boards' *_devs.c.  */	plldiv = 6;	}    /* See comments in auto_timing for details */    tCpuClk = 2000000/(BCM1480_REFCLK*plldiv);	/* tCpuClk is in picoseconds */    /* Compute MAX(MIN_tMEMCLK,spd_tCK_25) */    tMemClk = DECTO10THS(mc->tCK);    if (mc->mintmemclk > tMemClk) tMemClk = mc->mintmemclk;    clk_ratio = ((tMemClk*100) + tCpuClk - 1) / tCpuClk;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -