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

📄 bcm1480_draminit.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
		cs = &(mc->csdata[init->geom.geom_csel]);		cs->rows = init->geom.geom_rows;		cs->cols = init->geom.geom_cols;		cs->banks = init->geom.geom_banks;		cs->flags |= CS_PRESENT;			break;	    case MCR_SPD:		cs = &(mc->csdata[init->spd.spd_csel]);		bcm1480_dram_getinfo(init->spd.spd_smbuschan,				    init->spd.spd_smbusdev,				    mc,				    init->spd.spd_csel);		if (mc->dramtype == DRAM_TYPE_SPD) {		    /* Use the DRAM type we get from the SPD */		    if (cs->spd_dramtype == SPD_MEMTYPE_FCRAM){			mc->dramtype = FCRAM;			mc->pagepolicy = CLOSED;			if (mc->roundtrip == 0) mc->roundtrip = DEFAULT_MEMORY_ROUNDTRIP_TIME_FCRAM;			}		    else {			if(cs->spd_dramtype == SPD_MEMTYPE_DDR2){ 			    mc->dramtype = JEDEC_DDR2;			    }			else {			    mc->dramtype = JEDEC;			    }			if (mc->roundtrip == 0) mc->roundtrip = DEFAULT_MEMORY_ROUNDTRIP_TIME;					}		    }		/* 		 * The line below lets you put a MCR_MANTIMING record		 * before an MCR_SPD to work around some missing information		 * on certain DIMMs.   Normally you have only one or the		 * other.  		 */		mc->rfsh = cs->spd_rfsh;		/* XXX flags ignored */		break;	    case MCR_MANTIMING:		/* Manual timing - pick record up as bytes because we cannot		   guarantee the alignment of the "mtm_timing" field in our		   structure -- each row is 12 bytes, not good */		mc->rfsh = (uint16_t) init->mtm.mtm_rfsh;	/* units: JEDEC refresh value */		mc->tCK  = (uint16_t) init->mtm.mtm_tCK;	/* units: BCD, like SPD */		mc->mantiming =		    (((uint64_t) init->mtm.mtm_timing[0]) << 56) |		    (((uint64_t) init->mtm.mtm_timing[1]) << 48) |		    (((uint64_t) init->mtm.mtm_timing[2]) << 40) |		    (((uint64_t) init->mtm.mtm_timing[3]) << 32) |		    (((uint64_t) init->mtm.mtm_timing[4]) << 24) |		    (((uint64_t) init->mtm.mtm_timing[5]) << 16) |		    (((uint64_t) init->mtm.mtm_timing[6]) << 8) |		    (((uint64_t) init->mtm.mtm_timing[7]) << 0);		break;	    default:		break;	    }	init++;	}    /*     * Okay, now we've internalized all the data from the SPDs     * and/or the init table.     */    }/*  *********************************************************************    *  BCM1480_DRAMINIT_DELAY    *      *  This little routine delays at least 200 microseconds.    *      *  Input parameters:     *  	   nothing    *  	       *  Return value:    *  	   nothing.    *  	       *  Registers used:    *  	   tmp0,tmp1    ********************************************************************* *//* 200 microseconds = 5KHz, so delay 1GHz/5Khz = 200,000 cycles */#if defined(_FASTEMUL_) && !defined(_DENALI_)#define DRAMINIT_DELAY_CNT	"50"#else#define DRAMINIT_DELAY_CNT	 "(1000000000/5000)"#endif#if defined(_MCSTANDALONE_)#if defined(_MCSTANDALONE_NOISY_)#define DRAMINIT_DELAY()	printf("DELAY 200us\n");#define bcm1480_draminit_smalldelay(x) printf("DELAY 200 MCLKS\n");#else#define DRAMINIT_DELAY()		/* not running on a 1250, no delays */#define bcm1480_draminit_smalldelay(x)#endif#else#define DRAMINIT_DELAY() bcm1480_draminit_delay()static void bcm1480_draminit_delay(void){    __asm("     li $9," DRAMINIT_DELAY_CNT " ; "	  "     mtc0 $0,$9 ; "	  "1:   mfc0 $8,$9 ; "	  "     .set push ; .set mips64 ; ssnop ; ssnop ; .set pop ;"	  "     blt $8,$9,1b ;");}static void bcm1480_draminit_smalldelay(uint64_t clks){    __asm __volatile ("     move $9,%0 ; "	  "     mtc0 $0,$9 ; "	  "1:   mfc0 $8,$9 ; "	  "     .set push ; .set mips64 ; ssnop ; ssnop ; .set pop ;"	  "     blt $8,$9,1b ;" :: "r"(clks));}#endif/*  *********************************************************************    *  MAKEDRAMMASK(dest,width,pos)    *      *  Create a 64-bit mask for the DRAM config registers    *      *  Input parameters:     *  	   width - number of '1' bits to set    *  	   pos - position (from the right) of the first '1' bit    *  	       *  Return value:    *  	   mask with specified with at specified position     ********************************************************************* */#define MAKEDRAMMASK(width,pos) _SB_MAKEMASK(width,pos)/*  *********************************************************************    *  BCM1480_JEDEC_DDR2_INITCMDS    *      *  Issue the sequence of DRAM init commands (JEDEC DDR2)    *      *  Input parameters:     *      mcnum - memory controller index (0/1/2/3)    *  	   mc - pointer to data for this memory controller    *	   csel - which chip select to send init commands for    *      lmbank - for largemem systems, the cs qualifiers to be    *		    output on CS[2:3]    *      tdata - chip select to use as a template for timing data    *  	       *  Return value:    *  	   nothing    ********************************************************************* */static void bcm1480_jedec_ddr2_initcmds(int mcnum,mcdata_t *mc,unsigned int csel,				  int lmbank,csdata_t *tdata){    uint64_t csmask;    sbport_t cmd;    sbport_t mode;    uint64_t modebits;    uint64_t casbits;    uint64_t wrbits;    uint64_t clk_ratio;    uint64_t plldiv;    uint64_t ns400;    /* clkratio = number of core clocks per mclk */    cmd = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_MCLK_CFG));    clk_ratio = G_BCM1480_MC_CLK_RATIO(READCSR(cmd));#if defined(_FUNCSIM_)    plldiv = 16;#else    plldiv = G_BCM1480_SYS_PLL_DIV(READCSR(PHYS_TO_K1(A_SCD_SYSTEM_CFG)));#endif    if (plldiv == 0) {	plldiv = 6;	}    /*     * During the init sequence we'll need to delay 400ns (or thereabouts).     * Calculate this from the system PLL setting     *     *    Freq(MHz) = reference_clock * plldiv / 2     *      * Now figure out how much 400ns is.  Since MHz is the same units as uSec,     * multiply by 1000 first.     *     *	 400ns = (400 * 1000) / Freq(Mhz)     */    ns400 = (400 * 1000) / (BCM1480_REFCLK * plldiv / 2);    csmask = csel << S_BCM1480_MC_CS0;	/* move mask to right place */    if (mc->flags & MCFLG_BIGMEM) {	/* 	 * so that the banks will all get their precharge signals,	 * put the CS qualifiers out on CS[2:3].	 */	   	csmask |= (uint64_t)(lmbank << 6);	}    cmd  = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_DRAMCMD));    mode = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_DRAMMODE));    /*     * Using the data in the timing template, figure out which     * CAS latency command to issue. Only whole CAS lat for DDR2.     */    casbits = 0;        if (mc->chantype == MC_64BIT_CHAN) {	/* Use 4-byte bursts for 64-bit channels */	switch (tdata->flags & CS_CASLAT_MASK) {	    case CS_CASLAT_40:		casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS4);		break;	    default:	    case CS_CASLAT_30:		casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS3);		break;	    case CS_CASLAT_20:		casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS2);		break;	    }	}    else if (mc->chantype == MC_32BIT_CHAN) {	/* Use 8-byte bursts for 32-bit channels */	switch (tdata->flags & CS_CASLAT_MASK) {	    case CS_CASLAT_40:		casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS4_BL8);	    default:	    case CS_CASLAT_30:		casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS3_BL8);		break;	    case CS_CASLAT_20:		casbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_CAS2_BL8);		break;	    }	}    switch (mc->tWR) {	case 4:	    wrbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_WR_4);	    break;	case 3:	    wrbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_WR_3);	    break;	case 2:	default:	    wrbits = V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_WR_2);	    break;	}        /*     * Set up for doing mode register writes to the SDRAMs     *      * First time, we set bit 8 to reset the DLL on MR     *      * Enable DLL on EMR     */    modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL) |	V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_DQS_DISABLE) |	V_BCM1480_MC_MODE(JEDEC_SDRAM_MRVAL_RESETDLL);    /*     * Bring the "bcm1480_draminit_smalldelay" routine into the ICache to     * prevent the refresh from interfering between power-down-clear and     * precharge.     */    bcm1480_draminit_smalldelay(1);    /*     * Remember to set the "ganged" bit properly if in 64-bit mode.     * Also, set the page policy here.     */    WRITECSR(mode,modebits | casbits | mc->modebits | wrbits);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_CLRPWRDN);    /*     * Wait 400ns.     */    bcm1480_draminit_smalldelay(ns400);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_PRE);    /*     * Also need to load EMR(2) and EMR(3). Currently no support on 1480 pass1     */    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_EMRS);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_MRS);        bcm1480_draminit_smalldelay(ns400);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_PRE);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_AR);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_AR);    /*     * This time, clear bit 8 to start the DLL     */    modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL) |	V_BCM1480_MC_MODE_DEFAULT;    WRITECSR(mode,modebits | casbits | mc->modebits | wrbits);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_MRS);    /*     * Enable OCD default by setting bits 7,8,and 9 on EMR.     */    modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_OCD_DEFAULT) |	V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_DQS_DISABLE);	         WRITECSR(mode,modebits | casbits | mc->modebits | wrbits);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_EMRS);    /*     * Enable OCD exit by clearing bits 7,8,and 9 on EMR.     */    modebits = V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL) |	V_BCM1480_MC_EMODE(JEDEC_SDRAM_EMRVAL_DQS_DISABLE);	     WRITECSR(mode,modebits | casbits | mc->modebits | wrbits);    WRITECSR(cmd,csmask | V_BCM1480_MC_COMMAND_EMRS);    }     /*  *********************************************************************    *  BCM1480_JEDEC_INITCMDS    *      *  Issue the sequence of DRAM init commands (JEDEC SDRAMs)    *      *  Input parameters:     *      mcnum - memory controller index (0/1/2/3)    *  	   mc - pointer to data for this memory controller    *	   csel - which chip select to send init commands for    *      lmbank - for largemem systems, the cs qualifiers to be    *		    output on CS[2:3]    *      tdata - chip select to use as a template for timing data    *  	       *  Return value:    *  	   nothing    ********************************************************************* */static void bcm1480_jedec_initcmds(int mcnum,mcdata_t *mc,unsigned int csel,				  int lmbank,csdata_t *tdata){    uint64_t csmask;    sbport_t cmd;    sbport_t mode;    uint64_t modebits;    uint64_t casbits;    uint64_t clk_ratio;    uint64_t plldiv;    uint64_t ns400;    /* clkratio = number of core clocks per mclk */    cmd = (sbport_t) PHYS_TO_K1(A_BCM1480_MC_REGISTER(mcnum,R_BCM1480_MC_MCLK_CFG));    clk_ratio = G_BCM1480_MC_CLK_RATIO(READCSR(cmd));#if defined(_FUNCSIM_)    plldiv = 16;#else    plldiv = G_BCM1480_SYS_PLL_DIV(READCSR(PHYS_TO_K1(A_SCD_SYSTEM_CFG)));#endif    if (plldiv == 0) {	plldiv = 6;	}    /*     * During the init sequence we'll need to delay 400ns (or thereabouts).     * Calculate this from the system PLL setting     *     *    Freq(MHz) = reference_clock * plldiv / 2     *      * Now figure out how much 400ns is.  Since MHz is the same units as uSec,     * multiply by 1000 first.     *     *	 400ns = (400 * 1000) / Freq(Mhz)     */    ns400 = (400 * 1000) / (BCM1480_REFCLK * plldiv / 2);    csmask = csel << S_BCM1480_MC_CS0;	/* move mask to right place */    if (mc->flags & MCFLG_BIGMEM) {	/* 	 * so that the banks will all get their precharge signals,	 * put the CS qualifier

⌨️ 快捷键说明

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