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

📄 sb1250_draminit.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
    WRITECSR(base+R_MC_TIMING1,timing1);#ifdef _VERILOG_    /* Smash in some defaults for Verilog simulation */    mclkcfg &= ~(M_MC_CLK_RATIO | M_MC_DLL_DEFAULT | M_MC_REF_RATE);    mclkcfg |= V_MC_CLK_RATIO_3X | V_MC_REF_RATE(K_MC_REF_RATE_200MHz) | 	V_MC_DLL_DEFAULT(0x18);#endif    WRITECSR(base+R_MC_MCLK_CFG,mclkcfg);}	/*  *********************************************************************    *  Default DRAM init table    *     *  This is just here to make SB1250 BSPs easier to write.    *  If you've hooked up standard JEDEC SDRAMs in a standard    *  way with all your SPD ROMs on one SMBus channel,    *  This table is for you.    *     *  Otherwise, copy it into your board_init.S file and     *  modify it, and return a pointer to the table from    *  the board_draminfo routine.    *    *  (See the CFE manual for more details)    ********************************************************************* */#if !defined(_MCSTANDALONE_)		/* no tables in the non-CFE, non-MIPS version */#ifdef _VERILOG_static const mc_initrec_t draminittab_11xx[5] /*__attribute__ ((section(".text"))) */ = {    /*     * Globals: No interleaving     */    DRAM_GLOBALS(MC_NOPORTINTLV),    /*     * Memory channel 0:  manually configure for verilog runs     * Configure chip select 0.     */    DRAM_CHAN_CFG(MC_CHAN0, 80, JEDEC, CASCHECK, BLKSIZE32, NOCSINTLV, ECCDISABLE, 0),    DRAM_CS_GEOM(MC_CS0, 12, 8, 2),    DRAM_CS_TIMING(DRT10(7,5), JEDEC_RFSH_64khz, JEDEC_CASLAT_25, 0,  45, DRT4(20,0), DRT4(15,0),  DRT4(20,0),  0, 0),    DRAM_EOT};static const mc_initrec_t draminittab_12xx[5] /* __attribute__ ((section(".text"))) */ = {    /*     * Globals: No interleaving     */    DRAM_GLOBALS(MC_NOPORTINTLV),    /*     * Memory channel 0:  manually configure for verilog runs     * Configure chip select 0.     */    DRAM_CHAN_CFG(MC_CHAN0, 80, JEDEC, CASCHECK, BLKSIZE32, NOCSINTLV, ECCDISABLE, 0),    DRAM_CS_GEOM(MC_CS0, 12, 8, 2),    DRAM_CS_TIMING(DRT10(7,5), JEDEC_RFSH_64khz, JEDEC_CASLAT_25, 0,  45, DRT4(20,0), DRT4(15,0),  DRT4(20,0),  0, 0),    DRAM_EOT};#else#define DEVADDR (CFG_DRAM_SMBUS_BASE)#define DEFCHAN (CFG_DRAM_SMBUS_CHANNEL)static const mc_initrec_t draminittab_12xx[8] /* __attribute__ ((section(".text"))) */ = {    /*     * Global data: Interleave mode from bsp_config.h     */    DRAM_GLOBALS(CFG_DRAM_INTERLEAVE),	   		/* do port interleaving if possible */    /*     * Memory channel 0: Configure via SMBUS, Automatic Timing     * Assumes SMBus device numbers are arranged such     * that the first two addresses are CS0,1 and CS2,3 on MC0     * and the second two addresses are CS0,1 and CS2,3 on MC1     */    DRAM_CHAN_CFG(MC_CHAN0, CFG_DRAM_MIN_tMEMCLK, DRAM_TYPE_SPD, CASCHECK, CFG_DRAM_BLOCK_SIZE, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, 0),    DRAM_CS_SPD(MC_CS0, 0, DEFCHAN, DEVADDR+0),	    DRAM_CS_SPD(MC_CS2, 0, DEFCHAN, DEVADDR+1),    /*     * Memory channel 1: Configure via SMBUS     */    DRAM_CHAN_CFG(MC_CHAN1, CFG_DRAM_MIN_tMEMCLK, DRAM_TYPE_SPD, CASCHECK, CFG_DRAM_BLOCK_SIZE, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, 0),    DRAM_CS_SPD(MC_CS0, 0, DEFCHAN, DEVADDR+2),	    DRAM_CS_SPD(MC_CS2, 0, DEFCHAN, DEVADDR+3),   /*    * End of Table    */    DRAM_EOT};static const mc_initrec_t draminittab_11xx[5] /*__attribute__ ((section(".text"))) */ = {    /*     * Global data: Interleave mode from bsp_config.h     */    DRAM_GLOBALS(0),	   		/* no port interleaving on 11xx */    /*     * Memory channel 1: Configure via SMBUS     */    DRAM_CHAN_CFG(MC_CHAN1, CFG_DRAM_MIN_tMEMCLK, DRAM_TYPE_SPD, CASCHECK, CFG_DRAM_BLOCK_SIZE, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, 0),    DRAM_CS_SPD(MC_CS0, 0, DEFCHAN, DEVADDR+0),	    DRAM_CS_SPD(MC_CS2, 0, DEFCHAN, DEVADDR+1),   /*    * End of Table    */    DRAM_EOT};#endif#endif/*  *********************************************************************    *  SB1250_SMBUS_INIT()    *      *  Initialize SMBUS channel     *      *  Input parameters:     *  	   chan - SMBus channel number, 0 or 1    *  	       *  Return value:    *  	   smbus_base - KSEG1 address of SMBus channel    *      *  Registers used:    *  	   tmp0    ********************************************************************* */static sbport_t sb1250_smbus_init(int chan){    sbport_t base;    base = PHYS_TO_K1(A_SMB_BASE(chan));    WRITECSR(base+R_SMB_FREQ,K_SMB_FREQ_100KHZ);    WRITECSR(base+R_SMB_CONTROL,0);    return base;}	/*  *********************************************************************    *  SB1250_SMBUS_WAITREADY()    *      *  Wait for SMBUS channel to be ready.    *      *  Input parameters:     *  	   smbus_base - SMBus channel base (K1seg addr)    *  	       *  Return value:    *  	   ret0 - 0 if no error occured, else -1    *      *  Registers used:    *  	   tmp0,tmp1    ********************************************************************* */static int sb1250_smbus_waitready(sbport_t base){    uint64_t status;    /*	     * Wait for busy bit to clear     */    for (;;) {	status = READCSR(base+R_SMB_STATUS);	if (!(status & M_SMB_BUSY)) break;	}    /*     * Isolate error bit and clear error status     */    status &= M_SMB_ERROR;    WRITECSR(base+R_SMB_STATUS,status);    /*     * Return status     */    return (status) ? -1 : 0;}/*  *********************************************************************    *  SB1250_SMBUS_READBYTE()    *      *  Read a byte from a serial ROM attached to an SMBus channel    *      *  Input parameters:     *      base - SMBus channel base address (K1seg addr)    *  	   dev - address of device on SMBUS    *      offset - address of byte within device on SMBUS    *  	       *  Return value:    *  	   byte from device (-1 indicates an error)    ********************************************************************* */static int sb1250_smbus_readbyte(sbport_t base,unsigned int dev,unsigned int offset){    int res;    /*     * Wait for channel to be ready     */    res = sb1250_smbus_waitready(base);    if (res < 0) return res;    /*     * Set up a READ BYTE command.  This command has no associated     * data field, the command code is the data      */    WRITECSR(base+R_SMB_CMD,offset);    WRITECSR(base+R_SMB_START,dev | V_SMB_TT(K_SMB_TT_CMD_RD1BYTE));    /*      * Wait for the command to complete     */    res = sb1250_smbus_waitready(base);    if (res < 0) return res;    /*     * Return the data byte     */    return (int) ((READCSR(base+R_SMB_DATA)) & 0xFF);}/*  *********************************************************************    *  SB1250_DRAM_GETINFO    *      *  Process a single init table entry and move data into the    *  memory controller's data structure.    *      *  Input parameters:     *	   smbase - points to base of SMbus device to read from    *  	   mc - memory controller data    *      init - pointer to current user init table entry    *  	       *  Return value:    *  	   nothing    ********************************************************************* */static void sb1250_dram_getinfo(unsigned int smbchan,				unsigned int smbdev,				mcdata_t *mc,				int chipsel){    int res;    unsigned char spd[JEDEC_SPD_SIZE];    int idx;    csdata_t *cs = &(mc->csdata[chipsel]);    sbport_t smbase;    smbase = sb1250_smbus_init(smbchan);    /*     * Read just the memory type to see if the RAM is present.     */    res = sb1250_smbus_readbyte(smbase,smbdev,JEDEC_SPD_MEMTYPE);    if ((res < 0) || ((res != JEDEC_MEMTYPE_DDRSDRAM) && 		      (res != JEDEC_MEMTYPE_DDRSDRAM2) &&	              (res != SPD_MEMTYPE_FCRAM))) {	return;			/* invalid or no memory installed */	}    /*     * Now go back and read everything.     */    res = 0;    for (idx = 0; idx < JEDEC_SPD_SIZE; idx++) {	res = sb1250_smbus_readbyte(smbase,smbdev,idx);	if (res < 0) break;	spd[idx] = res;	}    if (res < 0) return;		/* some SMBus error */    cs->rows = spd[JEDEC_SPD_ROWS];    cs->cols = spd[JEDEC_SPD_COLS];    /*     * Determine how many bits the banks represent.  Unlike     * the rows/columns, the bank byte says how *many* banks     * there are, not how many bits represent banks     */    switch (spd[JEDEC_SPD_BANKS]) {	case 2:					/* 2 banks = 1 bits */	    cs->banks = 1;	    break;	case 4:					/* 4 banks = 2 bits */	    cs->banks = 2;	    break;	case 8:					/* 8 banks = 3 bits */	    cs->banks = 3;	    break;	case 16:				/* 16 banks = 4 bits */	    cs->banks = 4;	    break;	default:				/* invalid bank count */	    return;	}    /*     * Read timing parameters from the DIMM.  By this time we kind of trust     */    cs->spd_dramtype   = spd[JEDEC_SPD_MEMTYPE];    cs->spd_tCK_25     = spd[JEDEC_SPD_tCK25];    cs->spd_tCK_20     = spd[JEDEC_SPD_tCK20];    cs->spd_tCK_10     = spd[JEDEC_SPD_tCK10];    cs->spd_rfsh       = spd[JEDEC_SPD_RFSH];    cs->spd_caslatency = spd[JEDEC_SPD_CASLATENCIES];    cs->spd_attributes = spd[JEDEC_SPD_ATTRIBUTES];    cs->spd_tRAS       = spd[JEDEC_SPD_tRAS];    cs->spd_tRP        = spd[JEDEC_SPD_tRP];    cs->spd_tRRD       = spd[JEDEC_SPD_tRRD];    cs->spd_tRCD       = spd[JEDEC_SPD_tRCD];    cs->spd_tRFC       = spd[JEDEC_SPD_tRFC];    cs->spd_tRC        = spd[JEDEC_SPD_tRC];    /*     * Okay, we got all the required data.  mark this CS present.     */    cs->flags = CS_PRESENT | CS_AUTO_TIMING;    /*     * If the module width is not 72 for any DIMM, disable ECC for this     * channel.  All DIMMs must support ECC for us to enable it.     */    if (spd[JEDEC_SPD_WIDTH] != 72) mc->flags &= ~MCFLG_ECC_ENABLE;    /*     * If it was a double-sided DIMM, also mark the odd chip select     * present.     */    if ((spd[JEDEC_SPD_SIDES] == 2) && !(mc->flags & MCFLG_BIGMEM)) {	csdata_t *oddcs = &(mc->csdata[chipsel | 1]);	oddcs->rows  = cs->rows;	oddcs->cols  = cs->cols;	oddcs->banks = cs->banks;	oddcs->flags = CS_PRESENT;	oddcs->spd_dramtype   = spd[JEDEC_SPD_MEMTYPE];	oddcs->spd_tCK_25     = spd[JEDEC_SPD_tCK25];	oddcs->spd_tCK_20     = spd[JEDEC_SPD_tCK20];	oddcs->spd_tCK_10     = spd[JEDEC_SPD_tCK10];	oddcs->spd_rfsh       = spd[JEDEC_SPD_RFSH];	oddcs->spd_caslatency = spd[JEDEC_SPD_CASLATENCIES];	oddcs->spd_attributes = spd[JEDEC_SPD_ATTRIBUTES];	oddcs->spd_tRAS       = spd[JEDEC_SPD_tRAS];	oddcs->spd_tRP        = spd[JEDEC_SPD_tRP];	oddcs->spd_tRRD       = spd[JEDEC_SPD_tRRD];	oddcs->spd_tRCD       = spd[JEDEC_SPD_tRCD];	oddcs->spd_tRFC       = spd[JEDEC_SPD_tRFC];	oddcs->spd_tRC        = spd[JEDEC_SPD_tRC];	}    else if ((spd[JEDEC_SPD_SIDES] > 2) && !(mc->flags & MCFLG_BIGMEM)	     && (chipsel == 0)) {		/* More than 2 chip selects on a single DIMM. Start from cs 1 */	csdata_t *loopcs;	int i;	for (i=chipsel+1;i<spd[JEDEC_SPD_SIDES];i++) {	    loopcs = &(mc->csdata[i]);	    loopcs->rows  = cs->rows;

⌨️ 快捷键说明

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